Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
155 lines
5.0 KiB
PHP
155 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Panel;
|
|
|
|
use App\Enums\PageStatus;
|
|
use App\Filament\Resources\Pages\Pages\ListPages;
|
|
use App\Filament\Resources\Projects\Pages\ListProjects;
|
|
use App\Filament\Resources\Services\Pages\ListServices;
|
|
use App\Models\Page;
|
|
use App\Models\Project;
|
|
use App\Models\Service;
|
|
use Database\Seeders\RolePermissionSeeder;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Tests\FakesPireon;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* Publishing and requesting review, for a whole selection at once.
|
|
*
|
|
* The single-row versions of both already existed; what these tests hold
|
|
* still is that the bulk versions make the same judgement calls the single
|
|
* ones do — who may press the button, and which selected rows are actually
|
|
* eligible — rather than a cruder "do it to everything ticked".
|
|
*/
|
|
class BulkPublishingTest extends TestCase
|
|
{
|
|
use FakesPireon, RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->seed(RolePermissionSeeder::class);
|
|
}
|
|
|
|
#[Test]
|
|
public function publishing_a_selection_of_pages_skips_what_is_already_live(): void
|
|
{
|
|
$draft = Page::factory()->create(['status' => PageStatus::Draft, 'published_at' => null]);
|
|
$alreadyLive = Page::factory()->published()->create();
|
|
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
Livewire::test(ListPages::class)
|
|
->callTableBulkAction('publish', [$draft, $alreadyLive]);
|
|
|
|
$this->assertSame(PageStatus::Published, $draft->fresh()->status);
|
|
$this->assertNotNull($draft->fresh()->published_at);
|
|
}
|
|
|
|
/**
|
|
* Publishing is what closes a pending review — the model's own hook does
|
|
* that on any `update()`, and the bulk action has to go through it one
|
|
* record at a time rather than a single UPDATE query, or this silently
|
|
* stops working.
|
|
*/
|
|
#[Test]
|
|
public function bulk_publishing_closes_a_pending_review(): void
|
|
{
|
|
$page = Page::factory()->create(['status' => PageStatus::Draft, 'published_at' => null]);
|
|
$page->requestReview();
|
|
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
Livewire::test(ListPages::class)
|
|
->callTableBulkAction('publish', [$page]);
|
|
|
|
$this->assertFalse($page->fresh()->isAwaitingReview());
|
|
}
|
|
|
|
#[Test]
|
|
public function somebody_who_cannot_publish_does_not_see_the_bulk_action(): void
|
|
{
|
|
Page::factory()->create(['status' => PageStatus::Draft]);
|
|
|
|
$this->actingAs($this->userWithRoles('writer'));
|
|
|
|
Livewire::test(ListPages::class)
|
|
->assertTableBulkActionHidden('publish');
|
|
}
|
|
|
|
#[Test]
|
|
public function requesting_review_in_bulk_skips_what_is_already_awaiting_or_published(): void
|
|
{
|
|
$eligible = Page::factory()->create(['status' => PageStatus::Draft, 'published_at' => null]);
|
|
|
|
$alreadyAwaiting = Page::factory()->create(['status' => PageStatus::Draft, 'published_at' => null]);
|
|
$alreadyAwaiting->requestReview();
|
|
|
|
$alreadyPublished = Page::factory()->published()->create();
|
|
|
|
$this->actingAs($this->userWithRoles('writer'));
|
|
|
|
Livewire::test(ListPages::class)
|
|
->callTableBulkAction('request_review_bulk', [$eligible, $alreadyAwaiting, $alreadyPublished]);
|
|
|
|
$this->assertTrue($eligible->fresh()->isAwaitingReview());
|
|
|
|
// Untouched: neither had anything to gain from being asked again.
|
|
$this->assertSame(
|
|
$alreadyAwaiting->fresh()->review_requested_at->timestamp,
|
|
$alreadyAwaiting->review_requested_at->timestamp,
|
|
);
|
|
$this->assertFalse($alreadyPublished->fresh()->isAwaitingReview());
|
|
}
|
|
|
|
/**
|
|
* The same rule as the single button: somebody who can already publish
|
|
* has no use for asking permission first.
|
|
*/
|
|
#[Test]
|
|
public function somebody_who_can_already_publish_does_not_see_the_bulk_request_action(): void
|
|
{
|
|
Page::factory()->create();
|
|
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
Livewire::test(ListPages::class)
|
|
->assertTableBulkActionHidden('request_review_bulk');
|
|
}
|
|
|
|
#[Test]
|
|
public function it_works_for_projects(): void
|
|
{
|
|
$project = Project::factory()->create(['published_at' => null]);
|
|
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
Livewire::test(ListProjects::class)
|
|
->callTableBulkAction('publish', [$project]);
|
|
|
|
$this->assertNotNull($project->fresh()->published_at);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_works_for_services(): void
|
|
{
|
|
$service = Service::factory()->create(['is_published' => false, 'published_at' => null]);
|
|
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
Livewire::test(ListServices::class)
|
|
->callTableBulkAction('publish', [$service]);
|
|
|
|
$service->refresh();
|
|
|
|
$this->assertTrue($service->is_published);
|
|
$this->assertNotNull($service->published_at);
|
|
}
|
|
}
|