package services import ( "context" "testing" "veza-backend-api/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func setupTestPlaylistSearch(t *testing.T) (*PlaylistService, *gorm.DB, *models.User, *models.User, func()) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) require.NoError(t, err) // Enable foreign keys for SQLite db.Exec("PRAGMA foreign_keys = ON") // Auto-migrate err = db.AutoMigrate( &models.User{}, &models.Playlist{}, ) require.NoError(t, err) // Create test users user1 := &models.User{ Username: "user1", Email: "user1@example.com", PasswordHash: "hash1", Slug: "user1", IsActive: true, } user2 := &models.User{ Username: "user2", Email: "user2@example.com", PasswordHash: "hash2", Slug: "user2", IsActive: true, } require.NoError(t, db.Create(user1).Error) require.NoError(t, db.Create(user2).Error) // Create test playlists playlist1 := &models.Playlist{ UserID: user1.ID, Title: "Rock Playlist", Description: "A rock music playlist", IsPublic: true, TrackCount: 0, FollowerCount: 0, } playlist2 := &models.Playlist{ UserID: user1.ID, Title: "Private Playlist", Description: "A private playlist", IsPublic: false, TrackCount: 0, FollowerCount: 0, } playlist3 := &models.Playlist{ UserID: user2.ID, Title: "Jazz Playlist", Description: "A jazz music playlist", IsPublic: true, TrackCount: 0, FollowerCount: 0, } playlist4 := &models.Playlist{ UserID: user2.ID, Title: "Pop Playlist", Description: "A pop music playlist", IsPublic: true, TrackCount: 0, FollowerCount: 0, } require.NoError(t, db.Create(playlist1).Error) require.NoError(t, db.Create(playlist2).Error) // Force IsPublic to false (GORM might use default value true) require.NoError(t, db.Model(playlist2).Update("is_public", false).Error) require.NoError(t, db.Create(playlist3).Error) require.NoError(t, db.Create(playlist4).Error) logger := zap.NewNop() service := NewPlaylistServiceWithDB(db, logger) cleanup := func() { // Database will be closed automatically } return service, db, user1, user2, cleanup } func TestPlaylistService_SearchPlaylists_ByQuery(t *testing.T) { service, _, user1, _, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() userID := &user1.ID // Rechercher par "Rock" playlists, total, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ Query: "Rock", CurrentUserID: userID, Page: 1, Limit: 20, }) require.NoError(t, err) assert.GreaterOrEqual(t, total, int64(1)) assert.GreaterOrEqual(t, len(playlists), 1) // Vérifier que les résultats contiennent "Rock" found := false for _, p := range playlists { if p.Title == "Rock Playlist" { found = true break } } assert.True(t, found, "Should find Rock Playlist") } func TestPlaylistService_SearchPlaylists_ByUserID(t *testing.T) { service, _, user1, user2, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() userID := &user1.ID // Rechercher les playlists de user2 playlists, total, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ UserID: &user2.ID, CurrentUserID: userID, Page: 1, Limit: 20, }) require.NoError(t, err) assert.GreaterOrEqual(t, total, int64(2)) // Au moins 2 playlists publiques de user2 assert.GreaterOrEqual(t, len(playlists), 2) // Vérifier que toutes les playlists appartiennent à user2 for _, p := range playlists { assert.Equal(t, user2.ID, p.UserID) assert.True(t, p.IsPublic, "Should only return public playlists from other users") } } func TestPlaylistService_SearchPlaylists_ByIsPublic(t *testing.T) { service, _, user1, _, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() userID := &user1.ID public := true // Rechercher seulement les playlists publiques playlists, total, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ IsPublic: &public, CurrentUserID: userID, Page: 1, Limit: 20, }) require.NoError(t, err) assert.GreaterOrEqual(t, total, int64(3)) // Au moins 3 playlists publiques assert.GreaterOrEqual(t, len(playlists), 3) // Vérifier que toutes les playlists sont publiques for _, p := range playlists { assert.True(t, p.IsPublic) } } func TestPlaylistService_SearchPlaylists_OwnPrivatePlaylists(t *testing.T) { service, _, user1, _, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() userID := &user1.ID // Rechercher les playlists de user1 (devrait inclure les privées) playlists, total, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ UserID: &user1.ID, CurrentUserID: userID, Page: 1, Limit: 20, }) require.NoError(t, err) assert.GreaterOrEqual(t, total, int64(2)) // Au moins 2 playlists (1 publique + 1 privée) assert.GreaterOrEqual(t, len(playlists), 2) // Vérifier qu'on peut voir sa propre playlist privée foundPrivate := false for _, p := range playlists { if p.Title == "Private Playlist" && !p.IsPublic { foundPrivate = true break } } assert.True(t, foundPrivate, "Should find own private playlist") } func TestPlaylistService_SearchPlaylists_Unauthenticated(t *testing.T) { service, _, _, _, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() // Rechercher sans être authentifié (devrait seulement retourner les publiques) playlists, total, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ Query: "Playlist", CurrentUserID: nil, Page: 1, Limit: 20, }) require.NoError(t, err) assert.GreaterOrEqual(t, total, int64(3)) // Au moins 3 playlists publiques assert.GreaterOrEqual(t, len(playlists), 3) // Vérifier que toutes les playlists sont publiques for _, p := range playlists { assert.True(t, p.IsPublic, "Unauthenticated users should only see public playlists") } } func TestPlaylistService_SearchPlaylists_Pagination(t *testing.T) { service, _, user1, _, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() userID := &user1.ID // Première page playlists1, total1, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ CurrentUserID: userID, Page: 1, Limit: 2, }) require.NoError(t, err) assert.GreaterOrEqual(t, total1, int64(3)) assert.LessOrEqual(t, len(playlists1), 2) // Deuxième page playlists2, total2, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ CurrentUserID: userID, Page: 2, Limit: 2, }) require.NoError(t, err) assert.Equal(t, total1, total2) // Le total devrait être le même assert.LessOrEqual(t, len(playlists2), 2) // Vérifier qu'on a des résultats différents if len(playlists1) > 0 && len(playlists2) > 0 { assert.NotEqual(t, playlists1[0].ID, playlists2[0].ID, "Pages should return different results") } } func TestPlaylistService_SearchPlaylists_EmptyQuery(t *testing.T) { service, _, user1, _, cleanup := setupTestPlaylistSearch(t) defer cleanup() ctx := context.Background() userID := &user1.ID // Rechercher sans query (devrait retourner toutes les playlists accessibles) playlists, total, err := service.SearchPlaylists(ctx, SearchPlaylistsParams{ Query: "", CurrentUserID: userID, Page: 1, Limit: 20, }) require.NoError(t, err) assert.GreaterOrEqual(t, total, int64(3)) // Au moins 3 playlists accessibles assert.GreaterOrEqual(t, len(playlists), 3) }