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 d’utilisation', ], ) ->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(); });