592 lines
16 KiB
Go
592 lines
16 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap/zaptest"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
func setupTestPlaybackAggregationServiceDB(t *testing.T) *gorm.DB {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
db.Exec("PRAGMA foreign_keys = ON")
|
|
err = db.AutoMigrate(&models.User{}, &models.Track{}, &models.PlaybackAnalytics{})
|
|
require.NoError(t, err)
|
|
|
|
return db
|
|
}
|
|
|
|
func TestNewPlaybackAggregationService(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
assert.NotNil(t, service)
|
|
assert.Equal(t, db, service.db)
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_Day(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
// Créer test user et track
|
|
userID := uuid.New()
|
|
user := &models.User{ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
|
|
trackID := uuid.New()
|
|
track := &models.Track{
|
|
ID: trackID,
|
|
UserID: userID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
// Créer des sessions sur différentes dates
|
|
now := time.Now()
|
|
sessions := []models.PlaybackAnalytics{
|
|
{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 120,
|
|
PauseCount: 2,
|
|
SeekCount: 3,
|
|
CompletionRate: 75.0,
|
|
StartedAt: now.AddDate(0, 0, -2),
|
|
CreatedAt: now.AddDate(0, 0, -2),
|
|
},
|
|
{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 150,
|
|
PauseCount: 1,
|
|
SeekCount: 2,
|
|
CompletionRate: 90.0,
|
|
StartedAt: now.AddDate(0, 0, -2),
|
|
CreatedAt: now.AddDate(0, 0, -2),
|
|
},
|
|
{
|
|
TrackID: trackID,
|
|
UserID: userID,
|
|
PlayTime: 100,
|
|
PauseCount: 3,
|
|
SeekCount: 1,
|
|
CompletionRate: 60.0,
|
|
StartedAt: now.AddDate(0, 0, -1),
|
|
CreatedAt: now.AddDate(0, 0, -1),
|
|
},
|
|
}
|
|
for _, session := range sessions {
|
|
db.Create(&session)
|
|
}
|
|
|
|
startDate := now.AddDate(0, 0, -3)
|
|
endDate := now
|
|
|
|
result, err := service.AggregateByPeriod(context.Background(), trackID, PeriodDay, startDate, endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, int64(3), result.TotalSessions)
|
|
assert.Equal(t, int64(370), result.TotalPlayTime)
|
|
assert.InDelta(t, 123.33, result.AveragePlayTime, 0.1)
|
|
|
|
// Vérifier qu'il y a 2 périodes (2 jours différents)
|
|
assert.Len(t, result.Periods, 2)
|
|
|
|
// Vérifier la première période (jour -2)
|
|
period1 := result.Periods[0]
|
|
assert.Equal(t, int64(2), period1.Sessions)
|
|
assert.Equal(t, int64(270), period1.TotalPlayTime)
|
|
assert.InDelta(t, 135.0, period1.AveragePlayTime, 0.1)
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_Week(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, 0, -14)
|
|
endDate := now
|
|
|
|
// Créer des sessions dans différentes semaines
|
|
sessions := []models.PlaybackAnalytics{
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 120,
|
|
PauseCount: 2,
|
|
SeekCount: 3,
|
|
CompletionRate: 75.0,
|
|
StartedAt: startDate.AddDate(0, 0, 1),
|
|
CreatedAt: startDate.AddDate(0, 0, 1),
|
|
},
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 150,
|
|
PauseCount: 1,
|
|
SeekCount: 2,
|
|
CompletionRate: 90.0,
|
|
StartedAt: startDate.AddDate(0, 0, 8),
|
|
CreatedAt: startDate.AddDate(0, 0, 8),
|
|
},
|
|
}
|
|
for _, session := range sessions {
|
|
db.Create(&session)
|
|
}
|
|
|
|
result, err := service.AggregateByPeriod(context.Background(), track.ID, PeriodWeek, startDate, endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, int64(2), result.TotalSessions)
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_Month(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, -2, 0)
|
|
endDate := now
|
|
|
|
// Créer des sessions dans différents mois
|
|
sessions := []models.PlaybackAnalytics{
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 120,
|
|
PauseCount: 2,
|
|
SeekCount: 3,
|
|
CompletionRate: 75.0,
|
|
StartedAt: startDate.AddDate(0, 0, 1),
|
|
CreatedAt: startDate.AddDate(0, 0, 1),
|
|
},
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 150,
|
|
PauseCount: 1,
|
|
SeekCount: 2,
|
|
CompletionRate: 90.0,
|
|
StartedAt: startDate.AddDate(0, 1, 0),
|
|
CreatedAt: startDate.AddDate(0, 1, 0),
|
|
},
|
|
}
|
|
for _, session := range sessions {
|
|
db.Create(&session)
|
|
}
|
|
|
|
result, err := service.AggregateByPeriod(context.Background(), track.ID, PeriodMonth, startDate, endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, int64(2), result.TotalSessions)
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_InvalidTrackID(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, 0, -7)
|
|
endDate := now
|
|
|
|
_, err := service.AggregateByPeriod(context.Background(), uuid.Nil, PeriodDay, startDate, endDate)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid track ID")
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_TrackNotFound(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, 0, -7)
|
|
endDate := now
|
|
|
|
_, err := service.AggregateByPeriod(context.Background(), uuid.New(), PeriodDay, startDate, endDate)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "track not found")
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_InvalidPeriod(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, 0, -7)
|
|
endDate := now
|
|
|
|
_, err := service.AggregateByPeriod(context.Background(), track.ID, PeriodType("invalid"), startDate, endDate)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "invalid period type")
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_NoData(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, 0, -7)
|
|
endDate := now
|
|
|
|
result, err := service.AggregateByPeriod(context.Background(), track.ID, PeriodDay, startDate, endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, int64(0), result.TotalSessions)
|
|
assert.Len(t, result.Periods, 0)
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByPeriod_Trends(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
// Créer des sessions avec des valeurs croissantes pour tester les tendances
|
|
// Important: créer dans des jours différents pour avoir plusieurs périodes
|
|
sessions := []models.PlaybackAnalytics{
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 100,
|
|
PauseCount: 1,
|
|
SeekCount: 1,
|
|
CompletionRate: 50.0,
|
|
StartedAt: now.AddDate(0, 0, -3),
|
|
CreatedAt: now.AddDate(0, 0, -3),
|
|
},
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 200,
|
|
PauseCount: 2,
|
|
SeekCount: 2,
|
|
CompletionRate: 100.0,
|
|
StartedAt: now.AddDate(0, 0, -1),
|
|
CreatedAt: now.AddDate(0, 0, -1),
|
|
},
|
|
}
|
|
for _, session := range sessions {
|
|
db.Create(&session)
|
|
}
|
|
|
|
startDate := now.AddDate(0, 0, -4)
|
|
endDate := now
|
|
|
|
result, err := service.AggregateByPeriod(context.Background(), track.ID, PeriodDay, startDate, endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
|
|
// Les tendances ne sont calculées que s'il y a au moins 2 périodes
|
|
if len(result.Periods) >= 2 {
|
|
assert.NotNil(t, result.Trends)
|
|
|
|
// Vérifier que les tendances sont calculées (croissance attendue)
|
|
if result.Trends != nil {
|
|
// Les tendances peuvent être positives (croissance) ou négatives (décroissance)
|
|
// On vérifie juste qu'elles sont calculées (non nulles si les valeurs changent)
|
|
assert.NotNil(t, result.Trends.SessionsTrend)
|
|
assert.NotNil(t, result.Trends.PlayTimeTrend)
|
|
assert.NotNil(t, result.Trends.CompletionTrend)
|
|
}
|
|
} else {
|
|
// Si moins de 2 périodes, les tendances ne sont pas calculées
|
|
assert.Nil(t, result.Trends)
|
|
}
|
|
}
|
|
|
|
func TestPlaybackAggregationService_AggregateByDateRange(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
sessions := []models.PlaybackAnalytics{
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 120,
|
|
PauseCount: 2,
|
|
SeekCount: 3,
|
|
CompletionRate: 75.0,
|
|
StartedAt: now.AddDate(0, 0, -2),
|
|
CreatedAt: now.AddDate(0, 0, -2),
|
|
},
|
|
{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 150,
|
|
PauseCount: 1,
|
|
SeekCount: 2,
|
|
CompletionRate: 90.0,
|
|
StartedAt: now.AddDate(0, 0, -1),
|
|
CreatedAt: now.AddDate(0, 0, -1),
|
|
},
|
|
}
|
|
for _, session := range sessions {
|
|
db.Create(&session)
|
|
}
|
|
|
|
startDate := now.AddDate(0, 0, -3)
|
|
endDate := now
|
|
|
|
result, err := service.AggregateByDateRange(context.Background(), track.ID, startDate, endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, int64(2), result.Sessions)
|
|
assert.Equal(t, int64(270), result.TotalPlayTime)
|
|
assert.InDelta(t, 135.0, result.AveragePlayTime, 0.1)
|
|
assert.InDelta(t, 82.5, result.AverageCompletion, 0.1)
|
|
}
|
|
|
|
func TestPlaybackAggregationService_GetTopTracksByPlayback(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
userID := uuid.New()
|
|
user := &models.User{ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
|
|
// Créer plusieurs tracks
|
|
track1ID := uuid.New()
|
|
track2ID := uuid.New()
|
|
tracks := []models.Track{
|
|
{ID: track1ID, UserID: userID, Title: "Track 1", FilePath: "/1.mp3", FileSize: 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: models.TrackStatusCompleted},
|
|
{ID: track2ID, UserID: userID, Title: "Track 2", FilePath: "/2.mp3", FileSize: 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: models.TrackStatusCompleted},
|
|
}
|
|
for _, track := range tracks {
|
|
db.Create(&track)
|
|
}
|
|
|
|
now := time.Now()
|
|
// Créer plus de sessions pour le track 1
|
|
sessions := []models.PlaybackAnalytics{
|
|
{TrackID: track1ID, UserID: userID, PlayTime: 120, CompletionRate: 75.0, StartedAt: now, CreatedAt: now},
|
|
{TrackID: track1ID, UserID: userID, PlayTime: 150, CompletionRate: 90.0, StartedAt: now, CreatedAt: now},
|
|
{TrackID: track2ID, UserID: userID, PlayTime: 100, CompletionRate: 60.0, StartedAt: now, CreatedAt: now},
|
|
}
|
|
for _, session := range sessions {
|
|
db.Create(&session)
|
|
}
|
|
|
|
result, err := service.GetTopTracksByPlayback(context.Background(), 10, nil, nil)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Len(t, result, 2)
|
|
|
|
// Vérifier que le track 1 est en premier (plus de sessions)
|
|
// track_id is now uuid.UUID, not int64
|
|
trackID, ok := result[0]["track_id"].(uuid.UUID)
|
|
require.True(t, ok, "track_id should be uuid.UUID")
|
|
assert.Equal(t, track1ID, trackID)
|
|
assert.Equal(t, int64(2), result[0]["sessions"])
|
|
}
|
|
|
|
func TestPlaybackAggregationService_GetTopTracksByPlayback_WithDateRange(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
now := time.Now()
|
|
startDate := now.AddDate(0, 0, -7)
|
|
endDate := now
|
|
|
|
// Créer une session dans la plage
|
|
session := models.PlaybackAnalytics{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
PlayTime: 120,
|
|
CompletionRate: 75.0,
|
|
StartedAt: now.AddDate(0, 0, -3),
|
|
CreatedAt: now.AddDate(0, 0, -3),
|
|
}
|
|
db.Create(&session)
|
|
|
|
result, err := service.GetTopTracksByPlayback(context.Background(), 10, &startDate, &endDate)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Len(t, result, 1)
|
|
assert.Equal(t, track.ID, result[0]["track_id"])
|
|
}
|
|
|
|
func TestPlaybackAggregationService_GetTopTracksByPlayback_DefaultLimit(t *testing.T) {
|
|
db := setupTestPlaybackAggregationServiceDB(t)
|
|
logger := zaptest.NewLogger(t)
|
|
service := NewPlaybackAggregationService(db, logger)
|
|
|
|
user := &models.User{ID: uuid.New(), Username: "testuser", Email: "test@example.com", IsActive: true}
|
|
db.Create(user)
|
|
|
|
// Créer plusieurs tracks
|
|
for i := 1; i <= 15; i++ {
|
|
trackID := uuid.New()
|
|
track := models.Track{
|
|
ID: trackID,
|
|
UserID: user.ID,
|
|
Title: "Track " + string(rune(i)),
|
|
FilePath: "/test.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(&track)
|
|
|
|
session := models.PlaybackAnalytics{
|
|
TrackID: trackID,
|
|
UserID: user.ID,
|
|
PlayTime: 120,
|
|
CompletionRate: 75.0,
|
|
StartedAt: time.Now(),
|
|
CreatedAt: time.Now(),
|
|
}
|
|
db.Create(&session)
|
|
}
|
|
|
|
result, err := service.GetTopTracksByPlayback(context.Background(), 0, nil, nil)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
// Devrait utiliser la limite par défaut de 10
|
|
assert.LessOrEqual(t, len(result), 10)
|
|
}
|