Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions api/v1/controller/generic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package controller

import (
"context"
"net/http"
"reflect"

"github.com/gin-gonic/gin"
"github.com/zetsux/gin-gorm-api-starter/support/base"
)

func HandleCreate[T any, R any](
ctx *gin.Context,
dto T,
createFunc func(context.Context, T) (R, error),
successMsg, failMsg string,
) {
if err := ctx.ShouldBind(&dto); err != nil {
msg := base.GetValidationErrorMessage(err, dto, failMsg)
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, msg, err))
return
}

result, err := createFunc(ctx, dto)
if err != nil {
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, failMsg, err))
return
}

ctx.JSON(http.StatusCreated, base.CreateSuccessResponse(
successMsg, http.StatusCreated, result))
}

func HandleGetAll[T any, R any](
ctx *gin.Context,
dto T,
getAllFunc func(context.Context, T) (R, base.PaginationResponse, error),
successMsg, failMsg string,
) {
if err := ctx.ShouldBind(&dto); err != nil {
msg := base.GetValidationErrorMessage(err, dto, failMsg)
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, msg, err))
return
}

results, pageMeta, err := getAllFunc(ctx, dto)
if err != nil {
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, failMsg, err))
return
}

if reflect.DeepEqual(pageMeta, base.PaginationResponse{}) {
ctx.JSON(http.StatusOK, base.CreateSuccessResponse(
successMsg, http.StatusOK, results,
))
} else {
ctx.JSON(http.StatusOK, base.CreatePaginatedResponse(
successMsg, http.StatusOK, results, pageMeta,
))
}
}

func HandleGetByID[R any](
ctx *gin.Context,
id string,
getByIDFunc func(context.Context, string) (R, error),
successMsg, failMsg string,
) {
result, err := getByIDFunc(ctx, id)
if err != nil {
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, failMsg, err))
return
}

ctx.JSON(http.StatusOK, base.CreateSuccessResponse(
successMsg, http.StatusOK, result,
))
}

func HandleUpdate[T any, R any](
ctx *gin.Context,
id string,
dto T,
updateFunc func(context.Context, T) (R, error),
successMsg, failMsg string,
) {
if err := ctx.ShouldBind(&dto); err != nil {
msg := base.GetValidationErrorMessage(err, dto, failMsg)
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, msg, err))
return
}

v := reflect.ValueOf(&dto).Elem()
if field := v.FieldByName("ID"); field.IsValid() && field.CanSet() && field.Kind() == reflect.String {
field.SetString(id)
}

result, err := updateFunc(ctx, dto)
if err != nil {
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, failMsg, err))
return
}

ctx.JSON(http.StatusOK, base.CreateSuccessResponse(
successMsg, http.StatusOK, result,
))
}

func HandleDelete(
ctx *gin.Context,
id string,
deleteFunc func(context.Context, string) error,
successMsg, failMsg string,
) {
err := deleteFunc(ctx, id)
if err != nil {
_ = ctx.Error(base.NewAppError(http.StatusBadRequest, failMsg, err))
return
}

ctx.JSON(http.StatusOK, base.CreateSuccessResponse(
successMsg, http.StatusOK, nil,
))
}
56 changes: 51 additions & 5 deletions api/v1/controller/tests/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/zetsux/gin-gorm-api-starter/api/v1/router"
"github.com/zetsux/gin-gorm-api-starter/core/helper/dto"
errs "github.com/zetsux/gin-gorm-api-starter/core/helper/errors"
"github.com/zetsux/gin-gorm-api-starter/core/helper/messages"
"github.com/zetsux/gin-gorm-api-starter/core/service"
"github.com/zetsux/gin-gorm-api-starter/support/base"
"github.com/zetsux/gin-gorm-api-starter/support/constant"
Expand Down Expand Up @@ -59,8 +60,8 @@ func (m *userServiceMock) DeleteUserByID(ctx context.Context, id string) error {
args := m.Called(ctx, id)
return args.Error(0)
}
func (m *userServiceMock) ChangePicture(ctx context.Context, req dto.UserChangePictureRequest, userID string) (dto.UserResponse, error) {
args := m.Called(ctx, req, userID)
func (m *userServiceMock) ChangePicture(ctx context.Context, req dto.UserChangePictureRequest) (dto.UserResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(dto.UserResponse), args.Error(1)
}
func (m *userServiceMock) DeletePicture(ctx context.Context, userID string) error {
Expand Down Expand Up @@ -117,6 +118,11 @@ func TestUserController_Register(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusCreated, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserRegisterSuccess, resp["message"])
}

func TestUserController_Login(t *testing.T) {
Expand All @@ -135,6 +141,11 @@ func TestUserController_Login(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserLoginSuccess, resp["message"])
}

func TestUserController_Login_Invalid(t *testing.T) {
Expand Down Expand Up @@ -170,6 +181,11 @@ func TestUserController_GetMe(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserFetchSuccess, resp["message"])
}

func TestUserController_GetMe_Unauthenticated(t *testing.T) {
Expand Down Expand Up @@ -199,6 +215,11 @@ func TestUserController_GetAllUsers(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUsersFetchSuccess, resp["message"])
}

func TestUserController_UpdateSelfName(t *testing.T) {
Expand All @@ -220,6 +241,11 @@ func TestUserController_UpdateSelfName(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserUpdateSuccess, resp["message"])
}

func TestUserController_UpdateUserByID(t *testing.T) {
Expand All @@ -241,6 +267,11 @@ func TestUserController_UpdateUserByID(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserUpdateSuccess, resp["message"])
}

func TestUserController_Delete(t *testing.T) {
Expand All @@ -256,6 +287,11 @@ func TestUserController_Delete(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserDeleteSuccess, resp["message"])
}

func TestUserController_ChangePicture(t *testing.T) {
Expand Down Expand Up @@ -283,16 +319,21 @@ func TestUserController_ChangePicture(t *testing.T) {
require.NoError(t, err)
fileHeader := req.MultipartForm.File["picture"][0]

changePicReq := dto.UserChangePictureRequest{Picture: fileHeader}
usm.On("ChangePicture", mock.Anything, changePicReq, uuidStr).Return(
changePicReq := dto.UserChangePictureRequest{ID: uuidStr, Picture: fileHeader}
usm.On("ChangePicture", mock.Anything, changePicReq).Return(
dto.UserResponse{ID: uuidStr}, nil,
)

usm.On("ChangePicture", mock.Anything, changePicReq, uuidStr).
usm.On("ChangePicture", mock.Anything, changePicReq).
Return(dto.UserResponse{ID: uuidStr, Name: "Updated"}, nil)

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserPictureUpdateSuccess, resp["message"])
}

func TestUserController_DeletePicture(t *testing.T) {
Expand All @@ -309,4 +350,9 @@ func TestUserController_DeletePicture(t *testing.T) {

r.ServeHTTP(w, req)
require.Equal(t, http.StatusOK, w.Code)

var resp map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
require.Equal(t, messages.MsgUserPictureDeleteSuccess, resp["message"])
}
Loading
Loading