diff --git a/api/account_test.go b/api/account_test.go index c9b6d94..6892487 100644 --- a/api/account_test.go +++ b/api/account_test.go @@ -267,6 +267,157 @@ func TestCreateAccountAPI(t *testing.T) { } } +func TestListAccountsAPI(t *testing.T) { + user, _ := randomUser(t) + + n := 5 + accounts := make([]db.Account, n) + for i := 0; i < n; i++ { + accounts[i] = randomAccount(user.Username) + } + + type Query struct { + pageID int + pageSize int + } + + testCases := []struct { + name string + query Query + setupAuth func(t *testing.T, request *http.Request, tokenMaker token.Maker) + buildStubs func(store *mockdb.MockStore) + checkResponse func(recoder *httptest.ResponseRecorder) + }{ + { + name: "OK", + query: Query{ + pageID: 1, + pageSize: n, + }, + setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) { + addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute) + }, + buildStubs: func(store *mockdb.MockStore) { + arg := db.ListAccountsParams{ + Owner: user.Username, + Limit: int32(n), + Offset: 0, + } + + store.EXPECT(). + ListAccounts(gomock.Any(), gomock.Eq(arg)). + Times(1). + Return(accounts, nil) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusOK, recorder.Code) + requireBodyMatchAccounts(t, recorder.Body, accounts) + }, + }, + { + name: "NoAuthorization", + query: Query{ + pageID: 1, + pageSize: n, + }, + setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) { + }, + buildStubs: func(store *mockdb.MockStore) { + store.EXPECT(). + ListAccounts(gomock.Any(), gomock.Any()). + Times(0) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusUnauthorized, recorder.Code) + }, + }, + { + name: "InternalError", + query: Query{ + pageID: 1, + pageSize: n, + }, + setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) { + addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute) + }, + buildStubs: func(store *mockdb.MockStore) { + store.EXPECT(). + ListAccounts(gomock.Any(), gomock.Any()). + Times(1). + Return([]db.Account{}, sql.ErrConnDone) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusInternalServerError, recorder.Code) + }, + }, + { + name: "InvalidPageID", + query: Query{ + pageID: -1, + pageSize: n, + }, + setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) { + addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute) + }, + buildStubs: func(store *mockdb.MockStore) { + store.EXPECT(). + ListAccounts(gomock.Any(), gomock.Any()). + Times(0) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusBadRequest, recorder.Code) + }, + }, + { + name: "InvalidPageSize", + query: Query{ + pageID: 1, + pageSize: 100000, + }, + setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) { + addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute) + }, + buildStubs: func(store *mockdb.MockStore) { + store.EXPECT(). + ListAccounts(gomock.Any(), gomock.Any()). + Times(0) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusBadRequest, recorder.Code) + }, + }, + } + + for i := range testCases { + tc := testCases[i] + + t.Run(tc.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + store := mockdb.NewMockStore(ctrl) + tc.buildStubs(store) + + server := newTestServer(t, store) + recorder := httptest.NewRecorder() + + url := "/accounts" + request, err := http.NewRequest(http.MethodGet, url, nil) + require.NoError(t, err) + + // Add query parameters to request URL + q := request.URL.Query() + q.Add("page_id", fmt.Sprintf("%d", tc.query.pageID)) + q.Add("page_size", fmt.Sprintf("%d", tc.query.pageSize)) + request.URL.RawQuery = q.Encode() + + tc.setupAuth(t, request, server.tokenMaker) + server.router.ServeHTTP(recorder, request) + tc.checkResponse(recorder) + }) + } +} + func randomAccount(owner string) db.Account { return db.Account{ ID: util.RandomInt(1, 1000), @@ -285,3 +436,13 @@ func requireBodyMatchAccount(t *testing.T, body *bytes.Buffer, account db.Accoun require.NoError(t, err) require.Equal(t, account, gotAccount) } + +func requireBodyMatchAccounts(t *testing.T, body *bytes.Buffer, accounts []db.Account) { + data, err := io.ReadAll(body) + require.NoError(t, err) + + var gotAccounts []db.Account + err = json.Unmarshal(data, &gotAccounts) + require.NoError(t, err) + require.Equal(t, accounts, gotAccounts) +}