package models import ( "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" "gorm.io/driver/sqlite" "gorm.io/gorm" ) func setupTestTrackLikeDB(t *testing.T) (*gorm.DB, func()) { // Setup in-memory SQLite database db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) assert.NoError(t, err) db.Exec("PRAGMA foreign_keys = ON") sqlDB, _ := db.DB() sqlDB.SetMaxOpenConns(1) // Auto-migrate err = db.AutoMigrate(&User{}, &Track{}, &TrackLike{}) assert.NoError(t, err) // Cleanup function cleanup := func() { // Database will be closed automatically } return db, cleanup } func TestTrackLike_Create(t *testing.T) { db, cleanup := setupTestTrackLikeDB(t) defer cleanup() userID := uuid.New() // Create test user user := &User{ ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true, } err := db.Create(user).Error assert.NoError(t, err) // Create test track track := &Track{ UserID: userID, Title: "Test Track", FilePath: "/test/track.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track).Error assert.NoError(t, err) // Create track like trackLike := &TrackLike{ UserID: userID, TrackID: track.ID, } err = db.Create(trackLike).Error assert.NoError(t, err) // Verify track like was created var createdLike TrackLike err = db.First(&createdLike, trackLike.ID).Error assert.NoError(t, err) assert.Equal(t, userID, createdLike.UserID) assert.Equal(t, track.ID, createdLike.TrackID) assert.NotZero(t, createdLike.CreatedAt) } func TestTrackLike_UniqueConstraint(t *testing.T) { db, cleanup := setupTestTrackLikeDB(t) defer cleanup() userID := uuid.New() // Create test user user := &User{ ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true, } err := db.Create(user).Error assert.NoError(t, err) // Create test track track := &Track{ UserID: userID, Title: "Test Track", FilePath: "/test/track.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track).Error assert.NoError(t, err) // Create first track like trackLike1 := &TrackLike{ UserID: userID, TrackID: track.ID, } err = db.Create(trackLike1).Error assert.NoError(t, err) // Try to create duplicate like (should fail due to unique constraint) trackLike2 := &TrackLike{ UserID: userID, TrackID: track.ID, } err = db.Create(trackLike2).Error assert.Error(t, err) // SQLite doesn't enforce unique constraints the same way as PostgreSQL, // but GORM should still catch this } func TestTrackLike_Relations(t *testing.T) { db, cleanup := setupTestTrackLikeDB(t) defer cleanup() userID := uuid.New() // Create test user user := &User{ ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true, } err := db.Create(user).Error assert.NoError(t, err) // Create test track track := &Track{ UserID: userID, Title: "Test Track", FilePath: "/test/track.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track).Error assert.NoError(t, err) // Create track like trackLike := &TrackLike{ UserID: userID, TrackID: track.ID, } err = db.Create(trackLike).Error assert.NoError(t, err) // Test relation with User var likeWithUser TrackLike err = db.Preload("User").First(&likeWithUser, trackLike.ID).Error assert.NoError(t, err) assert.Equal(t, "testuser", likeWithUser.User.Username) assert.Equal(t, "test@example.com", likeWithUser.User.Email) // Test relation with Track var likeWithTrack TrackLike err = db.Preload("Track").First(&likeWithTrack, trackLike.ID).Error assert.NoError(t, err) assert.Equal(t, "Test Track", likeWithTrack.Track.Title) assert.Equal(t, userID, likeWithTrack.Track.UserID) } func TestTrackLike_CascadeDelete(t *testing.T) { db, cleanup := setupTestTrackLikeDB(t) defer cleanup() userID := uuid.New() // Create test user user := &User{ ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true, } err := db.Create(user).Error assert.NoError(t, err) // Create test track track := &Track{ UserID: userID, Title: "Test Track", FilePath: "/test/track.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track).Error assert.NoError(t, err) // Create track like trackLike := &TrackLike{ UserID: userID, TrackID: track.ID, } err = db.Create(trackLike).Error assert.NoError(t, err) // Delete track (should cascade delete the like) err = db.Unscoped().Delete(track).Error assert.NoError(t, err) // Verify like was deleted var deletedLike TrackLike err = db.First(&deletedLike, trackLike.ID).Error assert.Error(t, err) assert.Equal(t, gorm.ErrRecordNotFound, err) } func TestTrackLike_TableName(t *testing.T) { trackLike := TrackLike{} assert.Equal(t, "track_likes", trackLike.TableName()) } func TestTrackLike_Indexes(t *testing.T) { db, cleanup := setupTestTrackLikeDB(t) defer cleanup() userID1 := uuid.New() userID2 := uuid.New() // Create test users user1 := &User{ ID: userID1, Username: "testuser1", Email: "test1@example.com", IsActive: true, } err := db.Create(user1).Error assert.NoError(t, err) user2 := &User{ ID: userID2, Username: "testuser2", Email: "test2@example.com", IsActive: true, } err = db.Create(user2).Error assert.NoError(t, err) // Create test tracks track1 := &Track{ UserID: userID1, Title: "Track 1", FilePath: "/test/track1.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track1).Error assert.NoError(t, err) track2 := &Track{ UserID: userID1, Title: "Track 2", FilePath: "/test/track2.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track2).Error assert.NoError(t, err) // Create multiple likes like1 := &TrackLike{UserID: userID1, TrackID: track1.ID} err = db.Create(like1).Error assert.NoError(t, err) like2 := &TrackLike{UserID: userID1, TrackID: track2.ID} err = db.Create(like2).Error assert.NoError(t, err) like3 := &TrackLike{UserID: userID2, TrackID: track1.ID} err = db.Create(like3).Error assert.NoError(t, err) // Test query by user_id (should use index) var userLikes []TrackLike err = db.Where("user_id = ?", userID1).Find(&userLikes).Error assert.NoError(t, err) assert.Equal(t, 2, len(userLikes)) // Test query by track_id (should use index) var trackLikes []TrackLike err = db.Where("track_id = ?", track1.ID).Find(&trackLikes).Error assert.NoError(t, err) assert.Equal(t, 2, len(trackLikes)) } func TestTrackLike_CreatedAt(t *testing.T) { db, cleanup := setupTestTrackLikeDB(t) defer cleanup() userID := uuid.New() // Create test user user := &User{ ID: userID, Username: "testuser", Email: "test@example.com", IsActive: true, } err := db.Create(user).Error assert.NoError(t, err) // Create test track track := &Track{ UserID: userID, Title: "Test Track", FilePath: "/test/track.mp3", FileSize: 5 * 1024 * 1024, Format: "MP3", Duration: 180, IsPublic: true, Status: TrackStatusCompleted, } err = db.Create(track).Error assert.NoError(t, err) // Create track like beforeCreate := time.Now() trackLike := &TrackLike{ UserID: userID, TrackID: track.ID, } err = db.Create(trackLike).Error assert.NoError(t, err) afterCreate := time.Now() // Verify CreatedAt is set assert.WithinDuration(t, beforeCreate, trackLike.CreatedAt, time.Second) assert.WithinDuration(t, afterCreate, trackLike.CreatedAt, time.Second) }