425 lines
11 KiB
Go
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)
|
|
}
|