diff --git a/src/app/dto/pet.dto.go b/src/app/dto/pet.dto.go index 2e0df1e..6455129 100644 --- a/src/app/dto/pet.dto.go +++ b/src/app/dto/pet.dto.go @@ -25,6 +25,30 @@ type PetResponse struct { Images []ImageResponse `json:"images"` } +type FindAllPetRequest struct { + Search string `json:"search"` + Type string `json:"type"` + Gender string `json:"gender"` + Color string `json:"color"` + Pattern string `json:"pattern"` + Age string `json:"age"` + Origin string `json:"origin"` + PageSize int `json:"page_size"` + Page int `json:"page"` +} + +type FindAllMetadata struct { + Page int `json:"page"` + TotalPages int `json:"total_pages"` + PageSize int `json:"page_size"` + Total int `json:"total"` +} + +type FindAllPetResponse struct { + Pets []*PetResponse `json:"pets"` + Metadata *FindAllMetadata `json:"metadata"` +} + type CreatePetRequest struct { Type string `json:"type" validate:"required"` Name string `json:"name" validate:"required"` diff --git a/src/app/handler/pet/pet.handler.go b/src/app/handler/pet/pet.handler.go index 7be8fdd..b9689c8 100644 --- a/src/app/handler/pet/pet.handler.go +++ b/src/app/handler/pet/pet.handler.go @@ -7,6 +7,7 @@ import ( "github.com/isd-sgcu/johnjud-gateway/src/app/constant" "github.com/isd-sgcu/johnjud-gateway/src/app/dto" "github.com/isd-sgcu/johnjud-gateway/src/app/router" + petUtils "github.com/isd-sgcu/johnjud-gateway/src/app/utils/pet" "github.com/isd-sgcu/johnjud-gateway/src/app/validator" imageSvc "github.com/isd-sgcu/johnjud-gateway/src/pkg/service/image" petSvc "github.com/isd-sgcu/johnjud-gateway/src/pkg/service/pet" @@ -33,7 +34,13 @@ func NewHandler(service petSvc.Service, imageService imageSvc.Service, validate // @Failure 503 {object} dto.ResponseServiceDownErr "Service is down" // @Router /v1/pets/ [get] func (h *Handler) FindAll(c router.IContext) { - response, respErr := h.service.FindAll() + queries := c.Queries() + request, err := petUtils.QueriesToFindAllDto(queries) + if err != nil { + c.JSON(http.StatusBadRequest, err) + } + + response, respErr := h.service.FindAll(request) if respErr != nil { c.JSON(respErr.StatusCode, respErr) return diff --git a/src/app/handler/pet/pet.handler_test.go b/src/app/handler/pet/pet.handler_test.go index 6cff0fc..e42dfbb 100644 --- a/src/app/handler/pet/pet.handler_test.go +++ b/src/app/handler/pet/pet.handler_test.go @@ -28,6 +28,9 @@ type PetHandlerTest struct { Pet *petProto.Pet Pets []*petProto.Pet PetDto *dto.PetResponse + QueriesMock map[string]string + Metadata *dto.FindAllMetadata + FindAllPetRequest *dto.FindAllPetRequest CreatePetRequest *dto.CreatePetRequest ChangeViewPetRequest *dto.ChangeViewPetRequest UpdatePetRequest *dto.UpdatePetRequest @@ -80,6 +83,13 @@ func (t *PetHandlerTest) SetupTest() { t.Pets = pets t.Pet = t.Pets[0] + t.Metadata = &dto.FindAllMetadata{ + Page: 1, + TotalPages: 1, + PageSize: len(t.Pets), + Total: len(t.Pets), + } + t.PetDto = &dto.PetResponse{ Id: t.Pet.Id, Type: t.Pet.Type, @@ -100,6 +110,20 @@ func (t *PetHandlerTest) SetupTest() { AdoptBy: t.Pet.AdoptBy, } + t.QueriesMock = map[string]string{ + "search": "", + "type": "", + "gender": "", + "color": "", + "pattern": "", + "age": "", + "origin": "", + "pageSize": "0", + "page": "0", + } + + t.FindAllPetRequest = &dto.FindAllPetRequest{} + t.CreatePetRequest = &dto.CreatePetRequest{} t.UpdatePetRequest = &dto.UpdatePetRequest{} @@ -134,7 +158,11 @@ func (t *PetHandlerTest) SetupTest() { func (t *PetHandlerTest) TestFindAllSuccess() { findAllResponse := utils.ProtoToDtoList(t.Pets, t.ImagesList) - expectedResponse := findAllResponse + metadataResponse := t.Metadata + expectedResponse := &dto.FindAllPetResponse{ + Pets: findAllResponse, + Metadata: metadataResponse, + } controller := gomock.NewController(t.T()) @@ -143,7 +171,8 @@ func (t *PetHandlerTest) TestFindAllSuccess() { validator := validatorMock.NewMockIDtoValidator(controller) context := routerMock.NewMockIContext(controller) - petSvc.EXPECT().FindAll().Return(findAllResponse, nil) + context.EXPECT().Queries().Return(t.QueriesMock) + petSvc.EXPECT().FindAll(t.FindAllPetRequest).Return(expectedResponse, nil) context.EXPECT().JSON(http.StatusOK, expectedResponse) handler := NewHandler(petSvc, imageSvc, validator) diff --git a/src/app/router/context.go b/src/app/router/context.go index 4d55e9d..55e4b1d 100644 --- a/src/app/router/context.go +++ b/src/app/router/context.go @@ -19,6 +19,7 @@ type IContext interface { Path() string StoreValue(string, string) Next() error + Queries() map[string]string } type FiberCtx struct { @@ -91,6 +92,10 @@ func (c *FiberCtx) StoreValue(k string, v string) { c.Locals(k, v) } +func (c *FiberCtx) Queries() map[string]string { + return c.Ctx.Queries() +} + //func (c *FiberCtx) Next() { // err := c.Ctx.Next() // fmt.Println(c.Route().Path) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 47a7c98..a18a682 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -24,11 +24,11 @@ func NewService(petClient petproto.PetServiceClient) *Service { } } -func (s *Service) FindAll() (result []*dto.PetResponse, err *dto.ResponseErr) { +func (s *Service) FindAll(in *dto.FindAllPetRequest) (result *dto.FindAllPetResponse, err *dto.ResponseErr) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - res, errRes := s.petClient.FindAll(ctx, &petproto.FindAllPetRequest{}) + res, errRes := s.petClient.FindAll(ctx, utils.FindAllDtoToProto(in)) if errRes != nil { st, _ := status.FromError(errRes) log.Error(). @@ -51,8 +51,13 @@ func (s *Service) FindAll() (result []*dto.PetResponse, err *dto.ResponseErr) { } } imagesList := utils.MockImageList(len(res.Pets)) - findAllResponse := utils.ProtoToDtoList(res.Pets, imagesList) - return findAllResponse, nil + findAllDto := utils.ProtoToDtoList(res.Pets, imagesList) + metaData := utils.MetadataProtoToDto(res.Metadata) + + return &dto.FindAllPetResponse{ + Pets: findAllDto, + Metadata: metaData, + }, nil } func (s *Service) FindOne(id string) (result *dto.PetResponse, err *dto.ResponseErr) { diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index ce29072..909b39d 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -23,13 +23,17 @@ type PetServiceTest struct { suite.Suite Pets []*petproto.Pet Pet *petproto.Pet + MetadataDto *dto.FindAllMetadata + MetadataProto *petproto.FindAllPetMetaData PetNotVisible *petproto.Pet + FindAllPetReq *petproto.FindAllPetRequest UpdatePetReq *petproto.UpdatePetRequest CreatePetReq *petproto.CreatePetRequest ChangeViewPetReq *petproto.ChangeViewPetRequest DeletePetReq *petproto.DeletePetRequest AdoptReq *petproto.AdoptPetRequest PetDto *dto.PetResponse + FindAllPetDto *dto.FindAllPetRequest CreatePetDto *dto.CreatePetRequest UpdatePetDto *dto.UpdatePetRequest NotFoundErr *dto.ResponseErr @@ -80,6 +84,20 @@ func (t *PetServiceTest) SetupTest() { pets = append(pets, pet) } + t.MetadataDto = &dto.FindAllMetadata{ + Page: 1, + TotalPages: 1, + PageSize: len(t.Pets), + Total: len(t.Pets), + } + + t.MetadataProto = &petproto.FindAllPetMetaData{ + Page: 1, + TotalPages: 1, + PageSize: int32(len(t.Pets)), + Total: int32(len(t.Pets)), + } + t.Pets = pets t.Pet = t.Pets[0] @@ -106,6 +124,18 @@ func (t *PetServiceTest) SetupTest() { t.PetDto = utils.ProtoToDto(t.Pet, t.Pet.Images) + t.FindAllPetDto = &dto.FindAllPetRequest{ + Search: "", + Type: "", + Gender: "", + Color: "", + Pattern: "", + Age: "", + Origin: "", + PageSize: len(t.Pets), + Page: 1, + } + t.CreatePetDto = &dto.CreatePetRequest{ Type: t.Pet.Type, Name: t.Pet.Name, @@ -146,6 +176,7 @@ func (t *PetServiceTest) SetupTest() { AdoptBy: t.Pet.AdoptBy, } + t.FindAllPetReq = utils.FindAllDtoToProto(t.FindAllPetDto) t.CreatePetReq = utils.CreateDtoToProto(t.CreatePetDto) t.UpdatePetReq = utils.UpdateDtoToProto(t.Pet.Id, t.UpdatePetDto) @@ -194,35 +225,39 @@ func (t *PetServiceTest) SetupTest() { } func (t *PetServiceTest) TestFindAllSuccess() { - protoReq := &petproto.FindAllPetRequest{} protoResp := &petproto.FindAllPetResponse{ - Pets: t.Pets, + Pets: t.Pets, + Metadata: t.MetadataProto, } - expected := utils.ProtoToDtoList(t.Pets, t.ImagesList) + findAllPPetsDto := utils.ProtoToDtoList(t.Pets, t.ImagesList) + metadataDto := t.MetadataDto + + expected := &dto.FindAllPetResponse{ + Pets: findAllPPetsDto, + Metadata: metadataDto, + } client := petmock.PetClientMock{} - client.On("FindAll", protoReq).Return(protoResp, nil) + client.On("FindAll", t.FindAllPetReq).Return(protoResp, nil) svc := NewService(&client) - actual, err := svc.FindAll() + actual, err := svc.FindAll(t.FindAllPetDto) assert.Nil(t.T(), err) assert.Equal(t.T(), expected, actual) } func (t *PetServiceTest) TestFindAllUnavailableServiceError() { - protoReq := &petproto.FindAllPetRequest{} - expected := t.UnavailableServiceErr clientErr := status.Error(codes.Unavailable, constant.UnavailableServiceMessage) client := petmock.PetClientMock{} - client.On("FindAll", protoReq).Return(nil, clientErr) + client.On("FindAll", t.FindAllPetReq).Return(nil, clientErr) svc := NewService(&client) - actual, err := svc.FindAll() + actual, err := svc.FindAll(t.FindAllPetDto) assert.Nil(t.T(), actual) assert.Equal(t.T(), expected, err) diff --git a/src/app/utils/pet/pet.utils.go b/src/app/utils/pet/pet.utils.go index b57c6a7..c768f29 100644 --- a/src/app/utils/pet/pet.utils.go +++ b/src/app/utils/pet/pet.utils.go @@ -1,7 +1,9 @@ package pet import ( + "errors" "fmt" + "strconv" "github.com/isd-sgcu/johnjud-gateway/src/app/dto" "github.com/isd-sgcu/johnjud-gateway/src/constant/pet" @@ -137,3 +139,73 @@ func extractImages(images []*imgproto.Image) []dto.ImageResponse { } return result } + +func FindAllDtoToProto(in *dto.FindAllPetRequest) *petproto.FindAllPetRequest { + return &petproto.FindAllPetRequest{ + Search: in.Search, + Type: in.Type, + Gender: in.Gender, + Color: in.Color, + Pattern: in.Pattern, + Age: in.Age, + Origin: in.Origin, + PageSize: int32(in.PageSize), + Page: int32(in.Page), + } +} + +func MetadataProtoToDto(in *petproto.FindAllPetMetaData) *dto.FindAllMetadata { + return &dto.FindAllMetadata{ + Page: int(in.Page), + TotalPages: int(in.TotalPages), + PageSize: int(in.PageSize), + Total: int(in.Total), + } +} + +func QueriesToFindAllDto(queries map[string]string) (*dto.FindAllPetRequest, error) { + request := &dto.FindAllPetRequest{ + Search: "", + Type: "", + Gender: "", + Color: "", + Pattern: "", + Age: "", + Origin: "", + PageSize: 0, + Page: 0, + } + + for q, v := range queries { + switch q { + case "search": + request.Search = v + case "type": + request.Type = v + case "gender": + request.Gender = v + case "color": + request.Color = v + case "pattern": + request.Pattern = v + case "age": + request.Age = v + case "origin": + request.Origin = v + case "pageSize": + pageSize, err := strconv.Atoi(v) + if err != nil { + return nil, errors.New("error pasring pageSize") + } + request.PageSize = pageSize + case "page": + page, err := strconv.Atoi(v) + if err != nil { + return nil, errors.New("error pasring page") + } + request.Page = page + } + } + + return request, nil +} diff --git a/src/mocks/router/context.mock.go b/src/mocks/router/context.mock.go index df02a3c..9db2501 100644 --- a/src/mocks/router/context.mock.go +++ b/src/mocks/router/context.mock.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./src/app/router/context.go +// +// Generated by this command: +// +// mockgen -source ./src/app/router/context.go -destination ./src/mocks/router/context.mock.go +// // Package mock_router is a generated GoMock package. package mock_router @@ -34,7 +39,7 @@ func (m *MockIContext) EXPECT() *MockIContextMockRecorder { } // Bind mocks base method. -func (m *MockIContext) Bind(arg0 interface{}) error { +func (m *MockIContext) Bind(arg0 any) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Bind", arg0) ret0, _ := ret[0].(error) @@ -42,7 +47,7 @@ func (m *MockIContext) Bind(arg0 interface{}) error { } // Bind indicates an expected call of Bind. -func (mr *MockIContextMockRecorder) Bind(arg0 interface{}) *gomock.Call { +func (mr *MockIContextMockRecorder) Bind(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bind", reflect.TypeOf((*MockIContext)(nil).Bind), arg0) } @@ -63,13 +68,13 @@ func (mr *MockIContextMockRecorder) ID() *gomock.Call { } // JSON mocks base method. -func (m *MockIContext) JSON(arg0 int, arg1 interface{}) { +func (m *MockIContext) JSON(arg0 int, arg1 any) { m.ctrl.T.Helper() m.ctrl.Call(m, "JSON", arg0, arg1) } // JSON indicates an expected call of JSON. -func (mr *MockIContextMockRecorder) JSON(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockIContextMockRecorder) JSON(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "JSON", reflect.TypeOf((*MockIContext)(nil).JSON), arg0, arg1) } @@ -112,7 +117,7 @@ func (m *MockIContext) Param(arg0 string) (string, error) { } // Param indicates an expected call of Param. -func (mr *MockIContextMockRecorder) Param(arg0 interface{}) *gomock.Call { +func (mr *MockIContextMockRecorder) Param(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Param", reflect.TypeOf((*MockIContext)(nil).Param), arg0) } @@ -131,6 +136,20 @@ func (mr *MockIContextMockRecorder) Path() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Path", reflect.TypeOf((*MockIContext)(nil).Path)) } +// Queries mocks base method. +func (m *MockIContext) Queries() map[string]string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Queries") + ret0, _ := ret[0].(map[string]string) + return ret0 +} + +// Queries indicates an expected call of Queries. +func (mr *MockIContextMockRecorder) Queries() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Queries", reflect.TypeOf((*MockIContext)(nil).Queries)) +} + // Role mocks base method. func (m *MockIContext) Role() string { m.ctrl.T.Helper() @@ -152,7 +171,7 @@ func (m *MockIContext) StoreValue(arg0, arg1 string) { } // StoreValue indicates an expected call of StoreValue. -func (mr *MockIContextMockRecorder) StoreValue(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockIContextMockRecorder) StoreValue(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreValue", reflect.TypeOf((*MockIContext)(nil).StoreValue), arg0, arg1) } diff --git a/src/mocks/service/pet/pet.mock.go b/src/mocks/service/pet/pet.mock.go index d1689f4..35b82b0 100644 --- a/src/mocks/service/pet/pet.mock.go +++ b/src/mocks/service/pet/pet.mock.go @@ -1,5 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./src/pkg/service/pet/pet.service.go +// +// Generated by this command: +// +// mockgen -source ./src/pkg/service/pet/pet.service.go -destination ./src/mocks/service/pet/pet.mock.go +// // Package mock_pet is a generated GoMock package. package mock_pet @@ -7,8 +12,8 @@ package mock_pet import ( reflect "reflect" - gomock "github.com/golang/mock/gomock" dto "github.com/isd-sgcu/johnjud-gateway/src/app/dto" + gomock "github.com/golang/mock/gomock" ) // MockService is a mock of Service interface. @@ -44,7 +49,7 @@ func (m *MockService) Adopt(arg0 string, arg1 *dto.AdoptByRequest) (*dto.AdoptBy } // Adopt indicates an expected call of Adopt. -func (mr *MockServiceMockRecorder) Adopt(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) Adopt(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Adopt", reflect.TypeOf((*MockService)(nil).Adopt), arg0, arg1) } @@ -59,7 +64,7 @@ func (m *MockService) ChangeView(arg0 string, arg1 *dto.ChangeViewPetRequest) (* } // ChangeView indicates an expected call of ChangeView. -func (mr *MockServiceMockRecorder) ChangeView(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) ChangeView(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeView", reflect.TypeOf((*MockService)(nil).ChangeView), arg0, arg1) } @@ -74,7 +79,7 @@ func (m *MockService) Create(arg0 *dto.CreatePetRequest) (*dto.PetResponse, *dto } // Create indicates an expected call of Create. -func (mr *MockServiceMockRecorder) Create(arg0 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) Create(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockService)(nil).Create), arg0) } @@ -89,24 +94,24 @@ func (m *MockService) Delete(arg0 string) (*dto.DeleteResponse, *dto.ResponseErr } // Delete indicates an expected call of Delete. -func (mr *MockServiceMockRecorder) Delete(arg0 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) Delete(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockService)(nil).Delete), arg0) } // FindAll mocks base method. -func (m *MockService) FindAll() ([]*dto.PetResponse, *dto.ResponseErr) { +func (m *MockService) FindAll(arg0 *dto.FindAllPetRequest) (*dto.FindAllPetResponse, *dto.ResponseErr) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FindAll") - ret0, _ := ret[0].([]*dto.PetResponse) + ret := m.ctrl.Call(m, "FindAll", arg0) + ret0, _ := ret[0].(*dto.FindAllPetResponse) ret1, _ := ret[1].(*dto.ResponseErr) return ret0, ret1 } // FindAll indicates an expected call of FindAll. -func (mr *MockServiceMockRecorder) FindAll() *gomock.Call { +func (mr *MockServiceMockRecorder) FindAll(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindAll", reflect.TypeOf((*MockService)(nil).FindAll)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindAll", reflect.TypeOf((*MockService)(nil).FindAll), arg0) } // FindOne mocks base method. @@ -119,7 +124,7 @@ func (m *MockService) FindOne(arg0 string) (*dto.PetResponse, *dto.ResponseErr) } // FindOne indicates an expected call of FindOne. -func (mr *MockServiceMockRecorder) FindOne(arg0 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) FindOne(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindOne", reflect.TypeOf((*MockService)(nil).FindOne), arg0) } @@ -134,7 +139,7 @@ func (m *MockService) Update(arg0 string, arg1 *dto.UpdatePetRequest) (*dto.PetR } // Update indicates an expected call of Update. -func (mr *MockServiceMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockServiceMockRecorder) Update(arg0, arg1 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockService)(nil).Update), arg0, arg1) } diff --git a/src/pkg/service/pet/pet.service.go b/src/pkg/service/pet/pet.service.go index 9862eee..fbbe5bc 100644 --- a/src/pkg/service/pet/pet.service.go +++ b/src/pkg/service/pet/pet.service.go @@ -5,7 +5,7 @@ import ( ) type Service interface { - FindAll() ([]*dto.PetResponse, *dto.ResponseErr) + FindAll(*dto.FindAllPetRequest) (*dto.FindAllPetResponse, *dto.ResponseErr) FindOne(string) (*dto.PetResponse, *dto.ResponseErr) Create(*dto.CreatePetRequest) (*dto.PetResponse, *dto.ResponseErr) Update(string, *dto.UpdatePetRequest) (*dto.PetResponse, *dto.ResponseErr)