tests/legal: Testdatenbank-Guard vor den DB-Traits, Flags in phpunit.xml gepinnt, Zustimmung an gezeigte Fassung gebunden (Umsetzungsaudit 25.09.: N22, N06, 5.3)

- Tests\TestCase prüft die Standardverbindung in setUpTraits(), also vor
  RefreshDatabase — bisher erst nach dem Refresh (N22). Eigener Test.
- phpunit.xml pinnt IMAGE_RIGHTS_V2, IMAGE_PRECHECK(_STAGE) und
  LEGAL_ACCEPTANCE_GATE auf die Vorgaben aus .env.example; die Suite hing
  sonst an der lokalen .env (Audit Abschnitt 6).
- Zustimmungsgate: die Livewire-Komponenten tragen die beim Rendern gezeigten
  Fassungen (Trait-Hook rendering); weicht die aktuelle Fassung beim Absenden
  ab, wird die Annahme abgelehnt und der neue Wortlaut gezeigt. Ein fehlendes
  Pflichtdokument ist bei aktivem Gate ein Konfigurationsfehler (N06).
- Audit vom 25.09., Decision-Update vom 22.09. und Plan Fassung 2 versioniert;
  die Antwortkopie „…-211.md" entfernt; U10-Formulierung im Plan präzisiert.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-25 13:35:14 +00:00
parent d99f55e555
commit 4e34c3d0d1
10 changed files with 1436 additions and 10 deletions

View file

@ -97,6 +97,51 @@ test('with the gate on the submit requires an active acceptance of agb and guide
expect(app(LegalAcceptanceGate::class)->requiredFor($owner)->pluck('version')->all())->toBe(['0.7']);
});
test('a confirmation is bound to the versions that were shown, a newer version must be read and accepted again', function () {
/** @var TestCase $this */
config()->set('legal.acceptance_gate', true);
['owner' => $owner, 'pr' => $pr] = legalGateDraft();
$this->actingAs($owner);
$component = LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id])
->assertSee('Version 0.6')
->set('aiTextDeclaration', 'none')
->set('aiDeclarationConfirmed', true)
->set('legalAcceptanceConfirmed', true);
expect($component->get('legalAcceptanceVersions')['agb'])->toBe('0.6');
// Zwischen Anzeige und Absenden wird eine neue AGB-Fassung wirksam.
LegalDocument::factory()->agb()->create(['version' => '0.7', 'effective_from' => now()->subDay()->toDateString()]);
$component->call('submitForReview')->assertHasErrors(['legalAcceptanceConfirmed']);
expect(LegalDocumentAcceptance::query()->count())->toBe(0)
->and($pr->fresh()->status)->toBe(PressReleaseStatus::Draft)
->and($component->get('legalAcceptanceConfirmed'))->toBeFalse()
->and($component->get('legalAcceptanceVersions')['agb'])->toBe('0.7');
// Neu gelesen und bestätigt: jetzt wird genau 0.7 protokolliert.
$component->assertSee('Version 0.7')
->set('aiDeclarationConfirmed', true)
->set('legalAcceptanceConfirmed', true)
->call('submitForReview')
->assertHasNoErrors();
expect(LegalDocumentAcceptance::query()->where('type', 'agb')->pluck('version')->all())->toBe(['0.7'])
->and($pr->fresh()->status)->not->toBe(PressReleaseStatus::Draft);
});
test('a missing required document is a configuration error while the gate is on, not a smaller gate', function () {
/** @var TestCase $this */
config()->set('legal.acceptance_gate', true);
['owner' => $owner] = legalGateDraft();
LegalDocument::query()->where('type', 'richtlinien')->delete();
expect(fn () => app(LegalAcceptanceGate::class)->requiredFor($owner))->toThrow(RuntimeException::class, 'richtlinien');
});
test('acceptances are insert-only', function () {
config()->set('legal.acceptance_gate', true);
['owner' => $owner] = legalGateDraft();