veza/veza-backend-api/internal/services/track_service_list_test.go.disabled
2025-12-03 20:29:37 +01:00

845 lines
19 KiB
Text

package services
import (
"context"
"github.com/google/uuid"
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"veza-backend-api/internal/models"
)
func setupTestTrackServiceForList(t *testing.T) (*TrackService, *gorm.DB, func()) {
// Setup in-memory SQLite database
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
assert.NoError(t, err)
// Auto-migrate
err = db.AutoMigrate(&models.Track{}, &models.User{})
assert.NoError(t, err)
// Create test users
user1 := &models.User{
ID: 123,
Username: "testuser1",
Email: "test1@example.com",
IsActive: true,
}
err = db.Create(user1).Error
assert.NoError(t, err)
user2 := &models.User{
ID: 456,
Username: "testuser2",
Email: "test2@example.com",
IsActive: true,
}
err = db.Create(user2).Error
assert.NoError(t, err)
// Setup logger
logger := zap.NewNop()
// Setup test service
service := NewTrackService(db, logger, "test_uploads/tracks")
// Cleanup function
cleanup := func() {
// Database will be closed automatically
}
return service, db, cleanup
}
func TestTrackService_ListTracks_Success(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer quelques tracks avec statut completed
track1 := &models.Track{
UserID: 123,
Title: "Track 1",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
PlayCount: 10,
LikeCount: 5,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "Track 2",
FilePath: "/test/track2.flac",
FileSize: 10 * 1024 * 1024,
Format: "FLAC",
Genre: "Jazz",
Duration: 200,
IsPublic: true,
Status: models.TrackStatusCompleted,
PlayCount: 20,
LikeCount: 10,
}
err = db.Create(track2).Error
assert.NoError(t, err)
track3 := &models.Track{
UserID: 456,
Title: "Track 3",
FilePath: "/test/track3.mp3",
FileSize: 3 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 150,
IsPublic: true,
Status: models.TrackStatusCompleted,
PlayCount: 5,
LikeCount: 2,
}
err = db.Create(track3).Error
assert.NoError(t, err)
// Track avec statut uploading (ne doit pas apparaître)
track4 := &models.Track{
UserID: 123,
Title: "Track 4",
FilePath: "/test/track4.mp3",
FileSize: 2 * 1024 * 1024,
Format: "MP3",
Duration: 100,
IsPublic: true,
Status: models.TrackStatusUploading,
}
err = db.Create(track4).Error
assert.NoError(t, err)
// Test: Lister tous les tracks
params := TrackListParams{
Page: 1,
Limit: 20,
SortBy: "created_at",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(3), total) // Seulement les tracks completed
assert.Len(t, tracks, 3)
}
func TestTrackService_ListTracks_WithPagination(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer 5 tracks
for i := 1; i <= 5; i++ {
track := &models.Track{
UserID: 123,
Title: "Track " + string(rune('0'+i)),
FilePath: "/test/track" + string(rune('0'+i)) + ".mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
}
// Test: Page 1, limit 2
params := TrackListParams{
Page: 1,
Limit: 2,
SortBy: "created_at",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(5), total)
assert.Len(t, tracks, 2)
// Test: Page 2, limit 2
params.Page = 2
tracks, total, err = service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(5), total)
assert.Len(t, tracks, 2)
// Test: Page 3, limit 2
params.Page = 3
tracks, total, err = service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(5), total)
assert.Len(t, tracks, 1) // Dernière page avec 1 track
}
func TestTrackService_ListTracks_WithUserFilter(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer tracks pour deux utilisateurs
track1 := &models.Track{
UserID: 123,
Title: "Track User 1",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 456,
Title: "Track User 2",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
// Test: Filtrer par user_id
userID := int64(123)
params := TrackListParams{
Page: 1,
Limit: 20,
UserID: &userID,
SortBy: "created_at",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, tracks, 1)
assert.Equal(t, int64(123), tracks[0].UserID)
}
func TestTrackService_ListTracks_WithGenreFilter(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer tracks avec différents genres
track1 := &models.Track{
UserID: 123,
Title: "Rock Track",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "Jazz Track",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Jazz",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
// Test: Filtrer par genre
genre := "Rock"
params := TrackListParams{
Page: 1,
Limit: 20,
Genre: &genre,
SortBy: "created_at",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, tracks, 1)
assert.Equal(t, "Rock", tracks[0].Genre)
}
func TestTrackService_ListTracks_WithFormatFilter(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer tracks avec différents formats
track1 := &models.Track{
UserID: 123,
Title: "MP3 Track",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "FLAC Track",
FilePath: "/test/track2.flac",
FileSize: 10 * 1024 * 1024,
Format: "FLAC",
Duration: 200,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
// Test: Filtrer par format
format := "FLAC"
params := TrackListParams{
Page: 1,
Limit: 20,
Format: &format,
SortBy: "created_at",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, tracks, 1)
assert.Equal(t, "FLAC", tracks[0].Format)
}
func TestTrackService_ListTracks_WithSorting(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer tracks avec différents titres
track1 := &models.Track{
UserID: 123,
Title: "A Track",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "Z Track",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
track3 := &models.Track{
UserID: 123,
Title: "M Track",
FilePath: "/test/track3.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track3).Error
assert.NoError(t, err)
// Test: Trier par titre asc
params := TrackListParams{
Page: 1,
Limit: 20,
SortBy: "title",
SortOrder: "asc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(3), total)
assert.Len(t, tracks, 3)
assert.Equal(t, "A Track", tracks[0].Title)
assert.Equal(t, "M Track", tracks[1].Title)
assert.Equal(t, "Z Track", tracks[2].Title)
}
func TestTrackService_ListTracks_WithPopularitySort(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer tracks avec différentes popularités
track1 := &models.Track{
UserID: 123,
Title: "Low Popularity",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
PlayCount: 5,
LikeCount: 2,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "High Popularity",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
PlayCount: 50,
LikeCount: 20,
}
err = db.Create(track2).Error
assert.NoError(t, err)
track3 := &models.Track{
UserID: 123,
Title: "Medium Popularity",
FilePath: "/test/track3.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
PlayCount: 20,
LikeCount: 10,
}
err = db.Create(track3).Error
assert.NoError(t, err)
// Test: Trier par popularité desc
params := TrackListParams{
Page: 1,
Limit: 20,
SortBy: "popularity",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(3), total)
assert.Len(t, tracks, 3)
// Vérifier que le plus populaire est en premier (70 = 50 + 20)
assert.Equal(t, "High Popularity", tracks[0].Title)
}
func TestTrackService_ListTracks_DefaultValues(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Test: Paramètres par défaut (page 0, limit 0)
params := TrackListParams{
Page: 0,
Limit: 0,
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(1), total)
assert.Len(t, tracks, 1)
// Vérifier que les valeurs par défaut sont appliquées
// Page devrait être 1, limit devrait être 20
}
func TestTrackService_ListTracks_MaxLimit(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer 150 tracks
for i := 1; i <= 150; i++ {
track := &models.Track{
UserID: 123,
Title: "Track " + string(rune('0'+(i%10))),
FilePath: "/test/track" + string(rune('0'+(i%10))) + ".mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
}
// Test: Limit supérieur à 100 devrait être limité à 100
params := TrackListParams{
Page: 1,
Limit: 200,
SortBy: "created_at",
SortOrder: "desc",
}
tracks, total, err := service.ListTracks(ctx, params)
assert.NoError(t, err)
assert.Equal(t, int64(150), total)
assert.LessOrEqual(t, len(tracks), 100) // Maximum 100
}
func TestTrackService_GetTrackByID_Success(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Test Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Récupérer le track
retrievedTrack, err := service.GetTrackByID(ctx, track.ID)
assert.NoError(t, err)
assert.NotNil(t, retrievedTrack)
assert.Equal(t, track.ID, retrievedTrack.ID)
assert.Equal(t, track.Title, retrievedTrack.Title)
assert.Equal(t, track.UserID, retrievedTrack.UserID)
}
func TestTrackService_GetTrackByID_NotFound(t *testing.T) {
service, _, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Essayer de récupérer un track qui n'existe pas
_, err := service.GetTrackByID(ctx, 99999)
assert.Error(t, err)
assert.Equal(t, ErrTrackNotFound, err)
}
func TestTrackService_UpdateTrack_Success(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Mettre à jour le track
newTitle := "Updated Title"
newGenre := "Jazz"
params := UpdateTrackParams{
Title: &newTitle,
Genre: &newGenre,
}
updatedTrack, err := service.UpdateTrack(ctx, track.ID, 123, params)
assert.NoError(t, err)
assert.NotNil(t, updatedTrack)
assert.Equal(t, "Updated Title", updatedTrack.Title)
assert.Equal(t, "Jazz", updatedTrack.Genre)
assert.Equal(t, track.ID, updatedTrack.ID)
}
func TestTrackService_UpdateTrack_NotFound(t *testing.T) {
service, _, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
newTitle := "Updated Title"
params := UpdateTrackParams{
Title: &newTitle,
}
_, err := service.UpdateTrack(ctx, 99999, 123, params)
assert.Error(t, err)
assert.Equal(t, ErrTrackNotFound, err)
}
func TestTrackService_UpdateTrack_Forbidden(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track appartenant à l'utilisateur 123
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Essayer de mettre à jour avec un autre utilisateur
newTitle := "Updated Title"
params := UpdateTrackParams{
Title: &newTitle,
}
_, err = service.UpdateTrack(ctx, track.ID, 456, params)
assert.Error(t, err)
assert.Equal(t, ErrForbidden, err)
}
func TestTrackService_UpdateTrack_EmptyTitle(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Essayer de mettre à jour avec un titre vide
emptyTitle := ""
params := UpdateTrackParams{
Title: &emptyTitle,
}
_, err = service.UpdateTrack(ctx, track.ID, 123, params)
assert.Error(t, err)
assert.Contains(t, err.Error(), "title cannot be empty")
}
func TestTrackService_UpdateTrack_NegativeYear(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Essayer de mettre à jour avec une année négative
negativeYear := -1
params := UpdateTrackParams{
Year: &negativeYear,
}
_, err = service.UpdateTrack(ctx, track.ID, 123, params)
assert.Error(t, err)
assert.Contains(t, err.Error(), "year cannot be negative")
}
func TestTrackService_UpdateTrack_NoUpdates(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Mettre à jour sans aucun paramètre
params := UpdateTrackParams{}
updatedTrack, err := service.UpdateTrack(ctx, track.ID, 123, params)
assert.NoError(t, err)
assert.NotNil(t, updatedTrack)
assert.Equal(t, track.Title, updatedTrack.Title)
}
func TestTrackService_DeleteTrack_Success(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Test Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Supprimer le track
err = service.DeleteTrack(ctx, track.ID, 123)
assert.NoError(t, err)
// Vérifier que le track a été supprimé
var deletedTrack models.Track
err = db.First(&deletedTrack, track.ID).Error
assert.Error(t, err)
assert.Equal(t, gorm.ErrRecordNotFound, err)
}
func TestTrackService_DeleteTrack_NotFound(t *testing.T) {
service, _, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Essayer de supprimer un track qui n'existe pas
err := service.DeleteTrack(ctx, 99999, 123)
assert.Error(t, err)
assert.Equal(t, ErrTrackNotFound, err)
}
func TestTrackService_DeleteTrack_Forbidden(t *testing.T) {
service, db, cleanup := setupTestTrackServiceForList(t)
defer cleanup()
ctx := context.Background()
// Créer un track appartenant à l'utilisateur 123
track := &models.Track{
UserID: 123,
Title: "Test Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Essayer de supprimer avec un autre utilisateur
err = service.DeleteTrack(ctx, track.ID, 456)
assert.Error(t, err)
assert.Equal(t, ErrForbidden, err)
// Vérifier que le track n'a pas été supprimé
var existingTrack models.Track
err = db.First(&existingTrack, track.ID).Error
assert.NoError(t, err)
assert.Equal(t, track.ID, existingTrack.ID)
}