Initial commit: Pireon Admin — headless admin panel and public API

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>
This commit is contained in:
2026-08-19 17:55:27 +02:00
commit 3897113313
534 changed files with 64050 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
<?php
declare(strict_types=1);
namespace Tests\Feature\Panel;
use App\Filament\Resources\Pages\PageResource;
use App\Filament\Resources\Pages\Pages\CreatePage;
use App\Filament\Resources\Pages\Pages\EditPage;
use App\Filament\Resources\Projects\Pages\CreateProject;
use App\Filament\Resources\Services\Pages\CreateService;
use App\Models\Page;
use App\Models\Project;
use App\Models\Service;
use App\Support\DuplicateTitles;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use PHPUnit\Framework\Attributes\Test;
use Tests\FakesPireon;
use Tests\TestCase;
/**
* A nudge, not a rule.
*
* The slug already has a hard uniqueness constraint — two records cannot
* answer at the same address. What this catches is the case that constraint
* cannot: two records with different addresses and almost the same title,
* which is what actually happens when nobody remembers something already
* exists. It warns; it has never once refused to save.
*/
class DuplicateTitlesTest extends TestCase
{
use FakesPireon, RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->seed(RolePermissionSeeder::class);
$this->actingAs($this->userWithRoles('admin'));
}
#[Test]
public function a_near_identical_title_is_found(): void
{
Page::factory()->create(['title' => ['es' => 'Gestor de socios']]);
$matches = DuplicateTitles::similarTo(Page::class, 'Gestor de socios v2', 'es', null);
$this->assertCount(1, $matches);
$this->assertSame('Gestor de socios', $matches->first()->getTranslation('title', 'es', false));
}
#[Test]
public function an_unrelated_title_is_not_a_match(): void
{
Page::factory()->create(['title' => ['es' => 'Gestor de socios']]);
$matches = DuplicateTitles::similarTo(Page::class, 'Convocatoria de primavera', 'es', null);
$this->assertTrue($matches->isEmpty());
}
/**
* The record being edited must never flag itself: typing in an existing
* page's own title field would otherwise "find" a perfect match on every
* keystroke.
*/
#[Test]
public function a_record_is_never_a_duplicate_of_itself(): void
{
$page = Page::factory()->create(['title' => ['es' => 'Gestor de socios']]);
$matches = DuplicateTitles::similarTo(Page::class, 'Gestor de socios', 'es', $page->id);
$this->assertTrue($matches->isEmpty());
}
#[Test]
public function an_empty_title_matches_nothing(): void
{
Page::factory()->create(['title' => ['es' => 'Gestor de socios']]);
$this->assertTrue(DuplicateTitles::similarTo(Page::class, '', 'es', null)->isEmpty());
$this->assertTrue(DuplicateTitles::similarTo(Page::class, ' ', 'es', null)->isEmpty());
}
#[Test]
public function only_the_closest_three_are_returned(): void
{
foreach (range(1, 5) as $n) {
Page::factory()->create(['title' => ['es' => "Gestor de socios {$n}"]]);
}
$matches = DuplicateTitles::similarTo(Page::class, 'Gestor de socios', 'es', null);
$this->assertCount(3, $matches);
}
#[Test]
public function typing_a_near_duplicate_title_warns_while_creating(): void
{
Page::factory()->create(['title' => ['es' => 'Quiénes somos']]);
Livewire::test(CreatePage::class)
->fillForm(['title' => ['es' => 'Quienes somos']])
->assertNotified(__('panel.duplicates.title'));
}
/**
* Editing an existing page must not warn about itself the moment the
* form is touched.
*/
#[Test]
public function editing_a_page_without_changing_its_title_does_not_warn(): void
{
$page = Page::factory()->create(['title' => ['es' => 'Quiénes somos']]);
Livewire::test(EditPage::class, ['record' => $page->getKey()])
->fillForm(['excerpt' => ['es' => 'Un resumen nuevo']])
->assertNotNotified(__('panel.duplicates.title'));
}
#[Test]
public function the_warning_links_to_the_existing_record(): void
{
$existing = Page::factory()->create(['title' => ['es' => 'Quiénes somos']]);
$component = Livewire::test(CreatePage::class)
->fillForm(['title' => ['es' => 'Quienes somos']]);
// Read ahead of `assertNotified()`, which pulls this same key from
// the session and would leave nothing behind for a second read.
$notified = collect(session('filament.claimed_notifications'))->first();
$component->assertNotified(__('panel.duplicates.title'));
$this->assertSame(
PageResource::getUrl('edit', ['record' => $existing]),
$notified['actions'][0]['url'] ?? null,
);
}
#[Test]
public function it_works_for_projects(): void
{
Project::factory()->create(['title' => ['es' => 'Web del colectivo']]);
Livewire::test(CreateProject::class)
->fillForm(['title' => ['es' => 'Web del colectivo v2']])
->assertNotified(__('panel.duplicates.title'));
}
#[Test]
public function it_works_for_services(): void
{
Service::factory()->create(['title' => ['es' => 'Auditoría técnica']]);
Livewire::test(CreateService::class)
->fillForm(['title' => ['es' => 'Auditoria tecnica']])
->assertNotified(__('panel.duplicates.title'));
}
}