feat: legal sections

This commit is contained in:
2026-05-24 13:20:04 +02:00
parent 3a74c2c34d
commit 8b162c8e4c
24 changed files with 1145 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
<?php
use App\Enums\LegalDocumentType;
use App\Enums\UserRole;
use App\Filament\Resources\LegalDocuments\Pages\EditLegalDocument;
use App\Filament\Resources\LegalDocuments\Pages\ListLegalDocuments;
use App\Models\LegalDocument;
use App\Models\User;
use Filament\Facades\Filament;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
uses(RefreshDatabase::class);
it('returns the active published legal document by slug', function (): void {
LegalDocument::factory()->create([
'slug' => 'privacy-policy',
'version' => 1,
'is_active' => false,
]);
LegalDocument::factory()->create([
'slug' => 'privacy-policy',
'version' => 2,
'is_active' => true,
'published_at' => now(),
'title' => [
'fr' => 'Confidentialité Bowli',
],
]);
$this
->getJson('/api/legal-documents/privacy-policy')
->assertOk()
->assertJsonPath('data.slug', 'privacy-policy')
->assertJsonPath('data.type', LegalDocumentType::PRIVACY_POLICY->value)
->assertJsonPath('data.version', 2)
->assertJsonPath('data.title.fr', 'Confidentialité Bowli')
->assertJsonPath('data.isActive', true);
});
it('does not expose inactive or unpublished legal documents', function (): void {
LegalDocument::factory()->inactive()->create([
'slug' => 'privacy-policy',
]);
LegalDocument::factory()->unpublished()->create([
'slug' => 'terms-of-service',
]);
$this->getJson('/api/legal-documents/privacy-policy')->assertNotFound();
$this->getJson('/api/legal-documents/terms-of-service')->assertNotFound();
});
it('lists active published legal documents with an optional type filter', function (): void {
LegalDocument::factory()->create([
'slug' => 'privacy-policy',
'type' => LegalDocumentType::PRIVACY_POLICY,
]);
LegalDocument::factory()->terms()->create([
'slug' => 'terms-of-service',
'type' => LegalDocumentType::TERMS,
]);
$this
->getJson('/api/legal-documents?type=terms')
->assertOk()
->assertJsonCount(1, 'data')
->assertJsonPath('data.0.slug', 'terms-of-service')
->assertJsonPath('data.0.type', LegalDocumentType::TERMS->value);
});
it('keeps only one active version per slug', function (): void {
$firstVersion = LegalDocument::factory()->create([
'slug' => 'privacy-policy',
'version' => 1,
'is_active' => true,
]);
LegalDocument::factory()->create([
'slug' => 'privacy-policy',
'version' => 2,
'is_active' => true,
]);
expect($firstVersion->fresh()->is_active)->toBeFalse();
});
it('exposes legal documents in filament', function (): void {
app()->setLocale('fr');
Filament::setCurrentPanel(Filament::getPanel('dashboard'));
$admin = User::factory()->create([
'role' => UserRole::ADMIN,
]);
$document = LegalDocument::factory()->create([
'slug' => 'privacy-policy',
]);
$this->actingAs($admin);
Livewire::test(ListLegalDocuments::class)
->assertTableColumnExists(
'slug',
fn (TextColumn $column): bool => $column->getLabel() === 'Slug',
)
->assertTableFilterExists(
'type',
fn (SelectFilter $filter): bool => $filter->getLabel() === 'Type'
&& $filter->getOptions() === [
'privacy_policy' => 'Politique de confidentialité',
'terms' => 'Conditions dutilisation',
],
)
->assertSee('privacy-policy');
Livewire::test(EditLegalDocument::class, ['record' => $document->getKey()])
->assertFormFieldExists(
'title.fr',
null,
fn (TextInput $field): bool => $field->getLabel() === 'Titre',
)
->assertFormFieldExists(
'content.fr.intro',
null,
fn (Repeater $field): bool => $field->getLabel() === 'Introduction',
)
->assertFormFieldExists(
'content.fr.sections',
null,
fn (Repeater $field): bool => $field->getLabel() === 'Sections',
);
});
it('creates a new inactive unpublished version from filament', function (): void {
app()->setLocale('fr');
Filament::setCurrentPanel(Filament::getPanel('dashboard'));
$admin = User::factory()->create([
'role' => UserRole::ADMIN,
]);
$document = LegalDocument::factory()->create([
'slug' => 'privacy-policy',
'version' => 3,
'is_active' => true,
'published_at' => now(),
]);
$this->actingAs($admin);
Livewire::test(ListLegalDocuments::class)
->callTableAction('createNewVersion', $document);
$newVersion = LegalDocument::query()
->where('slug', 'privacy-policy')
->where('version', 4)
->firstOrFail();
expect($newVersion->title)->toBe($document->title)
->and($newVersion->content)->toBe($document->content)
->and($newVersion->is_active)->toBeFalse()
->and($newVersion->published_at)->toBeNull();
});