350 lines
8.6 KiB
Go
350 lines
8.6 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"github.com/google/uuid"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
func setupTestPlaylistAnalyticsService(t *testing.T) (*PlaylistAnalyticsService, *gorm.DB, 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.Track{},
|
|
&models.Playlist{},
|
|
&models.PlaylistTrack{},
|
|
&models.PlaylistShareLink{},
|
|
&models.PlaylistFollow{},
|
|
&models.TrackPlay{},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
logger := zap.NewNop()
|
|
service := NewPlaylistAnalyticsService(db, logger)
|
|
|
|
cleanup := func() {
|
|
// Database will be closed automatically
|
|
}
|
|
|
|
return service, db, cleanup
|
|
}
|
|
|
|
func TestPlaylistAnalyticsService_GetPlaylistStats(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistAnalyticsService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &models.User{
|
|
Username: "user1",
|
|
Email: "user1@example.com",
|
|
PasswordHash: "hash1",
|
|
Slug: "user1",
|
|
IsActive: true,
|
|
}
|
|
require.NoError(t, db.Create(user).Error)
|
|
|
|
// Create test tracks
|
|
track1 := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Track 1",
|
|
FilePath: "/path/to/track1.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
PlayCount: 0,
|
|
LikeCount: 0,
|
|
}
|
|
track2 := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Track 2",
|
|
FilePath: "/path/to/track2.mp3",
|
|
FileSize: 2048,
|
|
Format: "MP3",
|
|
Duration: 240,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
PlayCount: 0,
|
|
LikeCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(track1).Error)
|
|
require.NoError(t, db.Create(track2).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
TrackCount: 2,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Add tracks to playlist
|
|
playlistTrack1 := &models.PlaylistTrack{
|
|
PlaylistID: playlist.ID,
|
|
TrackID: track1.ID,
|
|
Position: 1,
|
|
}
|
|
playlistTrack2 := &models.PlaylistTrack{
|
|
PlaylistID: playlist.ID,
|
|
TrackID: track2.ID,
|
|
Position: 2,
|
|
}
|
|
require.NoError(t, db.Create(playlistTrack1).Error)
|
|
require.NoError(t, db.Create(playlistTrack2).Error)
|
|
|
|
// Create some track plays
|
|
play1 := &models.TrackPlay{
|
|
TrackID: track1.ID,
|
|
UserID: &user.ID,
|
|
Duration: 180,
|
|
}
|
|
play2 := &models.TrackPlay{
|
|
TrackID: track1.ID,
|
|
UserID: &user.ID,
|
|
Duration: 150,
|
|
}
|
|
play3 := &models.TrackPlay{
|
|
TrackID: track2.ID,
|
|
UserID: &user.ID,
|
|
Duration: 240,
|
|
}
|
|
require.NoError(t, db.Create(play1).Error)
|
|
require.NoError(t, db.Create(play2).Error)
|
|
require.NoError(t, db.Create(play3).Error)
|
|
|
|
// Create share link
|
|
shareLink := &models.PlaylistShareLink{
|
|
PlaylistID: playlist.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "test-token-123",
|
|
AccessCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(shareLink).Error)
|
|
|
|
// Create follow
|
|
follow := &models.PlaylistFollow{
|
|
PlaylistID: playlist.ID,
|
|
UserID: user.ID,
|
|
}
|
|
require.NoError(t, db.Create(follow).Error)
|
|
|
|
// Update follower count
|
|
playlist.FollowerCount = 1
|
|
require.NoError(t, db.Save(playlist).Error)
|
|
|
|
// Get stats
|
|
stats, err := service.GetPlaylistStats(ctx, playlist.ID)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, stats)
|
|
|
|
// Verify stats
|
|
assert.Equal(t, int64(3), stats.Plays) // 3 plays total (2 for track1, 1 for track2)
|
|
assert.Equal(t, int64(1), stats.Shares) // 1 share link
|
|
assert.Equal(t, int64(1), stats.Likes) // 1 follow
|
|
assert.Equal(t, int64(1), stats.Followers) // 1 follower
|
|
assert.Equal(t, 2, stats.TrackCount) // 2 tracks
|
|
}
|
|
|
|
func TestPlaylistAnalyticsService_GetPlaylistStats_NotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestPlaylistAnalyticsService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Get stats for non-existent playlist
|
|
stats, err := service.GetPlaylistStats(ctx, uuid.New())
|
|
assert.Error(t, err)
|
|
assert.Nil(t, stats)
|
|
assert.Equal(t, "playlist not found", err.Error())
|
|
}
|
|
|
|
func TestPlaylistAnalyticsService_GetPlaylistStats_EmptyPlaylist(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistAnalyticsService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &models.User{
|
|
Username: "user1",
|
|
Email: "user1@example.com",
|
|
PasswordHash: "hash1",
|
|
Slug: "user1",
|
|
IsActive: true,
|
|
}
|
|
require.NoError(t, db.Create(user).Error)
|
|
|
|
// Create empty playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user.ID,
|
|
Title: "Empty Playlist",
|
|
Description: "An empty playlist",
|
|
IsPublic: true,
|
|
TrackCount: 0,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Get stats
|
|
stats, err := service.GetPlaylistStats(ctx, playlist.ID)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, stats)
|
|
|
|
// Verify stats for empty playlist
|
|
assert.Equal(t, int64(0), stats.Plays)
|
|
assert.Equal(t, int64(0), stats.Shares)
|
|
assert.Equal(t, int64(0), stats.Likes)
|
|
assert.Equal(t, int64(0), stats.Followers)
|
|
assert.Equal(t, 0, stats.TrackCount)
|
|
}
|
|
|
|
func TestPlaylistAnalyticsService_GetPlaylistStats_MultipleShares(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistAnalyticsService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create test user
|
|
user := &models.User{
|
|
Username: "user1",
|
|
Email: "user1@example.com",
|
|
PasswordHash: "hash1",
|
|
Slug: "user1",
|
|
IsActive: true,
|
|
}
|
|
require.NoError(t, db.Create(user).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
TrackCount: 0,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Create multiple share links
|
|
shareLink1 := &models.PlaylistShareLink{
|
|
PlaylistID: playlist.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "token-1",
|
|
AccessCount: 0,
|
|
}
|
|
shareLink2 := &models.PlaylistShareLink{
|
|
PlaylistID: playlist.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "token-2",
|
|
AccessCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(shareLink1).Error)
|
|
require.NoError(t, db.Create(shareLink2).Error)
|
|
|
|
// Get stats
|
|
stats, err := service.GetPlaylistStats(ctx, playlist.ID)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, stats)
|
|
|
|
// Verify shares count
|
|
assert.Equal(t, int64(2), stats.Shares)
|
|
}
|
|
|
|
func TestPlaylistAnalyticsService_GetPlaylistStats_MultipleFollows(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistAnalyticsService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// 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,
|
|
}
|
|
user3 := &models.User{
|
|
Username: "user3",
|
|
Email: "user3@example.com",
|
|
PasswordHash: "hash3",
|
|
Slug: "user3",
|
|
IsActive: true,
|
|
}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
require.NoError(t, db.Create(user2).Error)
|
|
require.NoError(t, db.Create(user3).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user1.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
TrackCount: 0,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Create multiple follows
|
|
follow1 := &models.PlaylistFollow{
|
|
PlaylistID: playlist.ID,
|
|
UserID: user2.ID,
|
|
}
|
|
follow2 := &models.PlaylistFollow{
|
|
PlaylistID: playlist.ID,
|
|
UserID: user3.ID,
|
|
}
|
|
require.NoError(t, db.Create(follow1).Error)
|
|
require.NoError(t, db.Create(follow2).Error)
|
|
|
|
// Update follower count
|
|
playlist.FollowerCount = 2
|
|
require.NoError(t, db.Save(playlist).Error)
|
|
|
|
// Get stats
|
|
stats, err := service.GetPlaylistStats(ctx, playlist.ID)
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, stats)
|
|
|
|
// Verify follows count
|
|
assert.Equal(t, int64(2), stats.Likes)
|
|
assert.Equal(t, int64(2), stats.Followers)
|
|
}
|
|
|
|
func TestPlaylistAnalyticsService_IncrementPlaylistPlays(t *testing.T) {
|
|
service, _, cleanup := setupTestPlaylistAnalyticsService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Test increment (should not error, but doesn't do anything for now)
|
|
err := service.IncrementPlaylistPlays(ctx, uuid.New())
|
|
assert.NoError(t, err)
|
|
}
|