diff --git a/api/server.go b/api/server.go index 32d9614..17287bf 100644 --- a/api/server.go +++ b/api/server.go @@ -14,7 +14,7 @@ func NewServer(store db.Store) *Server { server := &Server{store: store} router := gin.Default() - router.POST("/merchants", server.createUser) + router.POST("/user/merchants", server.createUserMerchant) router.POST("/products", server.createProduct) router.PATCH("/products", server.updateProduct) router.GET("/product/:id", server.getProduct) diff --git a/api/user.go b/api/user.go index 1451e63..499e8a9 100644 --- a/api/user.go +++ b/api/user.go @@ -5,19 +5,20 @@ import ( "net/http" db "git.nochill.in/nochill/naice_pos/db/sqlc" + "git.nochill.in/nochill/naice_pos/util" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/lib/pq" ) -type createUserRequest struct { +type createUserMerchantRequest struct { Email string `json:"email" binding:"required,email"` Fullname string `json:"fullname" binding:"required"` Password string `json:"password" binding:"required"` OutletName string `json:"outlet_name" binding:"required"` } -type createUserResponse struct { +type createUserMerchantResponse struct { ID uuid.UUID `json:"id"` IndexID int64 `json:"index_id"` Email string `json:"email"` @@ -27,18 +28,23 @@ type createUserResponse struct { Outlet db.Merchant `json:"outlet"` } -func (server *Server) createUser(ctx *gin.Context) { - var req createUserRequest - +func (server *Server) createUserMerchant(ctx *gin.Context) { + var req createUserMerchantRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err)) return } + hashedPassword, err := util.HashPassword(req.Password) + if err != nil { + ctx.JSON(http.StatusInternalServerError, errorResponse(err)) + return + } + arg := db.UserMerchantTxParams{ Email: req.Email, Fullname: req.Fullname, - Password: req.Password, + Password: hashedPassword, OutletName: req.OutletName, } @@ -55,7 +61,7 @@ func (server *Server) createUser(ctx *gin.Context) { return } - res := createUserResponse{ + res := createUserMerchantResponse{ ID: user.OwnerProfile.ID, IndexID: user.OwnerProfile.IndexID, Email: user.OwnerProfile.Email, diff --git a/api/user_test.go b/api/user_test.go index 778f64e..10c4f13 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -1 +1,135 @@ package api + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/http/httptest" + "reflect" + "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/gin-gonic/gin" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" +) + +type eqCreateUserMerchantParamsMatcher struct { + arg db.UserMerchantTxParams + password string +} + +func (e eqCreateUserMerchantParamsMatcher) Matches(x interface{}) bool { + arg, ok := x.(db.UserMerchantTxParams) + if !ok { + return false + } + + err := util.CheckPassword(e.password, arg.Password) + if err != nil { + return false + } + + e.arg.Password = arg.Password + return reflect.DeepEqual(e.arg.Password, arg.Password) +} + +func (e eqCreateUserMerchantParamsMatcher) String() string { + return fmt.Sprintf("matches arg %v and password %v", e.arg, e.password) +} + +func EqCreateUserMerchant(arg db.UserMerchantTxParams, password string) gomock.Matcher { + return eqCreateUserMerchantParamsMatcher{arg, password} +} + +func TestCreateUserMerchantAPI(t *testing.T) { + userMerchant, password := RandomUser(t) + var userMerchantResult db.UserMerchantTxResult + // var userMerchantResponse createUserMerchantResponse + testCases := []struct { + name string + body gin.H + buildStubs func(store *mockdb.MockStore) + checkResponse func(recorder *httptest.ResponseRecorder) + }{ + { + name: "OK", + body: gin.H{ + "email": userMerchant.Email, + "fullname": userMerchant.Fullname, + "password": password, + "outlet_name": userMerchant.OutletName, + }, + buildStubs: func(store *mockdb.MockStore) { + arg := db.UserMerchantTxParams{ + Email: userMerchant.Email, + Fullname: userMerchant.Fullname, + OutletName: userMerchant.OutletName, + } + store.EXPECT(). + CreateUserMerchantTx(gomock.Any(), EqCreateUserMerchant(arg, password)). + Times(1). + Return(userMerchantResult, nil) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusOK, recorder.Code) + // requireBodyMatchUserMerchant(t, recorder.Body, userMerchantResponse) + }, + }, + } + + 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() + + data, err := json.Marshal(tc.body) + require.NoError(t, err) + + url := "/user/merchants" + request, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data)) + require.NoError(t, err) + + server.router.ServeHTTP(recorder, request) + tc.checkResponse(recorder) + + }) + } +} + +func RandomUser(t *testing.T) (userMerchant db.UserMerchantTxParams, password string) { + password = util.RandomString(6) + hashedPassword, err := util.HashPassword(password) + require.NoError(t, err) + + userMerchant = db.UserMerchantTxParams{ + Email: util.RandomEmail(), + Fullname: util.RandomString(5), + Password: hashedPassword, + OutletName: util.RandomString(10), + } + + return +} + +func requireBodyMatchUserMerchant(t *testing.T, body *bytes.Buffer, userMerchant createUserMerchantResponse) { + data, err := ioutil.ReadAll(body) + require.NoError(t, err) + + var gotUserMerchant db.UserMerchantTxParams + err = json.Unmarshal(data, &gotUserMerchant) + + require.NoError(t, err) +}