427 lines
10 KiB
Go
427 lines
10 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 setupTestTrackHistoryService(t *testing.T) (*TrackHistoryService, *gorm.DB, func()) {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
err = db.AutoMigrate(&models.User{}, &models.Track{}, &models.TrackHistory{})
|
|
require.NoError(t, err)
|
|
|
|
logger := zap.NewNop()
|
|
service := NewTrackHistoryService(db, logger)
|
|
|
|
cleanup := func() {
|
|
// No cleanup needed for in-memory database
|
|
}
|
|
|
|
return service, db, cleanup
|
|
}
|
|
|
|
func TestTrackHistoryService_RecordHistory(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create user
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user)
|
|
|
|
// Create track
|
|
track := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/path/to/track.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
// Record history
|
|
params := RecordHistoryParams{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
Action: models.TrackHistoryActionCreated,
|
|
OldValue: nil,
|
|
NewValue: map[string]interface{}{"title": "Test Track"},
|
|
}
|
|
|
|
history, err := service.RecordHistory(ctx, params)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, history)
|
|
assert.Equal(t, track.ID, history.TrackID)
|
|
assert.Equal(t, user.ID, history.UserID)
|
|
assert.Equal(t, models.TrackHistoryActionCreated, history.Action)
|
|
assert.NotEmpty(t, history.NewValue)
|
|
}
|
|
|
|
func TestTrackHistoryService_RecordHistory_TrackNotFound(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create user
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user)
|
|
|
|
// Record history with non-existent track
|
|
params := RecordHistoryParams{
|
|
TrackID: uuid.New(),
|
|
UserID: user.ID,
|
|
Action: models.TrackHistoryActionCreated,
|
|
OldValue: nil,
|
|
NewValue: map[string]interface{}{"title": "Test Track"},
|
|
}
|
|
|
|
_, err := service.RecordHistory(ctx, params)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, ErrTrackNotFound)
|
|
}
|
|
|
|
func TestTrackHistoryService_RecordHistory_WithStringValues(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create user
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user)
|
|
|
|
// Create track
|
|
track := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/path/to/track.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
// Record history with string values
|
|
params := RecordHistoryParams{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
Action: models.TrackHistoryActionUpdated,
|
|
OldValue: "Old Title",
|
|
NewValue: "New Title",
|
|
}
|
|
|
|
history, err := service.RecordHistory(ctx, params)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, history)
|
|
assert.Contains(t, history.OldValue, "Old Title")
|
|
assert.Contains(t, history.NewValue, "New Title")
|
|
}
|
|
|
|
func TestTrackHistoryService_GetHistory(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create user
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user)
|
|
|
|
// Create track
|
|
track := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/path/to/track.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
// Record multiple history entries
|
|
for i := 0; i < 5; i++ {
|
|
params := RecordHistoryParams{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
Action: models.TrackHistoryActionUpdated,
|
|
OldValue: map[string]interface{}{"iteration": i},
|
|
NewValue: map[string]interface{}{"iteration": i + 1},
|
|
}
|
|
_, err := service.RecordHistory(ctx, params)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get history
|
|
histories, total, err := service.GetHistory(ctx, track.ID, 10, 0)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(5), total)
|
|
assert.Len(t, histories, 5)
|
|
|
|
// Verify ordering (should be DESC by created_at)
|
|
for i := 0; i < len(histories)-1; i++ {
|
|
assert.True(t, histories[i].CreatedAt.After(histories[i+1].CreatedAt) || histories[i].CreatedAt.Equal(histories[i+1].CreatedAt))
|
|
}
|
|
}
|
|
|
|
func TestTrackHistoryService_GetHistory_WithPagination(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create user
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user)
|
|
|
|
// Create track
|
|
track := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/path/to/track.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
// Record multiple history entries
|
|
for i := 0; i < 10; i++ {
|
|
params := RecordHistoryParams{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
Action: models.TrackHistoryActionUpdated,
|
|
OldValue: map[string]interface{}{"iteration": i},
|
|
NewValue: map[string]interface{}{"iteration": i + 1},
|
|
}
|
|
_, err := service.RecordHistory(ctx, params)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get first page
|
|
histories, total, err := service.GetHistory(ctx, track.ID, 5, 0)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(10), total)
|
|
assert.Len(t, histories, 5)
|
|
|
|
// Get second page
|
|
histories2, total2, err := service.GetHistory(ctx, track.ID, 5, 5)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(10), total2)
|
|
assert.Len(t, histories2, 5)
|
|
|
|
// Verify no overlap
|
|
assert.NotEqual(t, histories[0].ID, histories2[0].ID)
|
|
}
|
|
|
|
func TestTrackHistoryService_GetHistory_TrackNotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
_, _, err := service.GetHistory(ctx, uuid.New(), 10, 0)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, ErrTrackNotFound)
|
|
}
|
|
|
|
func TestTrackHistoryService_GetHistoryByUser(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create users
|
|
user1 := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "user1",
|
|
Email: "user1@example.com",
|
|
IsActive: true,
|
|
}
|
|
user2 := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "user2",
|
|
Email: "user2@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user1)
|
|
db.Create(user2)
|
|
|
|
// Create tracks
|
|
track1 := &models.Track{
|
|
UserID: user1.ID,
|
|
Title: "Track 1",
|
|
FilePath: "/path/to/track1.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
track2 := &models.Track{
|
|
UserID: user2.ID,
|
|
Title: "Track 2",
|
|
FilePath: "/path/to/track2.mp3",
|
|
FileSize: 2048,
|
|
Format: "MP3",
|
|
Duration: 240,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track1)
|
|
db.Create(track2)
|
|
|
|
// Record history for user1
|
|
for i := 0; i < 3; i++ {
|
|
params := RecordHistoryParams{
|
|
TrackID: track1.ID,
|
|
UserID: user1.ID,
|
|
Action: models.TrackHistoryActionUpdated,
|
|
OldValue: map[string]interface{}{"iteration": i},
|
|
NewValue: map[string]interface{}{"iteration": i + 1},
|
|
}
|
|
_, err := service.RecordHistory(ctx, params)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Record history for user2
|
|
for i := 0; i < 2; i++ {
|
|
params := RecordHistoryParams{
|
|
TrackID: track2.ID,
|
|
UserID: user2.ID,
|
|
Action: models.TrackHistoryActionUpdated,
|
|
OldValue: map[string]interface{}{"iteration": i},
|
|
NewValue: map[string]interface{}{"iteration": i + 1},
|
|
}
|
|
_, err := service.RecordHistory(ctx, params)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get history for user1
|
|
histories, total, err := service.GetHistoryByUser(ctx, user1.ID, 10, 0)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(3), total)
|
|
assert.Len(t, histories, 3)
|
|
|
|
// Verify all entries belong to user1
|
|
for _, h := range histories {
|
|
assert.Equal(t, user1.ID, h.UserID)
|
|
}
|
|
}
|
|
|
|
func TestTrackHistoryService_GetHistoryByAction(t *testing.T) {
|
|
service, db, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Create user
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
db.Create(user)
|
|
|
|
// Create track
|
|
track := &models.Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
FilePath: "/path/to/track.mp3",
|
|
FileSize: 1024,
|
|
Format: "MP3",
|
|
Duration: 180,
|
|
IsPublic: true,
|
|
Status: models.TrackStatusCompleted,
|
|
}
|
|
db.Create(track)
|
|
|
|
// Record different actions
|
|
actions := []models.TrackHistoryAction{
|
|
models.TrackHistoryActionCreated,
|
|
models.TrackHistoryActionUpdated,
|
|
models.TrackHistoryActionUpdated,
|
|
models.TrackHistoryActionPublished,
|
|
models.TrackHistoryActionUpdated,
|
|
}
|
|
|
|
for _, action := range actions {
|
|
params := RecordHistoryParams{
|
|
TrackID: track.ID,
|
|
UserID: user.ID,
|
|
Action: action,
|
|
OldValue: nil,
|
|
NewValue: map[string]interface{}{"action": string(action)},
|
|
}
|
|
_, err := service.RecordHistory(ctx, params)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get history for "updated" action only
|
|
histories, total, err := service.GetHistoryByAction(ctx, track.ID, models.TrackHistoryActionUpdated, 10, 0)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(3), total)
|
|
assert.Len(t, histories, 3)
|
|
|
|
// Verify all entries have "updated" action
|
|
for _, h := range histories {
|
|
assert.Equal(t, models.TrackHistoryActionUpdated, h.Action)
|
|
}
|
|
}
|
|
|
|
func TestTrackHistoryService_GetHistoryByAction_TrackNotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestTrackHistoryService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
_, _, err := service.GetHistoryByAction(ctx, uuid.New(), models.TrackHistoryActionUpdated, 10, 0)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, ErrTrackNotFound)
|
|
}
|