package api_test import ( "bytes" "fmt" "mime/multipart" "net/http" "net/http/httptest" "testing" "time" mockdb "git.nochill.in/nochill/hiling_go/db/mock" db "git.nochill.in/nochill/hiling_go/db/sqlc" "git.nochill.in/nochill/hiling_go/util" "github.com/jackc/pgx/v5/pgtype" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) func TestGetLocationsAPI(t *testing.T) { location := randomLocation() testCases := []struct { name string id int32 buildStubs func(store *mockdb.MockStore) checkResponse func(t *testing.T, recorder *httptest.ResponseRecorder) }{ { name: "OK", id: location.ID, buildStubs: func(store *mockdb.MockStore) { store.EXPECT(). GetLocation(gomock.Any(), gomock.Eq(location.ID)). Times(1). Return(location, nil) }, checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) { require.Equal(t, http.StatusOK, 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 := fmt.Sprintf("/location/%d", tc.id) request, err := http.NewRequest(http.MethodGet, url, nil) require.NoError(t, err) server.Router.ServeHTTP(recorder, request) tc.checkResponse(t, recorder) }) } } func TestCreateLocationAPI(t *testing.T) { location := db.CreateLocationParams{ Address: util.RandomString(10), Name: util.RandomString(10), SubmittedBy: 1, RegencyID: 1305, GoogleMapsLink: pgtype.Text{Valid: true, String: util.RandomString(10)}, } testCases := []struct { name string body db.CreateLocationParams buildStubs func(store *mockdb.MockStore) checkResponse func(t *testing.T, recorder *httptest.ResponseRecorder) }{ { name: "OK", body: location, buildStubs: func(store *mockdb.MockStore) { arg := db.CreateLocationParams{ Address: location.Address, Name: location.Name, SubmittedBy: location.SubmittedBy, RegencyID: location.RegencyID, GoogleMapsLink: location.GoogleMapsLink, } store.EXPECT(). CreateLocation(gomock.Any(), gomock.Eq(arg)). Times(1). Return(nil) }, checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) { require.Equal(t, http.StatusOK, recorder.Code) }, }, { name: "Bad Request", body: db.CreateLocationParams{}, buildStubs: func(store *mockdb.MockStore) { store.EXPECT(). CreateLocation(gomock.Any(), gomock.Any()). Times(0) }, checkResponse: func(t *testing.T, 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) { bodyBuffer := new(bytes.Buffer) mw := multipart.NewWriter(bodyBuffer) mw.WriteField("address", tc.body.Address) mw.WriteField("name", tc.body.Name) mw.WriteField("submitted_by", fmt.Sprintf("%d", tc.body.SubmittedBy)) mw.WriteField("regency_id", fmt.Sprintf("%d", tc.body.RegencyID)) mw.WriteField("google_maps_link", tc.body.GoogleMapsLink.String) mw.Close() ctrl := gomock.NewController(t) defer ctrl.Finish() store := mockdb.NewMockStore(ctrl) tc.buildStubs(store) server := newTestServer(t, store) recorder := httptest.NewRecorder() url := "/locations" request, err := http.NewRequest(http.MethodPost, url, bodyBuffer) request.Header.Set("Content-Type", mw.FormDataContentType()) require.NoError(t, err) server.Router.ServeHTTP(recorder, request) tc.checkResponse(t, recorder) }) } } func randomLocation() db.Location { return db.Location{ ID: int32(util.RandomInt(1, 20)), Address: util.RandomString(10), Name: util.RandomString(10), GoogleMapsLink: pgtype.Text{Valid: true, String: util.RandomString(20)}, SubmittedBy: 1, TotalVisited: pgtype.Int4{Valid: true, Int32: int32(util.RandomInt(0, 32))}, Thumbnail: pgtype.Text{Valid: false, String: ""}, RegencyID: 1305, IsDeleted: false, CreatedAt: pgtype.Timestamp{Valid: true, Time: time.Now()}, UpdatedAt: pgtype.Timestamp{Valid: true, Time: time.Now()}, ApprovedBy: pgtype.Int4{Valid: true, Int32: 1}, ApprovedAt: pgtype.Timestamp{Valid: true, Time: time.Now()}, } }