Files
david 935f742ac9 Add filtering support to GET /api/v1/habits endpoint
Implemented comprehensive filtering capabilities for the habits list endpoint:
- Filter by type (BOOLEAN, COUNTER, VALUE)
- Filter by frequency (DAILY, WEEKLY, MONTHLY)
- Filter by archived status
- Text search in habit name and description
- All filters can be combined
- Filters work with pagination

Technical changes:
- Added FilterParams to GetUserHabitsQuery
- Created HabitFilter struct in repository interface
- Implemented dynamic SQL query building in SQLite repository
- Updated HTTP handler to parse filter query parameters
- Added comprehensive tests for repository and handler filtering
- Updated all test mocks with new filter methods
2025-12-02 01:02:39 +01:00

153 lines
3.9 KiB
Go

package commands
import (
"apocapoc-api/internal/domain/repositories"
"apocapoc-api/internal/shared/pagination"
"context"
"testing"
"apocapoc-api/internal/domain/entities"
"apocapoc-api/internal/shared/errors"
)
type mockDeleteUserRepo struct {
findByIDFunc func(ctx context.Context, id string) (*entities.User, error)
deleteFunc func(ctx context.Context, id string) error
}
func (m *mockDeleteUserRepo) FindByID(ctx context.Context, id string) (*entities.User, error) {
if m.findByIDFunc != nil {
return m.findByIDFunc(ctx, id)
}
return nil, errors.ErrNotFound
}
func (m *mockDeleteUserRepo) FindByEmail(ctx context.Context, email string) (*entities.User, error) {
return nil, errors.ErrNotFound
}
func (m *mockDeleteUserRepo) FindByVerificationToken(ctx context.Context, token string) (*entities.User, error) {
return nil, errors.ErrNotFound
}
func (m *mockDeleteUserRepo) Create(ctx context.Context, user *entities.User) error {
return nil
}
func (m *mockDeleteUserRepo) Update(ctx context.Context, user *entities.User) error {
return nil
}
func (m *mockDeleteUserRepo) Delete(ctx context.Context, id string) error {
if m.deleteFunc != nil {
return m.deleteFunc(ctx, id)
}
return nil
}
func TestDeleteUserHandler_Success(t *testing.T) {
var deletedID string
repo := &mockDeleteUserRepo{
findByIDFunc: func(ctx context.Context, id string) (*entities.User, error) {
user := entities.NewUser("test@example.com", "hashedPassword")
user.ID = id
return user, nil
},
deleteFunc: func(ctx context.Context, id string) error {
deletedID = id
return nil
},
}
handler := NewDeleteUserHandler(repo)
cmd := DeleteUserCommand{
UserID: "user-123",
}
err := handler.Handle(context.Background(), cmd)
if err != nil {
t.Fatalf("Handle() unexpected error = %v", err)
}
if deletedID != "user-123" {
t.Errorf("deletedID = %v, want %v", deletedID, "user-123")
}
}
func TestDeleteUserHandler_EmptyUserID(t *testing.T) {
repo := &mockDeleteUserRepo{}
handler := NewDeleteUserHandler(repo)
cmd := DeleteUserCommand{
UserID: "",
}
err := handler.Handle(context.Background(), cmd)
if err != errors.ErrInvalidInput {
t.Errorf("Handle() error = %v, want %v", err, errors.ErrInvalidInput)
}
}
func TestDeleteUserHandler_UserNotFound(t *testing.T) {
repo := &mockDeleteUserRepo{
findByIDFunc: func(ctx context.Context, id string) (*entities.User, error) {
return nil, errors.ErrNotFound
},
}
handler := NewDeleteUserHandler(repo)
cmd := DeleteUserCommand{
UserID: "non-existent-user",
}
err := handler.Handle(context.Background(), cmd)
if err != errors.ErrNotFound {
t.Errorf("Handle() error = %v, want %v", err, errors.ErrNotFound)
}
}
func TestDeleteUserHandler_DeleteError(t *testing.T) {
customError := errors.ErrNotFound
repo := &mockDeleteUserRepo{
findByIDFunc: func(ctx context.Context, id string) (*entities.User, error) {
user := entities.NewUser("test@example.com", "hashedPassword")
user.ID = id
return user, nil
},
deleteFunc: func(ctx context.Context, id string) error {
return customError
},
}
handler := NewDeleteUserHandler(repo)
cmd := DeleteUserCommand{
UserID: "user-123",
}
err := handler.Handle(context.Background(), cmd)
if err != customError {
t.Errorf("Handle() error = %v, want %v", err, customError)
}
}
func (m *mockDeleteUserRepo) FindActiveByUserIDWithPagination(ctx context.Context, userID string, params pagination.Params) ([]*entities.Habit, error) {
return nil, nil
}
func (m *mockDeleteUserRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
return 0, nil
}
func (m *mockDeleteUserRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
return nil, nil
}
func (m *mockDeleteUserRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
return 0, nil
}