318 lines
7.9 KiB
Go
318 lines
7.9 KiB
Go
package models
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestTrackShare(t *testing.T) {
|
|
// Setup in-memory database
|
|
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(&User{}, &Track{}, &TrackShare{})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("Create TrackShare with all fields", func(t *testing.T) {
|
|
// Create user
|
|
user := &User{
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
PasswordHash: "hash",
|
|
Slug: "testuser",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track
|
|
track := &Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/test/track.mp3",
|
|
FileSize: 5 * 1024 * 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: TrackStatusCompleted,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track share
|
|
expiresAt := time.Now().Add(24 * time.Hour)
|
|
trackShare := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "test-token-123",
|
|
Permissions: "read,download",
|
|
ExpiresAt: &expiresAt,
|
|
AccessCount: 0,
|
|
}
|
|
err = db.Create(trackShare).Error
|
|
require.NoError(t, err)
|
|
|
|
assert.NotZero(t, trackShare.ID)
|
|
assert.Equal(t, track.ID, trackShare.TrackID)
|
|
assert.Equal(t, user.ID, trackShare.UserID)
|
|
assert.Equal(t, "test-token-123", trackShare.ShareToken)
|
|
assert.Equal(t, "read,download", trackShare.Permissions)
|
|
assert.NotNil(t, trackShare.ExpiresAt)
|
|
assert.Equal(t, int64(0), trackShare.AccessCount)
|
|
assert.False(t, trackShare.CreatedAt.IsZero())
|
|
assert.False(t, trackShare.UpdatedAt.IsZero())
|
|
})
|
|
|
|
t.Run("Create TrackShare without expiration", func(t *testing.T) {
|
|
// Create user
|
|
user := &User{
|
|
Username: "testuser2",
|
|
Email: "test2@example.com",
|
|
PasswordHash: "hash",
|
|
Slug: "testuser2",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track
|
|
track := &Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track 2",
|
|
FilePath: "/test/track2.mp3",
|
|
FileSize: 5 * 1024 * 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: TrackStatusCompleted,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track share without expiration
|
|
trackShare := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "test-token-456",
|
|
Permissions: "read",
|
|
ExpiresAt: nil,
|
|
AccessCount: 0,
|
|
}
|
|
err = db.Create(trackShare).Error
|
|
require.NoError(t, err)
|
|
|
|
assert.NotZero(t, trackShare.ID)
|
|
assert.Nil(t, trackShare.ExpiresAt)
|
|
assert.Equal(t, "read", trackShare.Permissions)
|
|
})
|
|
|
|
t.Run("TrackShare with unique share_token constraint", func(t *testing.T) {
|
|
// Create user
|
|
user := &User{
|
|
Username: "testuser3",
|
|
Email: "test3@example.com",
|
|
PasswordHash: "hash",
|
|
Slug: "testuser3",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track
|
|
track := &Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track 3",
|
|
FilePath: "/test/track3.mp3",
|
|
FileSize: 5 * 1024 * 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: TrackStatusCompleted,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create first track share
|
|
trackShare1 := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "unique-token-123",
|
|
Permissions: "read",
|
|
}
|
|
err = db.Create(trackShare1).Error
|
|
require.NoError(t, err)
|
|
|
|
// Try to create second track share with same token
|
|
trackShare2 := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "unique-token-123",
|
|
Permissions: "read",
|
|
}
|
|
err = db.Create(trackShare2).Error
|
|
assert.Error(t, err) // Should fail due to unique constraint
|
|
})
|
|
|
|
t.Run("TrackShare cascade delete on track deletion", func(t *testing.T) {
|
|
// Create user
|
|
user := &User{
|
|
Username: "testuser4",
|
|
Email: "test4@example.com",
|
|
PasswordHash: "hash",
|
|
Slug: "testuser4",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track
|
|
track := &Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track 4",
|
|
FilePath: "/test/track4.mp3",
|
|
FileSize: 5 * 1024 * 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: TrackStatusCompleted,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track share
|
|
trackShare := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "cascade-token-123",
|
|
Permissions: "read",
|
|
}
|
|
err = db.Create(trackShare).Error
|
|
require.NoError(t, err)
|
|
|
|
shareID := trackShare.ID
|
|
|
|
// Delete track (hard delete)
|
|
err = db.Unscoped().Delete(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Verify track share is also deleted (cascade)
|
|
// Note: SQLite in-memory may not enforce foreign key constraints the same way as PostgreSQL
|
|
// So we check if the share still exists or was soft-deleted
|
|
var deletedShare TrackShare
|
|
err = db.Unscoped().First(&deletedShare, shareID).Error
|
|
// The share should be deleted (either hard or soft delete depending on DB behavior)
|
|
// In production with PostgreSQL, it will be hard deleted due to CASCADE
|
|
if err == nil {
|
|
// If still exists, verify it's at least soft-deleted
|
|
assert.NotNil(t, deletedShare.DeletedAt)
|
|
} else {
|
|
// If not found, it was hard deleted (expected behavior)
|
|
assert.Equal(t, gorm.ErrRecordNotFound, err)
|
|
}
|
|
})
|
|
|
|
t.Run("TrackShare TableName", func(t *testing.T) {
|
|
share := &TrackShare{}
|
|
assert.Equal(t, "track_shares", share.TableName())
|
|
})
|
|
|
|
t.Run("TrackShare with different permissions", func(t *testing.T) {
|
|
// Create user
|
|
user := &User{
|
|
Username: "testuser5",
|
|
Email: "test5@example.com",
|
|
PasswordHash: "hash",
|
|
Slug: "testuser5",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track
|
|
track := &Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track 5",
|
|
FilePath: "/test/track5.mp3",
|
|
FileSize: 5 * 1024 * 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: TrackStatusCompleted,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Test different permission values
|
|
permissions := []string{"read", "download", "read,download"}
|
|
|
|
for i, perm := range permissions {
|
|
trackShare := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "perm-token-" + string(rune(i)),
|
|
Permissions: perm,
|
|
}
|
|
err = db.Create(trackShare).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, perm, trackShare.Permissions)
|
|
}
|
|
})
|
|
|
|
t.Run("TrackShare increment access_count", func(t *testing.T) {
|
|
// Create user
|
|
user := &User{
|
|
Username: "testuser6",
|
|
Email: "test6@example.com",
|
|
PasswordHash: "hash",
|
|
Slug: "testuser6",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track
|
|
track := &Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track 6",
|
|
FilePath: "/test/track6.mp3",
|
|
FileSize: 5 * 1024 * 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: TrackStatusCompleted,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create track share
|
|
trackShare := &TrackShare{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
ShareToken: "access-token-123",
|
|
Permissions: "read",
|
|
AccessCount: 0,
|
|
}
|
|
err = db.Create(trackShare).Error
|
|
require.NoError(t, err)
|
|
|
|
// Increment access count
|
|
trackShare.AccessCount++
|
|
err = db.Save(trackShare).Error
|
|
require.NoError(t, err)
|
|
|
|
// Verify access count was incremented
|
|
var updatedShare TrackShare
|
|
err = db.First(&updatedShare, trackShare.ID).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), updatedShare.AccessCount)
|
|
})
|
|
}
|