naise_pos/api/product_test.go
2023-03-22 15:14:28 +07:00

253 lines
7.5 KiB
Go

package api
import (
"bytes"
"database/sql"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"time"
mockdb "git.nochill.in/nochill/naice_pos/db/mock"
db "git.nochill.in/nochill/naice_pos/db/sqlc"
"git.nochill.in/nochill/naice_pos/token"
"git.nochill.in/nochill/naice_pos/util"
"github.com/gin-gonic/gin"
"github.com/golang/mock/gomock"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
)
var MERCHANTID = "7e525a4b-4208-4f05-99a1-a75df475dd9b"
func TestGetProductApi(t *testing.T) {
product := randomProduct(MERCHANTID)
testCases := []struct {
name string
productID string
buildStubs func(store *mockdb.MockStore)
setupAuth func(t *testing.T, request *http.Request, tokenMaker token.Maker)
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)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusOK, recorder.Code)
},
},
{
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)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusNotFound, recorder.Code)
},
},
{
name: "Unauthorized",
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)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", uuid.New().String(), time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusNotFound, recorder.Code)
},
},
{
name: "NoAuthorization",
productID: product.ID.String(),
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
GetProduct(gomock.Any(), gomock.Any()).
Times(0)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusUnauthorized, 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)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
},
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)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
},
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 := newTestServer(t, store)
recorder := httptest.NewRecorder()
url := fmt.Sprintf("/api/product/%s", tc.productID)
request, err := http.NewRequest(http.MethodGet, url, nil)
require.NoError(t, err)
tc.setupAuth(t, request, server.tokenMaker)
server.router.ServeHTTP(recorder, request)
tc.checkResponse(t, recorder)
})
}
}
func TestCreateProductApi(t *testing.T) {
product := randomProduct(MERCHANTID)
testCases := []struct {
name string
body gin.H
buildStubs func(store *mockdb.MockStore)
setupAuth func(t *testing.T, request *http.Request, tokenMaker token.Maker)
checkResponse func(t *testing.T, recorder *httptest.ResponseRecorder)
}{
{
name: "OK",
body: gin.H{
"name": product.Name,
"selling_price": product.SellingPrice,
"purchase_price": product.PurchasePrice,
"product_type_id": product.ProductTypeID,
"product_category_id": product.ProductCategoryID,
"stock": product.Stock,
},
buildStubs: func(store *mockdb.MockStore) {
arg := db.CreateProductParams{
MerchantID: product.MerchantID,
Name: product.Name,
ProductTypeID: product.ProductTypeID,
SellingPrice: product.SellingPrice,
PurchasePrice: product.PurchasePrice,
ProductCategoryID: product.ProductCategoryID,
Stock: product.Stock,
}
store.EXPECT().
CreateProduct(gomock.Any(), gomock.Eq(arg)).
Times(1).
Return(product, nil)
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
},
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)
data, err := json.Marshal(tc.body)
require.NoError(t, err)
server := newTestServer(t, store)
recorder := httptest.NewRecorder()
url := "/api/products"
request, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data))
require.NoError(t, err)
tc.setupAuth(t, request, server.tokenMaker)
server.router.ServeHTTP(recorder, request)
tc.checkResponse(t, recorder)
})
}
}
func randomProduct(merchantID string) db.Product {
productCategory := createRandomProductCategory()
return db.Product{
ID: uuid.New(),
MerchantID: uuid.MustParse(MERCHANTID),
ProductTypeID: 1,
Name: util.RandomString(5),
SellingPrice: util.RandomFloat(1000, 99999),
PurchasePrice: util.RandomFloat(999, 9999),
ProductCategoryID: productCategory.ID,
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)
}