From 36b46b4d2e0273e89eb56721c92edcb6684e62b4 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sun, 9 Aug 2026 10:37:54 +0200 Subject: [PATCH] 113 - Scope clearing pending articles to the active feed filter --- app/Livewire/Articles.php | 18 ++++- resources/views/livewire/articles.blade.php | 6 +- tests/Feature/Livewire/ArticlesTest.php | 74 +++++++++++++++++++++ 3 files changed, 93 insertions(+), 5 deletions(-) diff --git a/app/Livewire/Articles.php b/app/Livewire/Articles.php index 199807d2..29ec16a9 100644 --- a/app/Livewire/Articles.php +++ b/app/Livewire/Articles.php @@ -8,6 +8,7 @@ use App\Models\RouteArticle; use App\Support\PendingFeedGroup; use Illuminate\Contracts\View\View; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Support\Collection; use Livewire\Component; @@ -76,8 +77,19 @@ public function restore(int $routeArticleId): void public function clear(): void { - RouteArticle::where('approval_status', ApprovalStatusEnum::PENDING) - ->update(['approval_status' => ApprovalStatusEnum::REJECTED]); + $this->clearableQuery()->update(['approval_status' => ApprovalStatusEnum::REJECTED]); + + $this->expandedFeeds = []; + } + + /** + * @return Builder + */ + private function clearableQuery(): Builder + { + return RouteArticle::query() + ->where('approval_status', ApprovalStatusEnum::PENDING) + ->when($this->feedId !== null, fn (Builder $q) => $q->where('feed_id', $this->feedId)); } public function refresh(): void @@ -99,6 +111,7 @@ public function render(): View 'pendingFeeds' => $this->pendingFeeds(), 'feedOptions' => $this->feedOptions(), 'pendingCount' => $pendingCount, + 'clearableCount' => $this->clearableQuery()->count(), ])->layout('layouts.app'); } @@ -122,6 +135,7 @@ public function render(): View 'pendingFeeds' => null, 'feedOptions' => $this->feedOptions(), 'pendingCount' => $pendingCount, + 'clearableCount' => 0, ])->layout('layouts.app'); } diff --git a/resources/views/livewire/articles.blade.php b/resources/views/livewire/articles.blade.php index 56df96b7..8672dc48 100644 --- a/resources/views/livewire/articles.blade.php +++ b/resources/views/livewire/articles.blade.php @@ -62,16 +62,16 @@ class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline- @endif - @if ($tab === 'pending' && $pendingCount > 0) + @if ($tab === 'pending' && $clearableCount > 0) @endif diff --git a/tests/Feature/Livewire/ArticlesTest.php b/tests/Feature/Livewire/ArticlesTest.php index acde862d..2ff785e8 100644 --- a/tests/Feature/Livewire/ArticlesTest.php +++ b/tests/Feature/Livewire/ArticlesTest.php @@ -163,6 +163,80 @@ public function test_clear_rejects_all_pending_route_articles(): void $this->assertEquals(ApprovalStatusEnum::APPROVED, $approved->fresh()->approval_status); } + public function test_clear_only_rejects_the_filtered_feed(): void + { + $vrt = Feed::factory()->create(['name' => 'VRT News']); + $belga = Feed::factory()->create(['name' => 'Belga Press']); + + $vrtArticle = $this->createRouteArticleForFeed($vrt, 'VRT Headline'); + $belgaArticle = $this->createRouteArticleForFeed($belga, 'Belga Headline'); + + Livewire::test(Articles::class) + ->set('feedId', $vrt->id) + ->call('clear'); + + $this->assertEquals(ApprovalStatusEnum::REJECTED, $vrtArticle->fresh()->approval_status); + $this->assertEquals(ApprovalStatusEnum::PENDING, $belgaArticle->fresh()->approval_status); + } + + public function test_clear_is_a_no_op_when_the_filtered_feed_has_nothing_pending(): void + { + $vrt = Feed::factory()->create(['name' => 'VRT News']); + $belga = Feed::factory()->create(['name' => 'Belga Press']); + + $vrtArticle = $this->createRouteArticleForFeed($vrt, 'VRT Headline'); + $belgaApproved = $this->createRouteArticleForFeed($belga, 'Belga Approved', ApprovalStatusEnum::APPROVED); + + Livewire::test(Articles::class) + ->set('feedId', $belga->id) + ->call('clear'); + + $this->assertEquals(ApprovalStatusEnum::PENDING, $vrtArticle->fresh()->approval_status); + $this->assertEquals(ApprovalStatusEnum::APPROVED, $belgaApproved->fresh()->approval_status); + } + + public function test_clear_confirmation_counts_only_the_filtered_feed(): void + { + $vrt = Feed::factory()->create(['name' => 'VRT News']); + $belga = Feed::factory()->create(['name' => 'Belga Press']); + + $this->createRouteArticleForFeed($vrt, 'VRT One'); + $this->createRouteArticleForFeed($vrt, 'VRT Two'); + $this->createRouteArticleForFeed($belga, 'Belga One'); + + Livewire::test(Articles::class) + ->set('feedId', $vrt->id) + ->assertSee('Reject 2 pending route articles from the selected feed?') + ->set('feedId', null) + ->assertSee('Reject 3 pending route articles?'); + } + + public function test_clear_button_hidden_when_filtered_feed_has_nothing_pending(): void + { + $vrt = Feed::factory()->create(['name' => 'VRT News']); + $belga = Feed::factory()->create(['name' => 'Belga Press']); + + $this->createRouteArticleForFeed($vrt, 'VRT Headline'); + $this->createRouteArticleForFeed($belga, 'Belga Approved', ApprovalStatusEnum::APPROVED); + + Livewire::test(Articles::class) + ->set('feedId', $belga->id) + ->assertDontSee('Clear Feed') + ->assertDontSee('Clear All'); + } + + public function test_clear_button_labels_its_scope(): void + { + $vrt = Feed::factory()->create(['name' => 'VRT News']); + + $this->createRouteArticleForFeed($vrt, 'VRT Headline'); + + Livewire::test(Articles::class) + ->assertSee('Clear All') + ->set('feedId', $vrt->id) + ->assertSee('Clear Feed'); + } + public function test_pending_count_badge_shows_correct_count(): void { $this->createRouteArticle(ApprovalStatusEnum::PENDING);