390 lines
9.9 KiB
Go
390 lines
9.9 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"veza-backend-api/internal/models"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func setupTestPlaylistFollowService(t *testing.T) (*PlaylistFollowService, *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.Playlist{}, &models.PlaylistFollow{})
|
|
require.NoError(t, err)
|
|
|
|
logger := zap.NewNop()
|
|
service := NewPlaylistFollowService(db, logger)
|
|
|
|
cleanup := func() {
|
|
// Database will be closed automatically
|
|
}
|
|
|
|
return service, db, cleanup
|
|
}
|
|
|
|
func TestPlaylistFollowService_FollowPlaylist(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
require.NoError(t, db.Create(user2).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user1.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Test follow
|
|
err := service.FollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify follow was created
|
|
var follow models.PlaylistFollow
|
|
err = db.Where("user_id = ? AND playlist_id = ?", user2.ID, playlist.ID).First(&follow).Error
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, user2.ID, follow.UserID)
|
|
assert.Equal(t, playlist.ID, follow.PlaylistID)
|
|
|
|
// Verify follower count was updated
|
|
var updatedPlaylist models.Playlist
|
|
db.First(&updatedPlaylist, playlist.ID)
|
|
assert.Equal(t, 1, updatedPlaylist.FollowerCount)
|
|
}
|
|
|
|
func TestPlaylistFollowService_FollowPlaylist_OwnPlaylist(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Test follow own playlist (should fail)
|
|
err := service.FollowPlaylist(ctx, user.ID, playlist.ID)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "cannot follow own playlist", err.Error())
|
|
}
|
|
|
|
func TestPlaylistFollowService_FollowPlaylist_NotFound(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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)
|
|
|
|
// Test follow non-existent playlist
|
|
err := service.FollowPlaylist(ctx, user.ID, uuid.New())
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "playlist not found", err.Error())
|
|
}
|
|
|
|
func TestPlaylistFollowService_FollowPlaylist_Idempotent(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
require.NoError(t, db.Create(user2).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user1.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Follow twice
|
|
err := service.FollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err)
|
|
err = service.FollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err) // Should be idempotent
|
|
|
|
// Verify only one follow exists
|
|
var count int64
|
|
db.Model(&models.PlaylistFollow{}).Where("user_id = ? AND playlist_id = ?", user2.ID, playlist.ID).Count(&count)
|
|
assert.Equal(t, int64(1), count)
|
|
}
|
|
|
|
func TestPlaylistFollowService_UnfollowPlaylist(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
require.NoError(t, db.Create(user2).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user1.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Follow first
|
|
err := service.FollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Unfollow
|
|
err = service.UnfollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify follow was deleted
|
|
var count int64
|
|
db.Model(&models.PlaylistFollow{}).Where("user_id = ? AND playlist_id = ? AND deleted_at IS NULL", user2.ID, playlist.ID).Count(&count)
|
|
assert.Equal(t, int64(0), count)
|
|
|
|
// Verify follower count was updated
|
|
var updatedPlaylist models.Playlist
|
|
db.First(&updatedPlaylist, playlist.ID)
|
|
assert.Equal(t, 0, updatedPlaylist.FollowerCount)
|
|
}
|
|
|
|
func TestPlaylistFollowService_UnfollowPlaylist_Idempotent(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
require.NoError(t, db.Create(user2).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user1.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Unfollow without following first (should be idempotent)
|
|
err := service.UnfollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestPlaylistFollowService_IsFollowing(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
}
|
|
require.NoError(t, db.Create(user1).Error)
|
|
require.NoError(t, db.Create(user2).Error)
|
|
|
|
// Create test playlist
|
|
playlist := &models.Playlist{
|
|
UserID: user1.ID,
|
|
Title: "Test Playlist",
|
|
Description: "A test playlist",
|
|
IsPublic: true,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Check before following
|
|
isFollowing, err := service.IsFollowing(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err)
|
|
assert.False(t, isFollowing)
|
|
|
|
// Follow
|
|
err = service.FollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Check after following
|
|
isFollowing, err = service.IsFollowing(ctx, user2.ID, playlist.ID)
|
|
assert.NoError(t, err)
|
|
assert.True(t, isFollowing)
|
|
}
|
|
|
|
func TestPlaylistFollowService_GetPlaylistFollowersCount(t *testing.T) {
|
|
service, db, cleanup := setupTestPlaylistFollowService(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,
|
|
FollowerCount: 0,
|
|
}
|
|
require.NoError(t, db.Create(playlist).Error)
|
|
|
|
// Check count before following
|
|
count, err := service.GetPlaylistFollowersCount(ctx, playlist.ID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(0), count)
|
|
|
|
// Follow by user2
|
|
err = service.FollowPlaylist(ctx, user2.ID, playlist.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Follow by user3
|
|
err = service.FollowPlaylist(ctx, user3.ID, playlist.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Check count after following
|
|
count, err = service.GetPlaylistFollowersCount(ctx, playlist.ID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(2), count)
|
|
}
|