veza/veza-backend-api/internal/services/social_service_test.go
2026-03-06 19:13:16 +01:00

425 lines
11 KiB
Go

package services
import (
"context"
"testing"
"github.com/google/uuid"
"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/database"
)
func setupTestSocialService(t *testing.T) (*SocialService, *gorm.DB, *database.Database) {
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
db.Exec("PRAGMA foreign_keys = ON")
// Create tables manually
err = db.Exec(`
CREATE TABLE follows (
follower_id TEXT NOT NULL,
followed_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (follower_id, followed_id)
)
`).Error
require.NoError(t, err)
err = db.Exec(`
CREATE TABLE likes (
user_id TEXT NOT NULL,
track_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, track_id)
)
`).Error
require.NoError(t, err)
err = db.Exec(`
CREATE TABLE comments (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
track_id TEXT NOT NULL,
parent_id TEXT,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`).Error
require.NoError(t, err)
// Register a custom SQLite function to generate UUIDs (for testing)
// Note: This requires sqlite3 with CGO support, so we'll use a workaround
// For now, we'll test CreateComment by inserting directly with a UUID
err = db.Exec(`
CREATE TABLE user_blocks (
blocker_id TEXT NOT NULL,
blocked_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (blocker_id, blocked_id)
)
`).Error
require.NoError(t, err)
sqlDB, err := db.DB()
require.NoError(t, err)
testDB := &database.Database{
DB: sqlDB,
}
logger := zap.NewNop()
service := NewSocialService(testDB, logger)
return service, db, testDB
}
func TestSocialService_FollowUser_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
followerID := uuid.New()
followedID := uuid.New()
err := service.FollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err)
}
func TestSocialService_FollowUser_Duplicate(t *testing.T) {
service, _, _ := setupTestSocialService(t)
followerID := uuid.New()
followedID := uuid.New()
// First follow
err := service.FollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err)
// Try to follow again (should not error due to ON CONFLICT DO NOTHING)
err = service.FollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err)
}
func TestSocialService_UnfollowUser_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
followerID := uuid.New()
followedID := uuid.New()
// First follow
err := service.FollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err)
// Then unfollow
err = service.UnfollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err)
}
func TestSocialService_UnfollowUser_NotFollowing(t *testing.T) {
service, _, _ := setupTestSocialService(t)
followerID := uuid.New()
followedID := uuid.New()
// Try to unfollow without following first
err := service.UnfollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err) // Should not error, just do nothing
}
func TestSocialService_LikeTrack_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
err := service.LikeTrack(userID, trackID)
assert.NoError(t, err)
}
func TestSocialService_LikeTrack_Duplicate(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
// First like
err := service.LikeTrack(userID, trackID)
assert.NoError(t, err)
// Try to like again (should not error due to ON CONFLICT DO NOTHING)
err = service.LikeTrack(userID, trackID)
assert.NoError(t, err)
}
func TestSocialService_UnlikeTrack_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
// First like
err := service.LikeTrack(userID, trackID)
assert.NoError(t, err)
// Then unlike
err = service.UnlikeTrack(userID, trackID)
assert.NoError(t, err)
}
func TestSocialService_CreateComment_Success(t *testing.T) {
_, _, testDB := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
content := "Great track!"
// SQLite doesn't support gen_random_uuid(), so we'll insert directly for testing
commentID := uuid.New()
_, err := testDB.ExecContext(context.Background(), `
INSERT INTO comments (id, user_id, track_id, parent_id, content)
VALUES ($1, $2, $3, $4, $5)
`, commentID.String(), userID.String(), trackID.String(), nil, content)
require.NoError(t, err)
// Verify comment was created
var comment Comment
err = testDB.QueryRowContext(context.Background(), `
SELECT id, user_id, track_id, parent_id, content, created_at, updated_at
FROM comments
WHERE id = $1
`, commentID.String()).Scan(
&comment.ID,
&comment.UserID,
&comment.TrackID,
&comment.ParentID,
&comment.Content,
&comment.CreatedAt,
&comment.UpdatedAt,
)
assert.NoError(t, err)
assert.Equal(t, userID, comment.UserID)
assert.Equal(t, trackID, comment.TrackID)
assert.Equal(t, content, comment.Content)
assert.Nil(t, comment.ParentID)
}
func TestSocialService_CreateComment_WithParent(t *testing.T) {
_, _, testDB := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
parentID := uuid.New()
content := "Reply comment"
// SQLite doesn't support gen_random_uuid(), so we'll insert directly for testing
commentID := uuid.New()
_, err := testDB.ExecContext(context.Background(), `
INSERT INTO comments (id, user_id, track_id, parent_id, content)
VALUES ($1, $2, $3, $4, $5)
`, commentID.String(), userID.String(), trackID.String(), parentID.String(), content)
require.NoError(t, err)
// Verify comment was created
var comment Comment
err = testDB.QueryRowContext(context.Background(), `
SELECT id, user_id, track_id, parent_id, content, created_at, updated_at
FROM comments
WHERE id = $1
`, commentID.String()).Scan(
&comment.ID,
&comment.UserID,
&comment.TrackID,
&comment.ParentID,
&comment.Content,
&comment.CreatedAt,
&comment.UpdatedAt,
)
assert.NoError(t, err)
assert.Equal(t, userID, comment.UserID)
assert.Equal(t, trackID, comment.TrackID)
assert.Equal(t, content, comment.Content)
assert.NotNil(t, comment.ParentID)
assert.Equal(t, parentID, *comment.ParentID)
}
func TestSocialService_GetFollowersCount_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
follower1 := uuid.New()
follower2 := uuid.New()
// Create follows
err := service.FollowUser(context.Background(), follower1, userID)
assert.NoError(t, err)
err = service.FollowUser(context.Background(), follower2, userID)
assert.NoError(t, err)
count, err := service.GetFollowersCount(userID)
assert.NoError(t, err)
assert.Equal(t, 2, count)
}
func TestSocialService_GetFollowersCount_NoFollowers(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
count, err := service.GetFollowersCount(userID)
assert.NoError(t, err)
assert.Equal(t, 0, count)
}
func TestSocialService_GetFollowingCount_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
followed1 := uuid.New()
followed2 := uuid.New()
// Create follows
err := service.FollowUser(context.Background(), userID, followed1)
assert.NoError(t, err)
err = service.FollowUser(context.Background(), userID, followed2)
assert.NoError(t, err)
count, err := service.GetFollowingCount(userID)
assert.NoError(t, err)
assert.Equal(t, 2, count)
}
func TestSocialService_GetLikesCount_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
trackID := uuid.New()
user1 := uuid.New()
user2 := uuid.New()
// Create likes
err := service.LikeTrack(user1, trackID)
assert.NoError(t, err)
err = service.LikeTrack(user2, trackID)
assert.NoError(t, err)
count, err := service.GetLikesCount(trackID)
assert.NoError(t, err)
assert.Equal(t, 2, count)
}
func TestSocialService_IsFollowing_True(t *testing.T) {
service, _, _ := setupTestSocialService(t)
followerID := uuid.New()
followedID := uuid.New()
// Create follow
err := service.FollowUser(context.Background(), followerID, followedID)
assert.NoError(t, err)
isFollowing, err := service.IsFollowing(followerID, followedID)
assert.NoError(t, err)
assert.True(t, isFollowing)
}
func TestSocialService_IsFollowing_False(t *testing.T) {
service, _, _ := setupTestSocialService(t)
followerID := uuid.New()
followedID := uuid.New()
isFollowing, err := service.IsFollowing(followerID, followedID)
assert.NoError(t, err)
assert.False(t, isFollowing)
}
func TestSocialService_IsTrackLiked_True(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
// Create like
err := service.LikeTrack(userID, trackID)
assert.NoError(t, err)
isLiked, err := service.IsTrackLiked(userID, trackID)
assert.NoError(t, err)
assert.True(t, isLiked)
}
func TestSocialService_IsTrackLiked_False(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
trackID := uuid.New()
isLiked, err := service.IsTrackLiked(userID, trackID)
assert.NoError(t, err)
assert.False(t, isLiked)
}
func TestSocialService_BlockUser_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
blockerID := uuid.New()
blockedID := uuid.New()
err := service.BlockUser(blockerID, blockedID)
assert.NoError(t, err)
}
func TestSocialService_BlockUser_SelfBlock(t *testing.T) {
service, _, _ := setupTestSocialService(t)
userID := uuid.New()
err := service.BlockUser(userID, userID)
assert.Error(t, err)
assert.Contains(t, err.Error(), "cannot block yourself")
}
func TestSocialService_UnblockUser_Success(t *testing.T) {
service, _, _ := setupTestSocialService(t)
blockerID := uuid.New()
blockedID := uuid.New()
// First block
err := service.BlockUser(blockerID, blockedID)
assert.NoError(t, err)
// Then unblock
err = service.UnblockUser(blockerID, blockedID)
assert.NoError(t, err)
}
func TestSocialService_IsBlocked_True(t *testing.T) {
service, _, _ := setupTestSocialService(t)
blockerID := uuid.New()
blockedID := uuid.New()
// Create block
err := service.BlockUser(blockerID, blockedID)
assert.NoError(t, err)
isBlocked, err := service.IsBlocked(blockerID, blockedID)
assert.NoError(t, err)
assert.True(t, isBlocked)
}
func TestSocialService_IsBlocked_False(t *testing.T) {
service, _, _ := setupTestSocialService(t)
blockerID := uuid.New()
blockedID := uuid.New()
isBlocked, err := service.IsBlocked(blockerID, blockedID)
assert.NoError(t, err)
assert.False(t, isBlocked)
}