From 009a5c70aa72ce395beb9e587c35cc91602e4ac6 Mon Sep 17 00:00:00 2001 From: Damian-4chain Date: Thu, 17 Oct 2024 13:00:26 +0200 Subject: [PATCH 1/5] test(SPV-1079): add endpoint tests for get merkleroots --- .../get_merkleroots_endpoint_test.go | 163 ++++++++++++++++++ actions/merkleroots/merkleroots_test.go | 2 +- actions/merkleroots/routes.go | 3 +- actions/register.go | 2 +- .../assert_spvwallet_application.go | 6 + .../fixture_block_header_service.go | 123 +++++++++++++ .../fixture_spvwallet_application.go | 52 ++++++ .../internal/bhs/get_merkleroots_test.go | 108 ------------ models/page.go | 4 +- 9 files changed, 349 insertions(+), 114 deletions(-) create mode 100644 actions/merkleroots/get_merkleroots_endpoint_test.go create mode 100644 actions/testabilities/fixture_block_header_service.go delete mode 100644 engine/chain/internal/bhs/get_merkleroots_test.go diff --git a/actions/merkleroots/get_merkleroots_endpoint_test.go b/actions/merkleroots/get_merkleroots_endpoint_test.go new file mode 100644 index 00000000..07a9ba72 --- /dev/null +++ b/actions/merkleroots/get_merkleroots_endpoint_test.go @@ -0,0 +1,163 @@ +package merkleroots_test + +import ( + "encoding/json" + "testing" + + "github.com/bitcoin-sv/spv-wallet/actions/testabilities" + "github.com/bitcoin-sv/spv-wallet/engine/chain/errors" + "github.com/bitcoin-sv/spv-wallet/models" + "github.com/stretchr/testify/require" +) + +const merklerootsURL = "/api/v1/merkleroots" + +func TestGETMerkleRootsSuccess(t *testing.T) { + + testCases := map[string]struct { + query string + expectedResponse models.MerkleRootsBHSResponse + }{ + "Get MerkleRoots success no query params": { + query: "", + expectedResponse: models.MerkleRootsBHSResponse{ + Content: testabilities.MockedBHSData, + Page: models.ExclusiveStartKeyPageInfo{ + TotalElements: len(testabilities.MockedBHSData), + Size: len(testabilities.MockedBHSData), + LastEvaluatedKey: "", + }, + }, + }, + "Get MerkleRoots success with last evaluated key param": { + query: "?lastEvaluatedKey=df2b060fa2e5e9c8ed5eaf6a45c13753ec8c63282b2688322eba40cd98ea067a", + expectedResponse: models.MerkleRootsBHSResponse{ + Content: testabilities.MockedBHSData[5:], + Page: models.ExclusiveStartKeyPageInfo{ + TotalElements: len(testabilities.MockedBHSData), + Size: len(testabilities.MockedBHSData[5:]), + LastEvaluatedKey: "", + }, + }, + }, + } + + for name, tt := range testCases { + t.Run(name, func(t *testing.T) { + + // given + expResponseJSON, _ := json.Marshal(tt.expectedResponse) + given, then := testabilities.New(t) + cleanup := given.StartedSPVWallet() + defer cleanup() + url := merklerootsURL + + if tt.query != "" { + url = url + tt.query + } + + // and + client := given.HttpClient().ForUser() + + // when + res, err := client.R(). + SetHeader("Content-Type", "application/json"). + Get(url) + + // then + then.Response(res).IsOK().WithJSONf(string(expResponseJSON)) + require.NoError(t, err) + }) + } + +} + +func TestGETMerkleRootsFailure(t *testing.T) { + + testCases := map[string]struct { + bhsToken string + bhsURL string + expectErr models.SPVError + response string + responseCode int + batchSize string + lastEvaluatedKey string + }{ + "Get MerkleRoots with wrong batch size": { + bhsURL: merklerootsURL, + expectErr: chainerrors.ErrInvalidBatchSize, + responseCode: 400, + response: "{\"code\": \"ErrInvalidBatchSize\",\"message\": \"batchSize must be 0 or a positive integer\"}", + }, + "Get MerkleRoots with invalid merkleroot": { + bhsURL: merklerootsURL, + expectErr: chainerrors.ErrMerkleRootNotFound, + responseCode: 404, + response: "{\"code\": \"ErrMerkleRootNotFound\",\"message\": \"No block with provided merkleroot was found\"}", + }, + "Get MerkleRoots with stale merkleroot": { + bhsURL: merklerootsURL, + expectErr: chainerrors.ErrMerkleRootNotInLongestChain, + responseCode: 409, + response: "{\"code\": \"ErrMerkleRootNotInLC\",\"message\": \"Provided merkleroot is not part of the longest chain\"}", + }, + } + + for name, tt := range testCases { + t.Run(name, func(t *testing.T) { + // given + given, then := testabilities.New(t) + cleanup := given.StartedSPVWallet() + defer cleanup() + + // and + given.BHS().WillRespondForMerkleRoots(tt.responseCode, tt.response) + client := given.HttpClient().ForUser() + + // when + resErr := &models.ResponseError{} + res, _ := client.R(). + SetHeader("Content-Type", "application/json"). + SetError(resErr). + Get(tt.bhsURL) + + // then + then.Response(res).IsNotSuccess() + require.NotNil(t, resErr) + require.Equal(t, tt.expectErr.GetCode(), resErr.Code) + require.Equal(t, tt.expectErr.GetMessage(), resErr.Message) + }) + } + + t.Run("not allowed for anonymous", func(t *testing.T) { + // given: + given, then := testabilities.New(t) + cleanup := given.StartedSPVWallet() + defer cleanup() + + // and: + client := given.HttpClient().ForAnonymous() + + // when: + res, _ := client.R().Get(merklerootsURL) + + // then: + then.Response(res).IsUnauthorized() + }) + + t.Run("not allowed for admin", func(t *testing.T) { + // given: + given, then := testabilities.New(t) + cleanup := given.StartedSPVWallet() + defer cleanup() + + // and: + client := given.HttpClient().ForAdmin() + + // when: + res, _ := client.R().Get(merklerootsURL) + + // then: + then.Response(res).IsUnauthorizedForAdmin() + }) +} diff --git a/actions/merkleroots/merkleroots_test.go b/actions/merkleroots/merkleroots_test.go index 5d52d81b..5cc59665 100644 --- a/actions/merkleroots/merkleroots_test.go +++ b/actions/merkleroots/merkleroots_test.go @@ -29,7 +29,7 @@ func (ts *TestSuite) SetupTest() { ts.BaseSetupTest() handlersManager := handlers.NewManager(ts.Router, config.APIVersion) - RegisterRoutes(ts.AppConfig, handlersManager) + RegisterRoutes(handlersManager) } // TearDownTest runs after each test diff --git a/actions/merkleroots/routes.go b/actions/merkleroots/routes.go index 270482cc..4dd9a1f3 100644 --- a/actions/merkleroots/routes.go +++ b/actions/merkleroots/routes.go @@ -1,12 +1,11 @@ package merkleroots import ( - "github.com/bitcoin-sv/spv-wallet/config" "github.com/bitcoin-sv/spv-wallet/server/handlers" ) // RegisterRoutes creates the specific package routes -func RegisterRoutes(appConfig *config.AppConfig, handlersManager *handlers.Manager) { +func RegisterRoutes(handlersManager *handlers.Manager) { group := handlersManager.Group(handlers.GroupAPI, "/merkleroots") group.GET("", handlers.AsUser(get)) } diff --git a/actions/register.go b/actions/register.go index 9debd3b2..7315257a 100644 --- a/actions/register.go +++ b/actions/register.go @@ -25,7 +25,7 @@ func Register(appConfig *config.AppConfig, handlersManager *handlers.Manager) { utxos.RegisterRoutes(handlersManager) users.RegisterRoutes(handlersManager) sharedconfig.RegisterRoutes(handlersManager) - merkleroots.RegisterRoutes(appConfig, handlersManager) + merkleroots.RegisterRoutes(handlersManager) if appConfig.ExperimentalFeatures.PikeContactsEnabled { contacts.RegisterRoutes(handlersManager) } diff --git a/actions/testabilities/assert_spvwallet_application.go b/actions/testabilities/assert_spvwallet_application.go index a3743edf..7b08a6f5 100644 --- a/actions/testabilities/assert_spvwallet_application.go +++ b/actions/testabilities/assert_spvwallet_application.go @@ -19,6 +19,7 @@ type SPVWalletApplicationAssertions interface { type SPVWalletResponseAssertions interface { IsOK() SPVWalletResponseAssertions + IsNotSuccess() SPVWalletResponseAssertions WithJSONf(expectedFormat string, args ...any) // IsUnauthorized asserts that the response status code is 401 and the error is about lack of authorization. IsUnauthorized() @@ -63,6 +64,11 @@ func (a *responseAssertions) IsOK() SPVWalletResponseAssertions { return a.assertIsStatus(http.StatusOK) } +func (a *responseAssertions) IsNotSuccess() SPVWalletResponseAssertions { + a.assert.False(a.response.IsSuccess()) + return a +} + func (a *responseAssertions) IsBadRequest() SPVWalletResponseAssertions { return a.assertIsStatus(http.StatusBadRequest) } diff --git a/actions/testabilities/fixture_block_header_service.go b/actions/testabilities/fixture_block_header_service.go new file mode 100644 index 00000000..11cdafd4 --- /dev/null +++ b/actions/testabilities/fixture_block_header_service.go @@ -0,0 +1,123 @@ +package testabilities + +import ( + "slices" + + "github.com/bitcoin-sv/spv-wallet/models" +) + +// MockedBHSData is mocked merkle roots data on Block Header Service (BHS) side +var MockedBHSData = []models.MerkleRoot{ + { + BlockHeight: 0, + MerkleRoot: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", + }, + { + BlockHeight: 1, + MerkleRoot: "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", + }, + { + BlockHeight: 2, + MerkleRoot: "9b0fc92260312ce44e74ef369f5c66bbb85848f2eddd5a7a1cde251e54ccfdd5", + }, + { + BlockHeight: 3, + MerkleRoot: "999e1c837c76a1b7fbb7e57baf87b309960f5ffefbf2a9b95dd890602272f644", + }, + { + BlockHeight: 4, + MerkleRoot: "df2b060fa2e5e9c8ed5eaf6a45c13753ec8c63282b2688322eba40cd98ea067a", + }, + { + BlockHeight: 5, + MerkleRoot: "63522845d294ee9b0188ae5cac91bf389a0c3723f084ca1025e7d9cdfe481ce1", + }, + { + BlockHeight: 6, + MerkleRoot: "20251a76e64e920e58291a30d4b212939aae976baca40e70818ceaa596fb9d37", + }, + { + BlockHeight: 7, + MerkleRoot: "8aa673bc752f2851fd645d6a0a92917e967083007d9c1684f9423b100540673f", + }, + { + BlockHeight: 8, + MerkleRoot: "a6f7f1c0dad0f2eb6b13c4f33de664b1b0e9f22efad5994a6d5b6086d85e85e3", + }, + { + BlockHeight: 9, + MerkleRoot: "0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9", + }, + { + BlockHeight: 10, + MerkleRoot: "d3ad39fa52a89997ac7381c95eeffeaf40b66af7a57e9eba144be0a175a12b11", + }, + { + BlockHeight: 11, + MerkleRoot: "f8325d8f7fa5d658ea143629288d0530d2710dc9193ddc067439de803c37066e", + }, + { + BlockHeight: 12, + MerkleRoot: "3b96bb7e197ef276b85131afd4a09c059cc368133a26ca04ebffb0ab4f75c8b8", + }, + { + BlockHeight: 13, + MerkleRoot: "9962d5c704ec27243364cbe9d384808feeac1c15c35ac790dffd1e929829b271", + }, + { + BlockHeight: 14, + MerkleRoot: "e1afd89295b68bc5247fe0ca2885dd4b8818d7ce430faa615067d7bab8640156", + }, +} + +// LastMockedMerkleRoot returns last merkleroot value from MockedBHSData +func LastMockedMerkleRoot() models.MerkleRoot { + return MockedBHSData[len(MockedBHSData)-1] +} + +// mockedMerkleRootsAPIResponseFn is a mock of Block Header Service (BHS) get merkleroots endpoint +// it will return a paged response of merkle roots since last evaluated merkle root +func mockedMerkleRootsAPIResponseFn(lastMerkleRoot string) models.ExclusiveStartKeyPage[[]models.MerkleRoot] { + if lastMerkleRoot == "" { + return models.ExclusiveStartKeyPage[[]models.MerkleRoot]{ + Content: MockedBHSData, + Page: models.ExclusiveStartKeyPageInfo{ + LastEvaluatedKey: "", + TotalElements: len(MockedBHSData), + Size: len(MockedBHSData), + }, + } + } + + lastMerkleRootIdx := slices.IndexFunc(MockedBHSData, func(mr models.MerkleRoot) bool { + return mr.MerkleRoot == lastMerkleRoot + }) + + // handle case when lastMerkleRoot is already highest in the servers database + if lastMerkleRootIdx == len(MockedBHSData)-1 { + return models.ExclusiveStartKeyPage[[]models.MerkleRoot]{ + Content: []models.MerkleRoot{}, + Page: models.ExclusiveStartKeyPageInfo{ + LastEvaluatedKey: "", + TotalElements: len(MockedBHSData), + Size: 0, + }, + } + } + + content := MockedBHSData[lastMerkleRootIdx+1:] + lastEvaluatedKey := content[len(content)-1].MerkleRoot + + if lastEvaluatedKey == MockedBHSData[len(MockedBHSData)-1].MerkleRoot { + lastEvaluatedKey = "" + } + + return models.ExclusiveStartKeyPage[[]models.MerkleRoot]{ + Content: content, + Page: models.ExclusiveStartKeyPageInfo{ + LastEvaluatedKey: lastEvaluatedKey, + TotalElements: len(MockedBHSData), + Size: len(content), + }, + } +} diff --git a/actions/testabilities/fixture_spvwallet_application.go b/actions/testabilities/fixture_spvwallet_application.go index 39c4f9e3..154d9460 100644 --- a/actions/testabilities/fixture_spvwallet_application.go +++ b/actions/testabilities/fixture_spvwallet_application.go @@ -3,6 +3,9 @@ package testabilities import ( "context" "database/sql" + "encoding/json" + "fmt" + "net/http" "testing" "github.com/bitcoin-sv/spv-wallet/config" @@ -32,6 +35,18 @@ type SPVWalletApplicationFixture interface { // NewTest creates a new test fixture based on the current one and the provided testing.TB // This is useful if you want to start spv-wallet once and then run multiple t.Run with some calls against this one instance. NewTest(t testing.TB) SPVWalletApplicationFixture + + // BHS creates a new test fixture for Block Header Service (BHS) + BHS() BlockHeadersServiceFixture +} + +type BlockHeadersServiceFixture interface { + // WillRespondForMerkleRoots returns a http response for get merkleroots endpoint with + // provided httpCode and response + WillRespondForMerkleRoots(httpCode int, response string) + + // WithMockedGetMerkleRoots mocks the get merkleroots endpoint with apporximate method of what it does + WithMockedGetMerkleRoots() } type SPVWalletHttpClientFixture interface { @@ -137,6 +152,42 @@ func (f *appFixture) ForGivenUser(user fixtures.User) *resty.Client { return c } +func (f *appFixture) BHS() BlockHeadersServiceFixture { + return f +} + +func (f *appFixture) WillRespondForMerkleRoots(httpCode int, response string) { + responder := func(req *http.Request) (*http.Response, error) { + res := httpmock.NewStringResponse(httpCode, response) + res.Header.Set("Content-Type", "application/json") + + return res, nil + } + + f.externalTransport.RegisterResponder("GET", "http://localhost:8080/api/v1/chain/merkleroot", responder) +} + +func (f *appFixture) WithMockedGetMerkleRoots() { + responder := func(req *http.Request) (*http.Response, error) { + fmt.Print("\n\n\n" + req.Header.Get("Authorization") + "\n\n\n") + if req.Header.Get("Authorization") != "Bearer "+f.config.BHS.AuthToken { + return httpmock.NewStringResponse(http.StatusUnauthorized, ""), nil + } + lastEvaluatedKey := req.URL.Query().Get("lastEvaluatedKey") + merkleRoots := mockedMerkleRootsAPIResponseFn(lastEvaluatedKey) + resString, err := json.Marshal(merkleRoots) + + require.NoError(f.t, err) + + res := httpmock.NewStringResponse(200, string(resString)) + res.Header.Set("Content-Type", "application/json") + + return res, nil + } + + f.externalTransport.RegisterResponder("GET", "http://localhost:8080/api/v1/chain/merkleroot", responder) +} + func (f *appFixture) initialiseFixtures() { opts := f.engine.DefaultModelOptions(engine.WithMetadata("source", "fixture")) @@ -151,6 +202,7 @@ func (f *appFixture) initialiseFixtures() { } f.paymailClient.WillRespondWithP2PCapabilities() + f.WithMockedGetMerkleRoots() } // initDbConnection creates a new connection that will be used as connection for engine diff --git a/engine/chain/internal/bhs/get_merkleroots_test.go b/engine/chain/internal/bhs/get_merkleroots_test.go deleted file mode 100644 index 4bcfa45a..00000000 --- a/engine/chain/internal/bhs/get_merkleroots_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package bhs_test - -import ( - "context" - "encoding/json" - "net/url" - "testing" - - "github.com/bitcoin-sv/spv-wallet/engine/chain" - "github.com/bitcoin-sv/spv-wallet/engine/chain/errors" - "github.com/bitcoin-sv/spv-wallet/engine/chain/models" - "github.com/bitcoin-sv/spv-wallet/engine/tester" - "github.com/bitcoin-sv/spv-wallet/models" - "github.com/stretchr/testify/require" -) - -func TestGetMerkleRootsSuccess(t *testing.T) { - t.Run("Get MerkleRoots success", func(t *testing.T) { - response := "{\"content\": [ {\"merkleRoot\": \"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b\",\"blockHeight\": 0 },{ \"merkleRoot\": \"0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098\", \"blockHeight\": 1}, { \"merkleRoot\": \"9b0fc92260312ce44e74ef369f5c66bbb85848f2eddd5a7a1cde251e54ccfdd5\", \"blockHeight\": 2 }, { \"merkleRoot\": \"999e1c837c76a1b7fbb7e57baf87b309960f5ffefbf2a9b95dd890602272f644\", \"blockHeight\": 3 } ], \"page\": { \"totalElements\": 866322, \"size\": 4, \"lastEvaluatedKey\": \"999e1c837c76a1b7fbb7e57baf87b309960f5ffefbf2a9b95dd890602272f644\" }}" - httpClient := bhsMockMerkleRoots(200, response) - - var responseUnmarshalled *models.MerkleRootsBHSResponse - err := json.Unmarshal([]byte(response), &responseUnmarshalled) - require.NoError(t, err) - - service := chain.NewChainService(tester.Logger(t), httpClient, chainmodels.ARCConfig{}, bhsCfg(bhsURL, bhsToken)) - - merkleroots, err := service.GetMerkleRoots(context.Background(), url.Values{}) - - require.NoError(t, err) - require.Equal(t, responseUnmarshalled, merkleroots) - }) -} - -func TestGetMerkleRootsFailure(t *testing.T) { - errorTestCases := map[string]struct { - bhsToken string - bhsURL string - expectErr error - response string - responseCode int - batchSize string - lastEvaluatedKey string - }{ - "Get MerkleRoots with wrong token": { - bhsToken: "wrong-token", - bhsURL: bhsURL, - expectErr: chainerrors.ErrBHSUnauthorized, - responseCode: 400, - response: "{\"code\": \"error-unauthorized\",\"message\": \"unauthorized\"}", - batchSize: "", - lastEvaluatedKey: "", - }, - "Get MerkleRoots with wrong batch size": { - bhsToken: bhsToken, - bhsURL: bhsURL, - expectErr: chainerrors.ErrInvalidBatchSize, - responseCode: 400, - response: "{\"code\": \"ErrInvalidBatchSize\",\"message\": \"batchSize must be 0 or a positive integer\"}", - batchSize: "-2", - lastEvaluatedKey: "", - }, - "Get MerkleRoots with invalid merkleroot": { - bhsToken: bhsToken, - bhsURL: bhsURL, - expectErr: chainerrors.ErrMerkleRootNotFound, - responseCode: 404, - response: "{\"code\": \"ErrMerkleRootNotFound\",\"message\": \"No block with provided merkleroot was found\"}", - batchSize: "2", - lastEvaluatedKey: "invalid-merkleroot", - }, - "Get MerkleRoots with stale merkleroot": { - bhsToken: bhsToken, - bhsURL: bhsURL, - expectErr: chainerrors.ErrMerkleRootNotInLongestChain, - responseCode: 409, - response: "{\"code\": \"ErrMerkleRootNotInLC\",\"message\": \"Provided merkleroot is not part of the longest chain\"}", - batchSize: "2", - lastEvaluatedKey: "6ef51ab0d52991faf8f82e951a6ff9c40e6fdf1d56406067ff6882c6826323a5", - }, - "Get MerkleRoots with bad url": { - bhsToken: bhsToken, - bhsURL: "%bad-url" + bhsURL, - expectErr: chainerrors.ErrBHSBadURL, - responseCode: 0, - response: "", - batchSize: "", - lastEvaluatedKey: "", - }, - } - - for name, test := range errorTestCases { - t.Run(name, func(t *testing.T) { - httpClient := bhsMockMerkleRoots(test.responseCode, test.response) - - service := chain.NewChainService(tester.Logger(t), httpClient, chainmodels.ARCConfig{}, bhsCfg(test.bhsURL, test.bhsToken)) - urlQuery := url.Values{ - "lastEvaluatedKey": []string{test.lastEvaluatedKey}, - "batchSize": []string{test.batchSize}, - } - - _, err := service.GetMerkleRoots(context.Background(), urlQuery) - - require.Error(t, err) - require.ErrorIs(t, err, test.expectErr) - }) - } -} diff --git a/models/page.go b/models/page.go index 5428421a..eaa7c6e4 100644 --- a/models/page.go +++ b/models/page.go @@ -30,9 +30,9 @@ type SearchContactsResponse = PagedResponse[*Contact] // ExclusiveStartKeyPage represents a paginated response for database records using Exclusive Start Key paging type ExclusiveStartKeyPage[T any] struct { // List of records for the response - Content T + Content T `json:"content"` // Pagination details - Page ExclusiveStartKeyPageInfo + Page ExclusiveStartKeyPageInfo `json:"page"` } // ExclusiveStartKeyPageInfo represents the pagination information for limiting and sorting database query results From 3283088fdb81e002658d92b853ed2d216be071ba Mon Sep 17 00:00:00 2001 From: Damian-4chain Date: Thu, 17 Oct 2024 13:07:38 +0200 Subject: [PATCH 2/5] test(SPV-1079): rm print log --- actions/testabilities/fixture_spvwallet_application.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/actions/testabilities/fixture_spvwallet_application.go b/actions/testabilities/fixture_spvwallet_application.go index 154d9460..84e8d3ae 100644 --- a/actions/testabilities/fixture_spvwallet_application.go +++ b/actions/testabilities/fixture_spvwallet_application.go @@ -4,7 +4,6 @@ import ( "context" "database/sql" "encoding/json" - "fmt" "net/http" "testing" @@ -169,7 +168,6 @@ func (f *appFixture) WillRespondForMerkleRoots(httpCode int, response string) { func (f *appFixture) WithMockedGetMerkleRoots() { responder := func(req *http.Request) (*http.Response, error) { - fmt.Print("\n\n\n" + req.Header.Get("Authorization") + "\n\n\n") if req.Header.Get("Authorization") != "Bearer "+f.config.BHS.AuthToken { return httpmock.NewStringResponse(http.StatusUnauthorized, ""), nil } From 6bfc7cee2ea4ed6bc6ad9a7410cea3144e405c66 Mon Sep 17 00:00:00 2001 From: Damian-4chain Date: Thu, 17 Oct 2024 13:21:28 +0200 Subject: [PATCH 3/5] test(SPV-1079): happy linter --- .../fixture_spvwallet_application.go | 2 +- engine/chain/internal/bhs/bhs_mock_test.go | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/actions/testabilities/fixture_spvwallet_application.go b/actions/testabilities/fixture_spvwallet_application.go index 84e8d3ae..2bfbb08a 100644 --- a/actions/testabilities/fixture_spvwallet_application.go +++ b/actions/testabilities/fixture_spvwallet_application.go @@ -44,7 +44,7 @@ type BlockHeadersServiceFixture interface { // provided httpCode and response WillRespondForMerkleRoots(httpCode int, response string) - // WithMockedGetMerkleRoots mocks the get merkleroots endpoint with apporximate method of what it does + // WithMockedGetMerkleRoots mocks the get merkleroots endpoint with approximate method of what it does WithMockedGetMerkleRoots() } diff --git a/engine/chain/internal/bhs/bhs_mock_test.go b/engine/chain/internal/bhs/bhs_mock_test.go index 84a45d9c..bc184f04 100644 --- a/engine/chain/internal/bhs/bhs_mock_test.go +++ b/engine/chain/internal/bhs/bhs_mock_test.go @@ -44,23 +44,6 @@ func bhsMockVerify(response string, applyTimeout bool) *resty.Client { return client } -func bhsMockMerkleRoots(httpCode int, response string) *resty.Client { - transport := httpmock.NewMockTransport() - client := resty.New() - client.GetClient().Transport = transport - - responder := func(req *http.Request) (*http.Response, error) { - res := httpmock.NewStringResponse(httpCode, response) - res.Header.Set("Content-Type", "application/json") - - return res, nil - } - - transport.RegisterResponder("GET", fmt.Sprintf("%s/api/v1/chain/merkleroot", bhsURL), responder) - - return client -} - func bhsCfg(url, authToken string) chainmodels.BHSConfig { return chainmodels.BHSConfig{ URL: url, From 1ad47865fe6f6c2da86d81125624abc5257ba062 Mon Sep 17 00:00:00 2001 From: Damian-4chain Date: Fri, 18 Oct 2024 14:34:49 +0200 Subject: [PATCH 4/5] tests(SPV-1079): address CR --- .../get_merkleroots_endpoint_test.go | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/actions/merkleroots/get_merkleroots_endpoint_test.go b/actions/merkleroots/get_merkleroots_endpoint_test.go index 07a9ba72..baf0489f 100644 --- a/actions/merkleroots/get_merkleroots_endpoint_test.go +++ b/actions/merkleroots/get_merkleroots_endpoint_test.go @@ -7,11 +7,24 @@ import ( "github.com/bitcoin-sv/spv-wallet/actions/testabilities" "github.com/bitcoin-sv/spv-wallet/engine/chain/errors" "github.com/bitcoin-sv/spv-wallet/models" + "github.com/go-resty/resty/v2" "github.com/stretchr/testify/require" ) const merklerootsURL = "/api/v1/merkleroots" +func setupWalletAndClientForUser(t *testing.T, responseCode *int, response *string) (*testabilities.SPVWalletApplicationAssertions, func(), *resty.Client) { + given, then := testabilities.New(t) + cleanup := given.StartedSPVWallet() + client := given.HttpClient().ForUser() + + if response != nil && responseCode != nil { + given.BHS().WillRespondForMerkleRoots(*responseCode, *response) + } + + return &then, cleanup, client +} + func TestGETMerkleRootsSuccess(t *testing.T) { testCases := map[string]struct { @@ -46,9 +59,9 @@ func TestGETMerkleRootsSuccess(t *testing.T) { t.Run(name, func(t *testing.T) { // given - expResponseJSON, _ := json.Marshal(tt.expectedResponse) - given, then := testabilities.New(t) - cleanup := given.StartedSPVWallet() + expResponseJSON, err := json.Marshal(tt.expectedResponse) + require.NoError(t, err, "Failed to marshall expected response") + then, cleanup, client := setupWalletAndClientForUser(t, nil, nil) defer cleanup() url := merklerootsURL @@ -56,17 +69,14 @@ func TestGETMerkleRootsSuccess(t *testing.T) { url = url + tt.query } - // and - client := given.HttpClient().ForUser() - // when res, err := client.R(). SetHeader("Content-Type", "application/json"). Get(url) + require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") // then - then.Response(res).IsOK().WithJSONf(string(expResponseJSON)) - require.NoError(t, err) + (*then).Response(res).IsOK().WithJSONf(string(expResponseJSON)) }) } @@ -106,23 +116,19 @@ func TestGETMerkleRootsFailure(t *testing.T) { for name, tt := range testCases { t.Run(name, func(t *testing.T) { // given - given, then := testabilities.New(t) - cleanup := given.StartedSPVWallet() + then, cleanup, client := setupWalletAndClientForUser(t, &tt.responseCode, &tt.response) defer cleanup() - // and - given.BHS().WillRespondForMerkleRoots(tt.responseCode, tt.response) - client := given.HttpClient().ForUser() - // when resErr := &models.ResponseError{} - res, _ := client.R(). + res, err := client.R(). SetHeader("Content-Type", "application/json"). SetError(resErr). Get(tt.bhsURL) + require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") // then - then.Response(res).IsNotSuccess() + (*then).Response(res).IsNotSuccess() require.NotNil(t, resErr) require.Equal(t, tt.expectErr.GetCode(), resErr.Code) require.Equal(t, tt.expectErr.GetMessage(), resErr.Message) @@ -139,7 +145,8 @@ func TestGETMerkleRootsFailure(t *testing.T) { client := given.HttpClient().ForAnonymous() // when: - res, _ := client.R().Get(merklerootsURL) + res, err := client.R().Get(merklerootsURL) + require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") // then: then.Response(res).IsUnauthorized() @@ -155,7 +162,8 @@ func TestGETMerkleRootsFailure(t *testing.T) { client := given.HttpClient().ForAdmin() // when: - res, _ := client.R().Get(merklerootsURL) + res, err := client.R().Get(merklerootsURL) + require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") // then: then.Response(res).IsUnauthorizedForAdmin() From 1092c20db5f418ea752fadd0717bc10888cb2a8c Mon Sep 17 00:00:00 2001 From: Damian-4chain Date: Fri, 18 Oct 2024 15:28:04 +0200 Subject: [PATCH 5/5] refactor(SPV-1079): fix typo --- actions/merkleroots/get_merkleroots_endpoint_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/merkleroots/get_merkleroots_endpoint_test.go b/actions/merkleroots/get_merkleroots_endpoint_test.go index baf0489f..a40d5d44 100644 --- a/actions/merkleroots/get_merkleroots_endpoint_test.go +++ b/actions/merkleroots/get_merkleroots_endpoint_test.go @@ -73,7 +73,7 @@ func TestGETMerkleRootsSuccess(t *testing.T) { res, err := client.R(). SetHeader("Content-Type", "application/json"). Get(url) - require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") + require.NoError(t, err, "Unexpected error occurred while getting MerkleRoots") // then (*then).Response(res).IsOK().WithJSONf(string(expResponseJSON)) @@ -125,7 +125,7 @@ func TestGETMerkleRootsFailure(t *testing.T) { SetHeader("Content-Type", "application/json"). SetError(resErr). Get(tt.bhsURL) - require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") + require.NoError(t, err, "Unexpected error occurred while getting MerkleRoots") // then (*then).Response(res).IsNotSuccess() @@ -146,7 +146,7 @@ func TestGETMerkleRootsFailure(t *testing.T) { // when: res, err := client.R().Get(merklerootsURL) - require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") + require.NoError(t, err, "Unexpected error occurred while getting MerkleRoots") // then: then.Response(res).IsUnauthorized() @@ -163,7 +163,7 @@ func TestGETMerkleRootsFailure(t *testing.T) { // when: res, err := client.R().Get(merklerootsURL) - require.NoError(t, err, "Unexpected error occured while getting MerkleRoots") + require.NoError(t, err, "Unexpected error occurred while getting MerkleRoots") // then: then.Response(res).IsUnauthorizedForAdmin()