658 lines
16 KiB
Go
658 lines
16 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 setupTestCommentService(t *testing.T) (*CommentService, *gorm.DB, 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.User{}, &models.Track{}, &models.TrackComment{})
|
|
require.NoError(t, err)
|
|
|
|
// Setup logger
|
|
logger := zap.NewNop()
|
|
|
|
// Setup service
|
|
service := NewCommentService(db, logger)
|
|
|
|
// Cleanup function
|
|
cleanup := func() {
|
|
// Database will be closed automatically
|
|
}
|
|
|
|
return service, db, cleanup
|
|
}
|
|
|
|
func TestCommentService_CreateComment_Success(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 comment
|
|
comment, err := service.CreateComment(ctx, track.ID, userID, "Great track!", 0.0, nil)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, comment)
|
|
assert.Equal(t, track.ID, comment.TrackID)
|
|
assert.Equal(t, userID, comment.UserID)
|
|
assert.Equal(t, "Great track!", comment.Content)
|
|
assert.Nil(t, comment.ParentID)
|
|
assert.False(t, comment.IsEdited)
|
|
assert.NotNil(t, comment.User)
|
|
assert.Equal(t, "testuser", comment.User.Username)
|
|
}
|
|
|
|
func TestCommentService_CreateComment_TrackNotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
userID := uuid.New()
|
|
|
|
// Try to create comment on non-existent track
|
|
comment, err := service.CreateComment(ctx, uuid.New(), userID, "Great track!", 0.0, nil)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, comment)
|
|
assert.ErrorIs(t, err, ErrTrackNotFound)
|
|
}
|
|
|
|
func TestCommentService_CreateComment_WithParent(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 parent comment
|
|
parentComment, err := service.CreateComment(ctx, track.ID, userID, "Parent comment", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Create reply
|
|
reply, err := service.CreateComment(ctx, track.ID, userID, "Reply to parent", 0.0, &parentComment.ID)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, reply)
|
|
assert.NotNil(t, reply.ParentID)
|
|
assert.Equal(t, parentComment.ID, *reply.ParentID)
|
|
assert.Equal(t, "Reply to parent", reply.Content)
|
|
}
|
|
|
|
func TestCommentService_CreateComment_ParentNotFound(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 reply with non-existent parent
|
|
parentID := uuid.New()
|
|
reply, err := service.CreateComment(ctx, track.ID, userID, "Reply", 0.0, &parentID)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, reply)
|
|
assert.ErrorIs(t, err, ErrParentCommentNotFound)
|
|
}
|
|
|
|
func TestCommentService_GetComments_Success(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 multiple comments
|
|
for i := 0; i < 5; i++ {
|
|
_, err := service.CreateComment(ctx, track.ID, userID, "Comment "+string(rune('0'+i)), 0.0, nil)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get comments
|
|
comments, total, err := service.GetComments(ctx, track.ID, 1, 10)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(5), total)
|
|
assert.Len(t, comments, 5)
|
|
assert.NotNil(t, comments[0].User)
|
|
}
|
|
|
|
func TestCommentService_GetComments_Pagination(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 multiple comments
|
|
for i := 0; i < 10; i++ {
|
|
_, err := service.CreateComment(ctx, track.ID, userID, "Comment", 0.0, nil)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get first page
|
|
comments, total, err := service.GetComments(ctx, track.ID, 1, 3)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(10), total)
|
|
assert.Len(t, comments, 3)
|
|
|
|
// Get second page
|
|
comments2, total2, err := service.GetComments(ctx, track.ID, 2, 3)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(10), total2)
|
|
assert.Len(t, comments2, 3)
|
|
}
|
|
|
|
func TestCommentService_GetComments_OnlyRootComments(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 root comment
|
|
rootComment, err := service.CreateComment(ctx, track.ID, userID, "Root comment", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Create reply (should not appear in GetComments)
|
|
_, err = service.CreateComment(ctx, track.ID, userID, "Reply", 0.0, &rootComment.ID)
|
|
require.NoError(t, err)
|
|
|
|
// Get comments (should only return root comment)
|
|
comments, total, err := service.GetComments(ctx, track.ID, 1, 10)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(1), total)
|
|
assert.Len(t, comments, 1)
|
|
assert.Equal(t, rootComment.ID, comments[0].ID)
|
|
}
|
|
|
|
func TestCommentService_UpdateComment_Success(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 comment
|
|
comment, err := service.CreateComment(ctx, track.ID, userID, "Original content", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Update comment
|
|
updatedComment, err := service.UpdateComment(ctx, comment.ID, userID, "Updated content")
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, updatedComment)
|
|
assert.Equal(t, "Updated content", updatedComment.Content)
|
|
assert.True(t, updatedComment.IsEdited)
|
|
}
|
|
|
|
func TestCommentService_UpdateComment_NotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
userID := uuid.New()
|
|
|
|
// Try to update non-existent comment
|
|
comment, err := service.UpdateComment(ctx, uuid.New(), userID, "Updated content")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, comment)
|
|
assert.ErrorIs(t, err, ErrCommentNotFound)
|
|
}
|
|
|
|
func TestCommentService_UpdateComment_Unauthorized(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
user1ID := uuid.New()
|
|
// Create test users
|
|
user1 := &models.User{
|
|
ID: user1ID,
|
|
Username: "user1",
|
|
Email: "user1@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user1).Error
|
|
require.NoError(t, err)
|
|
|
|
user2ID := uuid.New()
|
|
user2 := &models.User{
|
|
ID: user2ID,
|
|
Username: "user2",
|
|
Email: "user2@example.com",
|
|
IsActive: true,
|
|
}
|
|
err = db.Create(user2).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create test track
|
|
track := &models.Track{
|
|
UserID: user1ID,
|
|
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 comment with user1
|
|
comment, err := service.CreateComment(ctx, track.ID, user1ID, "Original content", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Try to update with user2 (should fail)
|
|
updatedComment, err := service.UpdateComment(ctx, comment.ID, user2ID, "Updated content")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, updatedComment)
|
|
assert.ErrorIs(t, err, ErrForbidden)
|
|
}
|
|
|
|
func TestCommentService_DeleteComment_Success(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 comment
|
|
comment, err := service.CreateComment(ctx, track.ID, userID, "Comment to delete", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Delete comment
|
|
err = service.DeleteComment(ctx, comment.ID, userID, false)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify comment is soft deleted
|
|
var deletedComment models.TrackComment
|
|
err = db.First(&deletedComment, comment.ID).Error
|
|
assert.Error(t, err)
|
|
assert.Equal(t, gorm.ErrRecordNotFound, err)
|
|
}
|
|
|
|
func TestCommentService_DeleteComment_NotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
userID := uuid.New()
|
|
|
|
// Try to delete non-existent comment
|
|
err := service.DeleteComment(ctx, uuid.New(), userID, false)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, ErrCommentNotFound)
|
|
}
|
|
|
|
func TestCommentService_DeleteComment_Unauthorized(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
user1ID := uuid.New()
|
|
// Create test users
|
|
user1 := &models.User{
|
|
ID: user1ID,
|
|
Username: "user1",
|
|
Email: "user1@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user1).Error
|
|
require.NoError(t, err)
|
|
|
|
user2ID := uuid.New()
|
|
user2 := &models.User{
|
|
ID: user2ID,
|
|
Username: "user2",
|
|
Email: "user2@example.com",
|
|
IsActive: true,
|
|
}
|
|
err = db.Create(user2).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create test track
|
|
track := &models.Track{
|
|
UserID: user1ID,
|
|
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 comment with user1
|
|
comment, err := service.CreateComment(ctx, track.ID, user1ID, "Comment", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Try to delete with user2 (should fail)
|
|
err = service.DeleteComment(ctx, comment.ID, user2ID, false)
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, ErrForbidden)
|
|
}
|
|
|
|
func TestCommentService_GetReplies_Success(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 parent comment
|
|
parentComment, err := service.CreateComment(ctx, track.ID, userID, "Parent comment", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Create multiple replies
|
|
for i := 0; i < 5; i++ {
|
|
_, err := service.CreateComment(ctx, track.ID, userID, "Reply", 0.0, &parentComment.ID)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get replies
|
|
replies, total, err := service.GetReplies(ctx, parentComment.ID, 1, 10)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(5), total)
|
|
assert.Len(t, replies, 5)
|
|
assert.NotNil(t, replies[0].User)
|
|
}
|
|
|
|
func TestCommentService_GetReplies_ParentNotFound(t *testing.T) {
|
|
service, _, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
// Try to get replies for non-existent parent
|
|
replies, total, err := service.GetReplies(ctx, uuid.New(), 1, 10)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, replies)
|
|
assert.Equal(t, int64(0), total)
|
|
assert.ErrorIs(t, err, ErrParentCommentNotFound)
|
|
}
|
|
|
|
func TestCommentService_GetReplies_Pagination(t *testing.T) {
|
|
service, db, cleanup := setupTestCommentService(t)
|
|
defer cleanup()
|
|
|
|
ctx := context.Background()
|
|
|
|
userID := uuid.New()
|
|
// Create test user
|
|
user := &models.User{
|
|
ID: userID,
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
IsActive: true,
|
|
}
|
|
err := db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// 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 parent comment
|
|
parentComment, err := service.CreateComment(ctx, track.ID, userID, "Parent comment", 0.0, nil)
|
|
require.NoError(t, err)
|
|
|
|
// Create multiple replies
|
|
for i := 0; i < 10; i++ {
|
|
_, err := service.CreateComment(ctx, track.ID, userID, "Reply", 0.0, &parentComment.ID)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Get first page
|
|
replies, total, err := service.GetReplies(ctx, parentComment.ID, 1, 3)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(10), total)
|
|
assert.Len(t, replies, 3)
|
|
|
|
// Get second page
|
|
replies2, total2, err := service.GetReplies(ctx, parentComment.ID, 2, 3)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, int64(10), total2)
|
|
assert.Len(t, replies2, 3)
|
|
}
|