create(); $category = Category::query()->create(['name' => 'c', 'display_order' => 0]); $article = Article::query()->create([ 'category_id' => $category->id, 'user_id' => $user->id, 'title' => 'T', 'content' => 'Hello world body', 'content_format' => 'markdown', 'published_at' => now(), 'visible' => true, ]); (new OptimizeArticleContentJob($article->id))->handle( app(LlmProvider::class), app(AiSettings::class), ); $article->refresh(); $this->assertNotEmpty($article->ai_summary); $this->assertIsArray($article->ai_suggestions); $this->assertNotEmpty($article->ai_polished_content); $this->assertStringContainsString('Hello world body', (string) $article->ai_polished_content); } public function test_moderate_job_approves_non_spam(): void { $user = User::factory()->create(); $category = Category::query()->create(['name' => 'c', 'display_order' => 0]); $article = Article::query()->create([ 'category_id' => $category->id, 'user_id' => $user->id, 'title' => 'T', 'content' => 'Body', 'content_format' => 'html', 'published_at' => now(), 'visible' => true, ]); $comment = Comment::query()->create([ 'article_id' => $article->id, 'author' => 'a', 'content' => 'nice post', 'moderation_status' => Comment::STATUS_PENDING_AI, 'published_at' => now(), ]); (new ModerateCommentJob($comment->id))->handle( app(LlmProvider::class), app(AiSettings::class), ); $this->assertSame(Comment::STATUS_APPROVED, $comment->fresh()->moderation_status); } public function test_optimize_action_dispatches_to_ai_content_queue(): void { Queue::fake(); OptimizeArticleContentJob::dispatch(1); Queue::assertPushedOn('ai-content', OptimizeArticleContentJob::class); } }