github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/access/rest/routes/collections_test.go (about) 1 package routes 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strings" 8 "testing" 9 10 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/status" 12 13 "github.com/onflow/flow-go/model/flow" 14 15 "github.com/stretchr/testify/assert" 16 mocks "github.com/stretchr/testify/mock" 17 18 "github.com/onflow/flow-go/access/mock" 19 "github.com/onflow/flow-go/utils/unittest" 20 ) 21 22 func getCollectionReq(id string, expandTransactions bool) *http.Request { 23 url := fmt.Sprintf("/v1/collections/%s", id) 24 if expandTransactions { 25 url = fmt.Sprintf("%s?expand=transactions", url) 26 } 27 28 req, _ := http.NewRequest("GET", url, nil) 29 return req 30 } 31 32 func TestGetCollections(t *testing.T) { 33 backend := &mock.API{} 34 35 t.Run("get by ID", func(t *testing.T) { 36 inputs := []flow.LightCollection{ 37 unittest.CollectionFixture(1).Light(), 38 unittest.CollectionFixture(10).Light(), 39 unittest.CollectionFixture(100).Light(), 40 } 41 42 for _, col := range inputs { 43 backend.Mock. 44 On("GetCollectionByID", mocks.Anything, col.ID()). 45 Return(&col, nil). 46 Once() 47 48 txs := make([]string, len(col.Transactions)) 49 for i, tx := range col.Transactions { 50 txs[i] = fmt.Sprintf("\"/v1/transactions/%s\"", tx.String()) 51 } 52 transactionsStr := fmt.Sprintf("[%s]", strings.Join(txs, ",")) 53 54 expected := fmt.Sprintf(`{ 55 "id":"%s", 56 "_links": { 57 "_self": "/v1/collections/%s" 58 }, 59 "_expandable": { 60 "transactions": %s 61 } 62 }`, col.ID(), col.ID(), transactionsStr) 63 64 req := getCollectionReq(col.ID().String(), false) 65 assertOKResponse(t, req, expected, backend) 66 mocks.AssertExpectationsForObjects(t, backend) 67 } 68 }) 69 70 t.Run("get by ID expand transactions", func(t *testing.T) { 71 col := unittest.CollectionFixture(3).Light() 72 73 transactions := make([]flow.TransactionBody, len(col.Transactions)) 74 for i := range col.Transactions { 75 transactions[i] = unittest.TransactionBodyFixture() 76 col.Transactions[i] = transactions[i].ID() // overwrite tx ids 77 78 backend.Mock. 79 On("GetTransaction", mocks.Anything, transactions[i].ID()). 80 Return(&transactions[i], nil). 81 Once() 82 } 83 84 backend.Mock. 85 On("GetCollectionByID", mocks.Anything, col.ID()). 86 Return(&col, nil). 87 Once() 88 89 req := getCollectionReq(col.ID().String(), true) 90 rr := executeRequest(req, backend) 91 92 assert.Equal(t, http.StatusOK, rr.Code) 93 // really hacky but we can't build whole response since it's really complex 94 // so we just make sure the transactions are included and have defined values 95 // anyhow we already test transaction responses in transaction tests 96 var res map[string]interface{} 97 err := json.Unmarshal(rr.Body.Bytes(), &res) 98 assert.NoError(t, err) 99 resTx := res["transactions"].([]interface{}) 100 for i, r := range resTx { 101 c := r.(map[string]interface{}) 102 assert.Equal(t, transactions[i].ID().String(), c["id"]) 103 assert.NotNil(t, c["envelope_signatures"]) 104 } 105 106 mocks.AssertExpectationsForObjects(t, backend) 107 }) 108 109 t.Run("get by ID errors out", func(t *testing.T) { 110 testID := unittest.IdentifierFixture() 111 tests := []struct { 112 id string 113 mockValue *flow.LightCollection 114 mockErr error 115 response string 116 status int 117 }{{ 118 testID.String(), 119 nil, 120 status.Error(codes.NotFound, "not found"), 121 `{"code":404,"message":"Flow resource not found: not found"}`, 122 http.StatusNotFound, 123 }, { 124 "invalidID", 125 nil, 126 nil, 127 `{"code":400,"message":"invalid ID format"}`, 128 http.StatusBadRequest, 129 }, 130 { 131 unittest.IdentifierFixture().String(), 132 nil, 133 status.Errorf(codes.Internal, "block not found"), 134 `{"code":400,"message":"Invalid Flow request: block not found"}`, 135 http.StatusBadRequest, 136 }, 137 } 138 139 for _, test := range tests { 140 id, err := flow.HexStringToIdentifier(test.id) 141 if err == nil { 142 // setup the backend mock ti return a not found error if this is a valid id 143 backend.Mock. 144 On("GetCollectionByID", mocks.Anything, id). 145 Return(test.mockValue, test.mockErr) 146 } 147 req := getCollectionReq(test.id, false) 148 assertResponse(t, req, test.status, test.response, backend) 149 } 150 }) 151 }