Skip to content

Commit

Permalink
likes and subs count
Browse files Browse the repository at this point in the history
  • Loading branch information
bocharovatd committed Dec 18, 2024
1 parent ae0b2bd commit a4e11ec
Show file tree
Hide file tree
Showing 38 changed files with 1,380 additions and 0 deletions.
2 changes: 2 additions & 0 deletions microservices/album/delivery.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ type Handlers interface {
DeleteFavoriteAlbum(response http.ResponseWriter, request *http.Request)
IsFavoriteAlbum(response http.ResponseWriter, request *http.Request)
GetFavoriteAlbums(response http.ResponseWriter, request *http.Request)
GetFavoriteAlbumsCount(response http.ResponseWriter, request *http.Request)
GetAlbumLikesCount(response http.ResponseWriter, request *http.Request)
}
57 changes: 57 additions & 0 deletions microservices/album/delivery/http/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,60 @@ func (handlers *albumHandlers) GetFavoriteAlbums(response http.ResponseWriter, r

response.WriteHeader(http.StatusOK)
}

func (handlers *albumHandlers) GetFavoriteAlbumsCount(response http.ResponseWriter, request *http.Request) {
requestID := request.Context().Value(utils.RequestIDKey{})
vars := mux.Vars(request)
userID, err := uuid.Parse(vars["userID"])
if err != nil {
handlers.logger.Error(fmt.Sprintf("Get '%s' wrong user id: %v", vars["userID"], err), requestID)
utils.JSONError(response, http.StatusBadRequest, "Wrong id value")
return
}

count, err := handlers.usecase.GetFavoriteAlbumsCount(request.Context(), userID)
if err != nil {
handlers.logger.Error(fmt.Sprintf("Failed to get favorite albums count: %v", err), requestID)
utils.JSONError(response, http.StatusInternalServerError, fmt.Sprintf("Failed to get favorite albums count: %v", err))
return
} else if count == 0 {
utils.JSONError(response, http.StatusNotFound, "No favorite albums were found")
return
}

response.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(response).Encode(map[string]uint64{"favoriteAlbumsCount": count}); err != nil {
handlers.logger.Error(fmt.Sprintf("Failed to encode favorite albums count: %v", err), requestID)
utils.JSONError(response, http.StatusInternalServerError, fmt.Sprintf("Failed to encode favorite albums count: %v", err))
return
}

response.WriteHeader(http.StatusOK)
}

func (handlers *albumHandlers) GetAlbumLikesCount(response http.ResponseWriter, request *http.Request) {
requestID := request.Context().Value(utils.RequestIDKey{})
vars := mux.Vars(request)
albumID, err := strconv.ParseUint(vars["albumID"], 10, 64)
if err != nil {
handlers.logger.Error(fmt.Sprintf("Invalid album ID: %v", err), requestID)
utils.JSONError(response, http.StatusBadRequest, fmt.Sprintf("Invalid album ID: %v", err))
return
}

likesCount, err := handlers.usecase.GetAlbumLikesCount(request.Context(), albumID)
if err != nil {
handlers.logger.Error("Failed to get album likes count", requestID)
utils.JSONError(response, http.StatusInternalServerError, "Can't check is album in favorite")
return
}

response.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(response).Encode(map[string]uint64{"albumLikesCount": likesCount}); err != nil {
handlers.logger.Error(fmt.Sprintf("Failed to encode: %v", err), requestID)
utils.JSONError(response, http.StatusInternalServerError, fmt.Sprintf("Failed to encode: %v", err))
return
}

response.WriteHeader(http.StatusOK)
}
136 changes: 136 additions & 0 deletions microservices/album/delivery/http/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,3 +632,139 @@ func TestAlbumHandlers_GetFavoriteAlbums(t *testing.T) {
assert.Contains(t, response.Body.String(), "No favorite albums were found")
})
}

func TestAlbumHandlers_GetFavoriteAlbumsCount(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

cfg := &config.Config{}
logger := logger.New(&cfg.Service.Logger)
usecaseMock := mocks.NewMockUsecase(ctrl)
albumHandlers := NewAlbumHandlers(usecaseMock, logger)

t.Run("Success", func(t *testing.T) {
userID := uuid.New()
count := uint64(2)

usecaseMock.EXPECT().GetFavoriteAlbumsCount(gomock.Any(), userID).Return(count, nil)

router := mux.NewRouter()
router.HandleFunc("/api/v1/albums/favorite/count/{userID:[0-9a-fA-F-]+}", albumHandlers.GetFavoriteAlbumsCount).Methods("GET")

request, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/albums/favorite/count/%s", userID.String()), nil)
assert.NoError(t, err)

response := httptest.NewRecorder()
router.ServeHTTP(response, request)

res := response.Result()
assert.Equal(t, http.StatusOK, res.StatusCode)

var result map[string]uint64
err = json.NewDecoder(res.Body).Decode(&result)
assert.NoError(t, err)
assert.Equal(t, count, result["favoriteAlbumsCount"])
})

t.Run("Wrong id value", func(t *testing.T) {
router := mux.NewRouter()
router.HandleFunc("/api/v1/albums/favorite/count/{userID:[0-9a-fA-F-]+}", albumHandlers.GetFavoriteAlbumsCount).Methods("GET")

request, err := http.NewRequest(http.MethodGet, "/api/v1/albums/favorite/count/123", nil)
assert.NoError(t, err)

response := httptest.NewRecorder()
router.ServeHTTP(response, request)

res := response.Result()
assert.Equal(t, http.StatusBadRequest, res.StatusCode)
assert.Contains(t, response.Body.String(), "Wrong id value")
})

t.Run("Error while getting favorite albums count", func(t *testing.T) {
userID := uuid.New()
mockError := fmt.Errorf("usecase error")
usecaseMock.EXPECT().GetFavoriteAlbumsCount(gomock.Any(), userID).Return(uint64(0), mockError)

router := mux.NewRouter()
router.HandleFunc("/api/v1/albums/favorite/count/{userID:[0-9a-fA-F-]+}", albumHandlers.GetFavoriteAlbumsCount).Methods("GET")

request, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/albums/favorite/count/%s", userID.String()), nil)
assert.NoError(t, err)

response := httptest.NewRecorder()
router.ServeHTTP(response, request)

res := response.Result()
assert.Equal(t, http.StatusInternalServerError, res.StatusCode)
assert.Contains(t, response.Body.String(), "Failed to get favorite albums count")
})
}

func TestAlbumHandlers_GetAlbumLikesCount(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

cfg := &config.Config{}
logger := logger.New(&cfg.Service.Logger)
usecaseMock := mocks.NewMockUsecase(ctrl)
albumHandlers := NewAlbumHandlers(usecaseMock, logger)

t.Run("Success", func(t *testing.T) {
albumID := uint64(123)
likesCount := uint64(10)

usecaseMock.EXPECT().GetAlbumLikesCount(gomock.Any(), albumID).Return(likesCount, nil)

router := mux.NewRouter()
router.HandleFunc("/api/v1/albums/likes/{albumID:[0-9]+}", albumHandlers.GetAlbumLikesCount).Methods("GET")

request, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/albums/likes/%d", albumID), nil)
assert.NoError(t, err)

response := httptest.NewRecorder()
router.ServeHTTP(response, request)

res := response.Result()
assert.Equal(t, http.StatusOK, res.StatusCode)

var result map[string]uint64
err = json.NewDecoder(res.Body).Decode(&result)
assert.NoError(t, err)
assert.Equal(t, likesCount, result["albumLikesCount"])
})

t.Run("Invalid album ID", func(t *testing.T) {
router := mux.NewRouter()
router.HandleFunc("/api/v1/albums/likes/{albumID}", albumHandlers.GetAlbumLikesCount).Methods("GET")

request, err := http.NewRequest(http.MethodGet, "/api/v1/albums/likes/abc", nil)
assert.NoError(t, err)

response := httptest.NewRecorder()
router.ServeHTTP(response, request)

res := response.Result()
assert.Equal(t, http.StatusBadRequest, res.StatusCode)
assert.Contains(t, response.Body.String(), "Invalid album ID")
})

t.Run("Error while getting album likes count", func(t *testing.T) {
albumID := uint64(123)
mockError := fmt.Errorf("usecase error")
usecaseMock.EXPECT().GetAlbumLikesCount(gomock.Any(), albumID).Return(uint64(0), mockError)

router := mux.NewRouter()
router.HandleFunc("/api/v1/albums/likes/{albumID:[0-9]+}", albumHandlers.GetAlbumLikesCount).Methods("GET")

request, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/albums/likes/%d", albumID), nil)
assert.NoError(t, err)

response := httptest.NewRecorder()
router.ServeHTTP(response, request)

res := response.Result()
assert.Equal(t, http.StatusInternalServerError, res.StatusCode)
assert.Contains(t, response.Body.String(), "Can't check is album in favorite")
})
}
10 changes: 10 additions & 0 deletions microservices/album/delivery/http/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ func BindRoutes(s *httpServer.Server, artistClient artistService.ArtistServiceCl
middleware.AuthMiddleware(&s.CFG.Service.Auth, s.Logger, http.HandlerFunc(albumHandleres.GetFavoriteAlbums)),
).Methods("GET")

s.MUX.Handle(
"/api/v1/albums/favorite/count/{userID:[0-9a-fA-F-]+}",
middleware.AuthMiddleware(&s.CFG.Service.Auth, s.Logger, http.HandlerFunc(albumHandleres.GetFavoriteAlbumsCount)),
).Methods("GET")

s.MUX.Handle(
"/api/v1/albums/favorite/{albumID:[0-9]+}",
middleware.AuthMiddleware(&s.CFG.Service.Auth, s.Logger, http.HandlerFunc(albumHandleres.IsFavoriteAlbum)),
Expand All @@ -42,4 +47,9 @@ func BindRoutes(s *httpServer.Server, artistClient artistService.ArtistServiceCl
"/api/v1/albums/favorite/{albumID:[0-9]+}",
middleware.AuthMiddleware(&s.CFG.Service.Auth, s.Logger, http.HandlerFunc(albumHandleres.DeleteFavoriteAlbum)),
).Methods("DELETE")

s.MUX.Handle(
"/api/v1/albums/likes/{albumID:[0-9]+}",
middleware.AuthMiddleware(&s.CFG.Service.Auth, s.Logger, http.HandlerFunc(albumHandleres.GetAlbumLikesCount)),
).Methods("GET")
}
30 changes: 30 additions & 0 deletions microservices/album/mock/repository_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions microservices/album/mock/usecase_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions microservices/album/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ type Repo interface {
DeleteFavoriteAlbum(ctx context.Context, userID uuid.UUID, albumID uint64) error
IsFavoriteAlbum(ctx context.Context, userID uuid.UUID, albumID uint64) (bool, error)
GetFavoriteAlbums(ctx context.Context, userID uuid.UUID) ([]*models.Album, error)
GetFavoriteAlbumsCount(ctx context.Context, userID uuid.UUID) (uint64, error)
GetAlbumLikesCount(ctx context.Context, albumID uint64) (uint64, error)
}
20 changes: 20 additions & 0 deletions microservices/album/repository/pg_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,23 @@ func (r *AlbumRepository) GetFavoriteAlbums(ctx context.Context, userID uuid.UUI

return albums, nil
}

func (r *AlbumRepository) GetFavoriteAlbumsCount(ctx context.Context, userID uuid.UUID) (uint64, error) {
var count uint64
err := r.db.QueryRowContext(ctx, getFavoriteCountQuery, userID).Scan(&count)
if err != nil && err != sql.ErrNoRows {
return 0, errors.Wrap(err, "GetFavoriteCount.Query")
}

return count, nil
}

func (r *AlbumRepository) GetAlbumLikesCount(ctx context.Context, albumID uint64) (uint64, error) {
var likesCount uint64
err := r.db.QueryRowContext(ctx, getLikesCountQuery, albumID).Scan(&likesCount)
if err != nil && err != sql.ErrNoRows {
return 0, errors.Wrap(err, "GetLikesCount.Query")
}

return likesCount, nil
}
44 changes: 44 additions & 0 deletions microservices/album/repository/pg_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,47 @@ func TestAlbumRepositoryGetFavoriteAlbums(t *testing.T) {
require.NotNil(t, foundAlbums)
require.Equal(t, foundAlbums, expectedAlbums)
}

func TestAlbumRepositoryGetFavoriteAlbumsCount(t *testing.T) {
t.Parallel()

db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(t, err)
defer db.Close()

albumRepository := NewAlbumPGRepository(db)

userID := uuid.New()
expectedCount := uint64(2)

mock.ExpectQuery(getFavoriteCountQuery).WithArgs(userID).WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(expectedCount))

count, err := albumRepository.GetFavoriteAlbumsCount(context.Background(), userID)
require.NoError(t, err)
require.Equal(t, expectedCount, count)

err = mock.ExpectationsWereMet()
require.NoError(t, err)
}

func TestAlbumRepositoryGetAlbumLikesCount(t *testing.T) {
t.Parallel()

db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(t, err)
defer db.Close()

albumRepository := NewAlbumPGRepository(db)

albumID := uint64(123)
expectedLikesCount := uint64(10)

mock.ExpectQuery(getLikesCountQuery).WithArgs(albumID).WillReturnRows(sqlmock.NewRows([]string{"likes_count"}).AddRow(expectedLikesCount))

likesCount, err := albumRepository.GetAlbumLikesCount(context.Background(), albumID)
require.NoError(t, err)
require.Equal(t, expectedLikesCount, likesCount)

err = mock.ExpectationsWereMet()
require.NoError(t, err)
}
Loading

0 comments on commit a4e11ec

Please sign in to comment.