veza/veza-backend-api/internal/services/playlist_service_test.go

465 lines
18 KiB
Go
Raw Normal View History

2025-12-03 19:29:37 +00:00
package services
import (
"context"
"github.com/google/uuid"
"testing"
"time"
"veza-backend-api/internal/models"
"veza-backend-api/internal/repositories"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// setupTestPlaylistServiceDB crée une base de données de test en mémoire
func setupTestPlaylistServiceDB(t *testing.T) *gorm.DB {
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err, "Failed to open test database")
// Enable foreign keys for SQLite to ensure data integrity constraints
db.Exec("PRAGMA foreign_keys = ON")
// Auto-migrate tous les modèles nécessaires
err = db.AutoMigrate(
&models.User{},
&models.Playlist{},
&models.PlaylistTrack{},
&models.PlaylistCollaborator{},
&models.Track{},
)
require.NoError(t, err, "Failed to migrate test database")
return db
}
// createTestUser crée un utilisateur de test
func createTestUserForService(t *testing.T, db *gorm.DB, username string) *models.User {
user := &models.User{
Username: username,
Slug: username,
Email: username + "@example.com",
PasswordHash: "hashed_password",
IsActive: true,
CreatedAt: time.Now(),
}
err := db.Create(user).Error
require.NoError(t, err)
return user
}
// createTestPlaylist crée une playlist de test
func createTestPlaylistForService(t *testing.T, db *gorm.DB, userID uuid.UUID) *models.Playlist {
playlist := &models.Playlist{
UserID: userID,
Title: "Test Playlist",
Description: "Test Description",
IsPublic: true,
TrackCount: 0,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
err := db.Create(playlist).Error
require.NoError(t, err)
return playlist
}
// createTestTrackForService crée un track de test
func createTestTrackForService(t *testing.T, db *gorm.DB, userID uuid.UUID) *models.Track {
track := &models.Track{
UserID: userID,
Title: "Test Track",
FilePath: "/tmp/test.mp3",
Format: "mp3",
IsPublic: true,
CreatedAt: time.Now(),
}
err := db.Create(track).Error
require.NoError(t, err)
return track
}
func TestPlaylistService_CreatePlaylist(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
user := createTestUserForService(t, db, "testuser")
// Test creation
playlist, err := service.CreatePlaylist(ctx, user.ID, "My Playlist", "Desc", true)
assert.NoError(t, err)
assert.NotNil(t, playlist)
assert.Equal(t, "My Playlist", playlist.Title)
assert.Equal(t, user.ID, playlist.UserID)
// Test user not found
_, err = service.CreatePlaylist(ctx, uuid.New(), "Title", "Desc", true)
2025-12-03 19:29:37 +00:00
assert.Error(t, err)
assert.Contains(t, err.Error(), "user not found")
}
func TestPlaylistService_AddTrackToPlaylist(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
user := createTestUserForService(t, db, "testuser")
playlist := createTestPlaylistForService(t, db, user.ID)
track := createTestTrackForService(t, db, user.ID)
// Add track
err := service.AddTrackToPlaylist(ctx, playlist.ID, track.ID, user.ID, 0)
assert.NoError(t, err)
// Verify track added
p, err := service.GetPlaylist(ctx, playlist.ID, &user.ID)
assert.NoError(t, err)
require.Len(t, p.Tracks, 1)
2025-12-03 19:29:37 +00:00
assert.Equal(t, track.ID, p.Tracks[0].TrackID)
// Test ownership (other user cannot add track)
otherUser := createTestUserForService(t, db, "other")
err = service.AddTrackToPlaylist(ctx, playlist.ID, track.ID, otherUser.ID, 0)
assert.Error(t, err)
assert.Equal(t, "forbidden", err.Error())
}
func TestPlaylistService_RemoveTrackFromPlaylist(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
user := createTestUserForService(t, db, "testuser")
playlist := createTestPlaylistForService(t, db, user.ID)
track := createTestTrackForService(t, db, user.ID)
// Add track first
err := service.AddTrackToPlaylist(ctx, playlist.ID, track.ID, user.ID, 0)
assert.NoError(t, err)
// Remove track
err = service.RemoveTrackFromPlaylist(ctx, playlist.ID, track.ID, user.ID)
assert.NoError(t, err)
// Verify removed
p, err := service.GetPlaylist(ctx, playlist.ID, &user.ID)
assert.NoError(t, err)
assert.Len(t, p.Tracks, 0)
}
func TestPlaylistService_AddCollaborator(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
owner := createTestUserForService(t, db, "owner")
collaborator := createTestUserForService(t, db, "collaborator")
playlist := createTestPlaylistForService(t, db, owner.ID)
// Test AddCollaborator avec permission read
collab, err := service.AddCollaborator(ctx, playlist.ID, owner.ID, collaborator.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.NotNil(t, collab)
assert.Equal(t, playlist.ID, collab.PlaylistID)
assert.Equal(t, collaborator.ID, collab.UserID)
assert.Equal(t, models.PlaylistPermissionRead, collab.Permission)
// Test AddCollaborator avec permission write (créer un autre utilisateur)
collaborator2 := createTestUserForService(t, db, "collaborator2")
collab2, err := service.AddCollaborator(ctx, playlist.ID, owner.ID, collaborator2.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
assert.Equal(t, models.PlaylistPermissionWrite, collab2.Permission)
// Test AddCollaborator avec non-propriétaire (devrait échouer)
otherUser := createTestUserForService(t, db, "other_user")
_, err = service.AddCollaborator(ctx, playlist.ID, collaborator.ID, otherUser.ID, models.PlaylistPermissionRead)
assert.Error(t, err)
assert.Contains(t, err.Error(), "forbidden")
// Test AddCollaborator avec le propriétaire lui-même (devrait échouer)
_, err = service.AddCollaborator(ctx, playlist.ID, owner.ID, owner.ID, models.PlaylistPermissionRead)
assert.Error(t, err)
assert.Contains(t, err.Error(), "cannot add playlist owner")
// Test AddCollaborator avec playlist inexistante
_, err = service.AddCollaborator(ctx, uuid.New(), owner.ID, collaborator.ID, models.PlaylistPermissionRead)
2025-12-03 19:29:37 +00:00
assert.Error(t, err)
assert.Contains(t, err.Error(), "playlist not found")
// Test AddCollaborator avec utilisateur inexistant
_, err = service.AddCollaborator(ctx, playlist.ID, owner.ID, uuid.New(), models.PlaylistPermissionRead)
2025-12-03 19:29:37 +00:00
assert.Error(t, err)
assert.Contains(t, err.Error(), "user not found")
}
func TestPlaylistService_RemoveCollaborator(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
owner := createTestUserForService(t, db, "owner")
collaborator := createTestUserForService(t, db, "collaborator")
playlist := createTestPlaylistForService(t, db, owner.ID)
// Ajouter un collaborateur
_, err := service.AddCollaborator(ctx, playlist.ID, owner.ID, collaborator.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
// Retirer le collaborateur
err = service.RemoveCollaborator(ctx, playlist.ID, owner.ID, collaborator.ID)
assert.NoError(t, err)
// Vérifier qu'il n'existe plus
exists, err := playlistCollaboratorRepo.Exists(ctx, playlist.ID, collaborator.ID)
assert.NoError(t, err)
assert.False(t, exists)
// Test RemoveCollaborator avec non-propriétaire (devrait échouer)
err = service.RemoveCollaborator(ctx, playlist.ID, collaborator.ID, owner.ID)
assert.Error(t, err)
assert.Contains(t, err.Error(), "forbidden")
// Test RemoveCollaborator avec collaborateur inexistant
err = service.RemoveCollaborator(ctx, playlist.ID, owner.ID, uuid.New())
2025-12-03 19:29:37 +00:00
assert.Error(t, err)
assert.Contains(t, err.Error(), "collaborator not found")
}
func TestPlaylistService_UpdateCollaboratorPermission(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
owner := createTestUserForService(t, db, "owner")
collaborator := createTestUserForService(t, db, "collaborator")
playlist := createTestPlaylistForService(t, db, owner.ID)
// Ajouter un collaborateur avec permission read
_, err := service.AddCollaborator(ctx, playlist.ID, owner.ID, collaborator.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
// Mettre à jour la permission à write
err = service.UpdateCollaboratorPermission(ctx, playlist.ID, owner.ID, collaborator.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
// Vérifier la mise à jour
collab, err := playlistCollaboratorRepo.GetCollaborator(ctx, playlist.ID, collaborator.ID)
assert.NoError(t, err)
assert.Equal(t, models.PlaylistPermissionWrite, collab.Permission)
// Mettre à jour la permission à admin
err = service.UpdateCollaboratorPermission(ctx, playlist.ID, owner.ID, collaborator.ID, models.PlaylistPermissionAdmin)
assert.NoError(t, err)
// Vérifier la mise à jour
collab, err = playlistCollaboratorRepo.GetCollaborator(ctx, playlist.ID, collaborator.ID)
assert.NoError(t, err)
assert.Equal(t, models.PlaylistPermissionAdmin, collab.Permission)
// Test UpdateCollaboratorPermission avec non-propriétaire (devrait échouer)
err = service.UpdateCollaboratorPermission(ctx, playlist.ID, collaborator.ID, owner.ID, models.PlaylistPermissionRead)
assert.Error(t, err)
assert.Contains(t, err.Error(), "forbidden")
// Test UpdateCollaboratorPermission avec permission invalide
err = service.UpdateCollaboratorPermission(ctx, playlist.ID, owner.ID, collaborator.ID, models.PlaylistPermission("invalid"))
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid permission")
// Test UpdateCollaboratorPermission avec collaborateur inexistant
err = service.UpdateCollaboratorPermission(ctx, playlist.ID, owner.ID, uuid.New(), models.PlaylistPermissionRead)
2025-12-03 19:29:37 +00:00
assert.Error(t, err)
assert.Contains(t, err.Error(), "collaborator not found")
}
func TestPlaylistService_CheckPermission(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
owner := createTestUserForService(t, db, "owner")
collaboratorRead := createTestUserForService(t, db, "collaborator_read")
collaboratorWrite := createTestUserForService(t, db, "collaborator_write")
collaboratorAdmin := createTestUserForService(t, db, "collaborator_admin")
otherUser := createTestUserForService(t, db, "other_user")
playlist := createTestPlaylistForService(t, db, owner.ID)
// Le propriétaire a toujours toutes les permissions
hasPermission, err := service.CheckPermission(ctx, playlist.ID, owner.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, owner.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, owner.ID, models.PlaylistPermissionAdmin)
assert.NoError(t, err)
assert.True(t, hasPermission)
// Pour une playlist publique, tout le monde peut lire
hasPermission, err = service.CheckPermission(ctx, playlist.ID, otherUser.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.True(t, hasPermission)
// Mais pas écrire
hasPermission, err = service.CheckPermission(ctx, playlist.ID, otherUser.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
assert.False(t, hasPermission)
// Ajouter des collaborateurs avec différentes permissions
_, err = service.AddCollaborator(ctx, playlist.ID, owner.ID, collaboratorRead.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
_, err = service.AddCollaborator(ctx, playlist.ID, owner.ID, collaboratorWrite.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
_, err = service.AddCollaborator(ctx, playlist.ID, owner.ID, collaboratorAdmin.ID, models.PlaylistPermissionAdmin)
assert.NoError(t, err)
// Vérifier les permissions du collaborateur read
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorRead.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorRead.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
assert.False(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorRead.ID, models.PlaylistPermissionAdmin)
assert.NoError(t, err)
assert.False(t, hasPermission)
// Vérifier les permissions du collaborateur write
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorWrite.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorWrite.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorWrite.ID, models.PlaylistPermissionAdmin)
assert.NoError(t, err)
assert.False(t, hasPermission)
// Vérifier les permissions du collaborateur admin
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorAdmin.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorAdmin.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
assert.True(t, hasPermission)
hasPermission, err = service.CheckPermission(ctx, playlist.ID, collaboratorAdmin.ID, models.PlaylistPermissionAdmin)
assert.NoError(t, err)
assert.True(t, hasPermission)
// Test avec playlist privée
privatePlaylist := createTestPlaylistForService(t, db, owner.ID)
privatePlaylist.IsPublic = false
err = db.Save(privatePlaylist).Error
assert.NoError(t, err)
// Un utilisateur non collaborateur ne peut pas lire une playlist privée
hasPermission, err = service.CheckPermission(ctx, privatePlaylist.ID, otherUser.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
assert.False(t, hasPermission)
// Test avec playlist inexistante
_, err = service.CheckPermission(ctx, uuid.New(), owner.ID, models.PlaylistPermissionRead)
2025-12-03 19:29:37 +00:00
assert.Error(t, err)
assert.Contains(t, err.Error(), "playlist not found")
}
func TestPlaylistService_GetCollaborators(t *testing.T) {
db := setupTestPlaylistServiceDB(t)
playlistRepo := repositories.NewPlaylistRepository(db)
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
userRepo := &gormUserRepository{db: db}
logger := zap.NewNop()
service := NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
ctx := context.Background()
owner := createTestUserForService(t, db, "owner")
collaborator1 := createTestUserForService(t, db, "collaborator1")
collaborator2 := createTestUserForService(t, db, "collaborator2")
otherUser := createTestUserForService(t, db, "other_user")
playlist := createTestPlaylistForService(t, db, owner.ID)
// Ajouter des collaborateurs
_, err := service.AddCollaborator(ctx, playlist.ID, owner.ID, collaborator1.ID, models.PlaylistPermissionRead)
assert.NoError(t, err)
_, err = service.AddCollaborator(ctx, playlist.ID, owner.ID, collaborator2.ID, models.PlaylistPermissionWrite)
assert.NoError(t, err)
// Le propriétaire peut récupérer les collaborateurs
collaborators, err := service.GetCollaborators(ctx, playlist.ID, owner.ID)
assert.NoError(t, err)
assert.Len(t, collaborators, 2)
// Un collaborateur peut récupérer les collaborateurs
collaborators, err = service.GetCollaborators(ctx, playlist.ID, collaborator1.ID)
assert.NoError(t, err)
assert.Len(t, collaborators, 2)
// Un utilisateur non collaborateur peut récupérer les collaborateurs d'une playlist publique
collaborators, err = service.GetCollaborators(ctx, playlist.ID, otherUser.ID)
assert.NoError(t, err)
assert.Len(t, collaborators, 2)
// Test avec playlist privée
privatePlaylist := createTestPlaylistForService(t, db, owner.ID)
privatePlaylist.IsPublic = false
err = db.Save(privatePlaylist).Error
assert.NoError(t, err)
// Un utilisateur non collaborateur ne peut pas récupérer les collaborateurs d'une playlist privée
_, err = service.GetCollaborators(ctx, privatePlaylist.ID, otherUser.ID)
assert.Error(t, err)
assert.Contains(t, err.Error(), "forbidden")
}