veza/veza-backend-api/internal/services/track_share_service_test.go

242 lines
6.3 KiB
Go

package services
import (
"context"
"errors"
"github.com/google/uuid"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"veza-backend-api/internal/models"
)
func setupTestTrackShareService(t *testing.T) (*TrackShareService, *gorm.DB, uuid.UUID, func()) {
// Setup in-memory SQLite database
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
// Auto-migrate
err = db.AutoMigrate(&models.TrackShare{}, &models.Track{}, &models.User{})
require.NoError(t, err)
// Create test user
userID := uuid.New()
user := &models.User{
ID: userID,
Username: "testuser",
Email: "test@example.com",
IsActive: true,
}
err = db.Create(user).Error
require.NoError(t, err)
// Setup service
// TrackShareService might need logger too?
// The original test didn't pass one, assuming NewTrackShareService(db) only.
// Checking the file content, it was: NewTrackShareService(db)
service := NewTrackShareService(db)
// Cleanup function
cleanup := func() {
// Database will be closed automatically
}
return service, db, userID, cleanup
}
func TestTrackShareService_CreateShare(t *testing.T) {
service, db, userID, cleanup := setupTestTrackShareService(t)
defer cleanup()
ctx := context.Background()
// Create test track
track := &models.Track{
UserID: userID,
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
require.NoError(t, err)
// Create share
share, err := service.CreateShare(ctx, track.ID, userID, "read,download", nil)
assert.NoError(t, err)
assert.NotNil(t, share)
assert.Equal(t, track.ID, share.TrackID)
assert.Equal(t, userID, share.UserID)
assert.Equal(t, "read,download", share.Permissions)
assert.NotEmpty(t, share.ShareToken)
}
func TestTrackShareService_CreateShare_NotOwner(t *testing.T) {
service, db, userID, cleanup := setupTestTrackShareService(t)
defer cleanup()
ctx := context.Background()
// Create test track
track := &models.Track{
UserID: userID,
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
require.NoError(t, err)
// Try to create share as different user
share, err := service.CreateShare(ctx, track.ID, uuid.New(), "read,download", nil)
assert.Error(t, err)
assert.Nil(t, share)
assert.Equal(t, ErrForbidden, err)
}
func TestTrackShareService_ValidateShareToken(t *testing.T) {
service, db, userID, cleanup := setupTestTrackShareService(t)
defer cleanup()
ctx := context.Background()
// Create test track
track := &models.Track{
UserID: userID,
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
require.NoError(t, err)
// Create share
share, err := service.CreateShare(ctx, track.ID, userID, "read,download", nil)
require.NoError(t, err)
// Validate token
validatedShare, err := service.ValidateShareToken(ctx, share.ShareToken)
assert.NoError(t, err)
assert.NotNil(t, validatedShare)
assert.Equal(t, share.ID, validatedShare.ID)
assert.Equal(t, int64(1), validatedShare.AccessCount) // Should be incremented
}
func TestTrackShareService_ValidateShareToken_Expired(t *testing.T) {
service, db, userID, cleanup := setupTestTrackShareService(t)
defer cleanup()
ctx := context.Background()
// Create test track
track := &models.Track{
UserID: userID,
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
require.NoError(t, err)
// Create share with expiration in the past
expiredTime := time.Now().Add(-1 * time.Hour)
share := &models.TrackShare{
TrackID: track.ID,
UserID: userID,
ShareToken: "test-token-123",
Permissions: "read,download",
ExpiresAt: &expiredTime,
AccessCount: 0,
}
err = db.Create(share).Error
require.NoError(t, err)
// Try to validate expired token
validatedShare, err := service.ValidateShareToken(ctx, share.ShareToken)
assert.Error(t, err)
assert.Nil(t, validatedShare)
assert.Equal(t, ErrShareExpired, err)
}
func TestTrackShareService_CheckPermission(t *testing.T) {
service, _, _, cleanup := setupTestTrackShareService(t)
defer cleanup()
// Test with read permission
share := &models.TrackShare{
Permissions: "read",
ExpiresAt: nil,
}
assert.True(t, service.CheckPermission(share, "read"))
assert.False(t, service.CheckPermission(share, "download"))
// Test with download permission
share.Permissions = "download"
assert.False(t, service.CheckPermission(share, "read"))
assert.True(t, service.CheckPermission(share, "download"))
// Test with both permissions
share.Permissions = "read,download"
assert.True(t, service.CheckPermission(share, "read"))
assert.True(t, service.CheckPermission(share, "download"))
// Test with expired share
expiredTime := time.Now().Add(-1 * time.Hour)
share.ExpiresAt = &expiredTime
assert.False(t, service.CheckPermission(share, "read"))
assert.False(t, service.CheckPermission(share, "download"))
}
func TestTrackShareService_RevokeShare(t *testing.T) {
service, db, userID, cleanup := setupTestTrackShareService(t)
defer cleanup()
ctx := context.Background()
// Create test track
track := &models.Track{
UserID: userID,
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
require.NoError(t, err)
// Create share
share, err := service.CreateShare(ctx, track.ID, userID, "read,download", nil)
require.NoError(t, err)
// Revoke share
err = service.RevokeShare(ctx, share.ID, userID)
assert.NoError(t, err)
// Verify share is deleted
var deletedShare models.TrackShare
err = db.First(&deletedShare, "id = ?", share.ID).Error
assert.Error(t, err)
assert.True(t, errors.Is(err, gorm.ErrRecordNotFound))
}