package api import ( "bytes" "database/sql" "encoding/json" "fmt" "io/ioutil" "net/http" "net/http/httptest" "testing" mockdb "git.nochill.in/nochill/naice_pos/db/mock" db "git.nochill.in/nochill/naice_pos/db/sqlc" "git.nochill.in/nochill/naice_pos/util" "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/stretchr/testify/require" ) func TestGetProductApi(t *testing.T) { product := randomProduct() testCases := []struct { name string productID string buildStubs func(store *mockdb.MockStore) checkResponse func(t *testing.T, recorder *httptest.ResponseRecorder) }{ { name: "OK", productID: product.ID.String(), buildStubs: func(store *mockdb.MockStore) { store.EXPECT(). GetProduct(gomock.Any(), gomock.Eq(product.ID)). Times(1). Return(product, nil) }, checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) { require.Equal(t, http.StatusOK, recorder.Code) requireBodyMatchAccount(t, recorder.Body, product) }, }, { name: "Not found", productID: product.ID.String(), buildStubs: func(store *mockdb.MockStore) { store.EXPECT(). GetProduct(gomock.Any(), gomock.Eq(product.ID)). Times(1). Return(db.Product{}, sql.ErrNoRows) }, checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) { require.Equal(t, http.StatusNotFound, recorder.Code) }, }, { name: "Internal Error", productID: product.ID.String(), buildStubs: func(store *mockdb.MockStore) { store.EXPECT(). GetProduct(gomock.Any(), gomock.Eq(product.ID)). Times(1). Return(db.Product{}, sql.ErrConnDone) }, checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) { require.Equal(t, http.StatusInternalServerError, recorder.Code) }, }, { name: "Bad request", productID: "0", buildStubs: func(store *mockdb.MockStore) { store.EXPECT(). GetProduct(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) { ctrl := gomock.NewController(t) defer ctrl.Finish() store := mockdb.NewMockStore(ctrl) tc.buildStubs(store) server := NewServer(store) recorder := httptest.NewRecorder() url := fmt.Sprintf("/product/%s", tc.productID) request, err := http.NewRequest(http.MethodGet, url, nil) require.NoError(t, err) server.router.ServeHTTP(recorder, request) tc.checkResponse(t, recorder) }) } } func randomProduct() db.Product { return db.Product{ ID: uuid.New(), MerchantID: uuid.MustParse("d9b0e126-991e-46ac-8c61-5efdd605f75d"), Name: util.RandomString(5), SellingPrice: util.RandomFloat(1000, 99999), PurchasePrice: util.RandomFloat(999, 9999), Stock: util.RandomFloat(100, 99999), } } func requireBodyMatchAccount(t *testing.T, body *bytes.Buffer, product db.Product) { data, err := ioutil.ReadAll(body) require.NoError(t, err) var gotProduct db.Product err = json.Unmarshal(data, &gotProduct) require.NoError(t, err) require.Equal(t, product, gotProduct) }