package service import ( "context" "testing" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" ) // ========== Article test helpers ========== // setupArticleService creates ArticleRepo + ArticleService test instances. func setupArticleService(t *testing.T) (*gorm.DB, *repository.ArticleRepo, *ArticleService) { t.Helper() db := setupServiceTestDB(t) repo := repository.NewArticleRepo(db) svc := NewArticleService(repo) return db, repo, svc } // ========== BulkActions ========== func TestArticleService_BulkActions_Publish(t *testing.T) { db, _, svc := setupArticleService(t) account := createTestAccount(t, db) a1 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "publish-art-1" }) a2 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "publish-art-2" }) err := svc.BulkActions(context.Background(), &BulkActionsRequest{ Action: "publish", IDs: []uint{a1.ID, a2.ID}, }) require.NoError(t, err) // Verify both articles have status "published" var updated1, updated2 model.Article require.NoError(t, db.First(&updated1, a1.ID).Error) require.NoError(t, db.First(&updated2, a2.ID).Error) assert.Equal(t, string(model.ArticleStatusPublished), updated1.Status) assert.Equal(t, string(model.ArticleStatusPublished), updated2.Status) } func TestArticleService_BulkActions_Archive(t *testing.T) { db, _, svc := setupArticleService(t) account := createTestAccount(t, db) a1 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "archive-art-1" }) a2 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "archive-art-2" }) err := svc.BulkActions(context.Background(), &BulkActionsRequest{ Action: "archive", IDs: []uint{a1.ID, a2.ID}, }) require.NoError(t, err) var updated1, updated2 model.Article require.NoError(t, db.First(&updated1, a1.ID).Error) require.NoError(t, db.First(&updated2, a2.ID).Error) assert.Equal(t, string(model.ArticleStatusArchived), updated1.Status) assert.Equal(t, string(model.ArticleStatusArchived), updated2.Status) } func TestArticleService_BulkActions_Delete(t *testing.T) { db, _, svc := setupArticleService(t) account := createTestAccount(t, db) a1 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "delete-art-1" }) a2 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "delete-art-2" }) err := svc.BulkActions(context.Background(), &BulkActionsRequest{ Action: "delete", IDs: []uint{a1.ID, a2.ID}, }) require.NoError(t, err) // Verify both articles are deleted (not found in DB) var found model.Article assert.ErrorIs(t, db.First(&found, a1.ID).Error, gorm.ErrRecordNotFound) assert.ErrorIs(t, db.First(&found, a2.ID).Error, gorm.ErrRecordNotFound) } func TestArticleService_BulkActions_InvalidAction(t *testing.T) { _, _, svc := setupArticleService(t) err := svc.BulkActions(context.Background(), &BulkActionsRequest{ Action: "invalid", IDs: []uint{1, 2}, }) assert.Error(t, err) assert.Contains(t, err.Error(), "unsupported action") } // ========== BulkUpdateStatus ========== func TestArticleService_BulkUpdateStatus_ValidStatus(t *testing.T) { db, _, svc := setupArticleService(t) account := createTestAccount(t, db) a1 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "status-art-1" }) a2 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "status-art-2" }) err := svc.BulkUpdateStatus(context.Background(), []uint{a1.ID, a2.ID}, string(model.ArticleStatusPublished)) require.NoError(t, err) var updated1, updated2 model.Article require.NoError(t, db.First(&updated1, a1.ID).Error) require.NoError(t, db.First(&updated2, a2.ID).Error) assert.Equal(t, string(model.ArticleStatusPublished), updated1.Status) assert.Equal(t, string(model.ArticleStatusPublished), updated2.Status) } func TestArticleService_BulkUpdateStatus_InvalidStatus(t *testing.T) { _, _, svc := setupArticleService(t) err := svc.BulkUpdateStatus(context.Background(), []uint{1, 2}, "invalid_status") assert.Error(t, err) assert.Contains(t, err.Error(), "invalid status") } // ========== BulkDelete ========== func TestArticleService_BulkDelete_Success(t *testing.T) { db, _, svc := setupArticleService(t) account := createTestAccount(t, db) a1 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "bulkdel-art-1" }) a2 := createTestArticle(t, db, account.ID, 1, func(a *model.Article) { a.Slug = "bulkdel-art-2" }) err := svc.BulkDelete(context.Background(), []uint{a1.ID, a2.ID}) require.NoError(t, err) var found model.Article assert.ErrorIs(t, db.First(&found, a1.ID).Error, gorm.ErrRecordNotFound) assert.ErrorIs(t, db.First(&found, a2.ID).Error, gorm.ErrRecordNotFound) }