2023-03-12 11:01:43 +07:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"database/sql"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
2023-03-15 15:00:36 +07:00
|
|
|
"time"
|
2023-03-12 11:01:43 +07:00
|
|
|
|
|
|
|
mockdb "git.nochill.in/nochill/naice_pos/db/mock"
|
|
|
|
db "git.nochill.in/nochill/naice_pos/db/sqlc"
|
2023-03-15 15:00:36 +07:00
|
|
|
"git.nochill.in/nochill/naice_pos/token"
|
2023-03-12 11:01:43 +07:00
|
|
|
"git.nochill.in/nochill/naice_pos/util"
|
2023-03-16 20:37:20 +07:00
|
|
|
"github.com/gin-gonic/gin"
|
2023-03-12 11:01:43 +07:00
|
|
|
"github.com/golang/mock/gomock"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2023-03-22 13:40:18 +07:00
|
|
|
var MERCHANTID = "7e525a4b-4208-4f05-99a1-a75df475dd9b"
|
2023-03-16 20:37:20 +07:00
|
|
|
|
2023-03-12 11:01:43 +07:00
|
|
|
func TestGetProductApi(t *testing.T) {
|
2023-03-16 20:37:20 +07:00
|
|
|
product := randomProduct(MERCHANTID)
|
2023-03-12 11:01:43 +07:00
|
|
|
|
|
|
|
testCases := []struct {
|
|
|
|
name string
|
|
|
|
productID string
|
|
|
|
buildStubs func(store *mockdb.MockStore)
|
2023-03-15 15:00:36 +07:00
|
|
|
setupAuth func(t *testing.T, request *http.Request, tokenMaker token.Maker)
|
2023-03-12 11:01:43 +07:00
|
|
|
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)
|
|
|
|
},
|
2023-03-15 15:00:36 +07:00
|
|
|
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
|
2023-03-16 20:37:20 +07:00
|
|
|
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
|
2023-03-15 15:00:36 +07:00
|
|
|
},
|
2023-03-12 11:01:43 +07:00
|
|
|
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)
|
|
|
|
},
|
2023-03-15 15:00:36 +07:00
|
|
|
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
|
2023-03-16 20:37:20 +07:00
|
|
|
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
|
2023-03-15 15:00:36 +07:00
|
|
|
},
|
|
|
|
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)
|
|
|
|
},
|
2023-03-12 11:01:43 +07:00
|
|
|
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
|
|
|
|
require.Equal(t, http.StatusNotFound, recorder.Code)
|
|
|
|
},
|
|
|
|
},
|
2023-03-15 15:00:36 +07:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
},
|
|
|
|
},
|
2023-03-12 11:01:43 +07:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
},
|
2023-03-15 15:00:36 +07:00
|
|
|
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
|
2023-03-16 20:37:20 +07:00
|
|
|
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
|
2023-03-15 15:00:36 +07:00
|
|
|
},
|
2023-03-12 11:01:43 +07:00
|
|
|
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)
|
|
|
|
},
|
2023-03-15 15:00:36 +07:00
|
|
|
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
|
2023-03-16 20:37:20 +07:00
|
|
|
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "email", MERCHANTID, time.Minute)
|
2023-03-15 15:00:36 +07:00
|
|
|
},
|
2023-03-12 11:01:43 +07:00
|
|
|
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)
|
|
|
|
|
2023-03-14 17:39:40 +07:00
|
|
|
server := newTestServer(t, store)
|
2023-03-12 11:01:43 +07:00
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
|
2023-03-15 15:00:36 +07:00
|
|
|
url := fmt.Sprintf("/api/product/%s", tc.productID)
|
2023-03-12 11:01:43 +07:00
|
|
|
request, err := http.NewRequest(http.MethodGet, url, nil)
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-03-15 15:00:36 +07:00
|
|
|
tc.setupAuth(t, request, server.tokenMaker)
|
2023-03-12 11:01:43 +07:00
|
|
|
server.router.ServeHTTP(recorder, request)
|
|
|
|
tc.checkResponse(t, recorder)
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-16 20:37:20 +07:00
|
|
|
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,
|
2023-03-22 15:14:28 +07:00
|
|
|
"product_type_id": product.ProductTypeID,
|
2023-03-16 20:37:20 +07:00
|
|
|
"product_category_id": product.ProductCategoryID,
|
|
|
|
"stock": product.Stock,
|
|
|
|
},
|
|
|
|
buildStubs: func(store *mockdb.MockStore) {
|
|
|
|
arg := db.CreateProductParams{
|
|
|
|
MerchantID: product.MerchantID,
|
|
|
|
Name: product.Name,
|
2023-03-22 15:14:28 +07:00
|
|
|
ProductTypeID: product.ProductTypeID,
|
2023-03-16 20:37:20 +07:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-15 15:00:36 +07:00
|
|
|
func randomProduct(merchantID string) db.Product {
|
2023-03-16 20:37:20 +07:00
|
|
|
productCategory := createRandomProductCategory()
|
2023-03-12 11:01:43 +07:00
|
|
|
return db.Product{
|
2023-03-16 20:37:20 +07:00
|
|
|
ID: uuid.New(),
|
|
|
|
MerchantID: uuid.MustParse(MERCHANTID),
|
2023-03-22 15:14:28 +07:00
|
|
|
ProductTypeID: 1,
|
2023-03-16 20:37:20 +07:00
|
|
|
Name: util.RandomString(5),
|
|
|
|
SellingPrice: util.RandomFloat(1000, 99999),
|
|
|
|
PurchasePrice: util.RandomFloat(999, 9999),
|
|
|
|
ProductCategoryID: productCategory.ID,
|
|
|
|
Stock: util.RandomFloat(100, 99999),
|
2023-03-12 11:01:43 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|