create(); $channel = PlatformChannel::factory()->create(); return Route::create([ 'feed_id' => $feed->id, 'platform_channel_id' => $channel->id, 'priority' => 50, 'is_active' => $isActive, ]); } private function strandedArticle(Route $route): Article { return Article::factory()->create([ 'feed_id' => $route->feed_id, 'title' => 'A title', 'description' => 'A description', 'content' => 'Some article content', ]); } public function test_it_backfills_articles_missing_a_route_article(): void { $route = $this->route(); $article = $this->strandedArticle($route); $this->action()->execute($route); $this->assertDatabaseHas('route_articles', [ 'article_id' => $article->id, 'feed_id' => $route->feed_id, 'platform_channel_id' => $route->platform_channel_id, ]); } public function test_it_is_idempotent(): void { $route = $this->route(); $this->strandedArticle($route); $this->action()->execute($route); $this->action()->execute($route); $this->assertSame(1, RouteArticle::count()); } public function test_it_skips_articles_already_routed_to_this_route(): void { $route = $this->route(); $article = $this->strandedArticle($route); RouteArticle::create([ 'feed_id' => $route->feed_id, 'platform_channel_id' => $route->platform_channel_id, 'article_id' => $article->id, 'approval_status' => ApprovalStatusEnum::APPROVED, ]); $this->action()->execute($route); $this->assertSame(1, RouteArticle::count()); $this->assertSame(ApprovalStatusEnum::APPROVED, RouteArticle::first()->approval_status); } public function test_it_skips_articles_without_stored_content(): void { $route = $this->route(); Article::factory()->create([ 'feed_id' => $route->feed_id, 'content' => null, ]); $this->action()->execute($route); $this->assertSame(0, RouteArticle::count()); } public function test_it_does_nothing_for_an_inactive_route(): void { $route = $this->route(isActive: false); $this->strandedArticle($route); $this->action()->execute($route); $this->assertSame(0, RouteArticle::count()); } public function test_it_does_not_touch_articles_in_other_feeds(): void { $route = $this->route(); $this->strandedArticle($route); $otherFeed = Feed::factory()->create(); $otherArticle = Article::factory()->create([ 'feed_id' => $otherFeed->id, 'content' => 'Other content', ]); $this->action()->execute($route); $this->assertSame(0, RouteArticle::where('article_id', $otherArticle->id)->count()); } public function test_keyword_matching_uses_the_stored_content_without_refetching(): void { Setting::setBool('enable_publishing_approvals', true); $route = $this->route(); Article::factory()->create([ 'feed_id' => $route->feed_id, 'title' => 'A title', 'description' => 'A description', 'content' => 'news from Brussels today', ]); Keyword::create([ 'feed_id' => $route->feed_id, 'platform_channel_id' => $route->platform_channel_id, 'keyword' => 'brussels', 'is_active' => true, ]); $this->action()->execute($route); $this->assertSame(ApprovalStatusEnum::PENDING, RouteArticle::first()->approval_status); } }