presseportale/tests/Feature/Web/WithdrawalRequestTest.php
Kevin Adametz fe1525b9ff auth/mail: Magic-Link-2FA (M1) + Mailversand über die Queue
- Magic-Link-Login übergibt bei aktiviertem 2FA an die 2FA-Challenge,
  statt sie zu umgehen (M1).
- Bestätigungs-/Benachrichtigungs-Mails (Kontakt, Recht, Kündigung,
  Widerruf, Magic-Link) laufen als ShouldQueue+afterCommit über die Queue,
  damit die Response nicht am SMTP-Roundtrip hängt.

Hinweis: Der Queue-Worker muss im Betrieb laufen und überwacht werden, da
fristrelevante Bestätigungen darüber zugestellt werden (siehe
Betriebsüberwachung).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 13:49:21 +00:00

99 lines
3.7 KiB
PHP

<?php
use App\Mail\WithdrawalRequestReceived;
use App\Mail\WithdrawalRequestSubmitted;
use App\Models\WithdrawalRequest;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
test('the withdrawal ui is retired on the hub (B2B-only, decision E2)', function () {
/** @var TestCase $this */
// Der Widerrufs-Button/-Modal entfällt seit der B2B-only-Entscheidung
// (E2, 03.07.2026); der POST-Endpunkt bleibt schlafend erhalten und ist
// bei einer B2C-Öffnung reaktivierbar (samt archivierter Belehrung).
$response = $this->get('https://pressekonto.test/')->assertSuccessful();
$content = $response->getContent();
expect($content)
->not->toContain('Vertrag widerrufen')
->not->toContain('open-withdrawal-modal');
});
test('a withdrawal is persisted and both mails are queued after persistence', function () {
/** @var TestCase $this */
Mail::fake();
config()->set('domains.domains.pressekonto.brand.contact_email', 'kontakt@pressekonto.de');
$this->from('https://pressekonto.test/')
->post('https://pressekonto.test/widerruf', [
'name' => 'Paula Presse',
'email' => 'paula@example.test',
'order_reference' => 'STR-2026-0042',
])
->assertRedirect('https://pressekonto.test/')
->assertSessionHas('withdrawal-status');
$request = WithdrawalRequest::query()->firstOrFail();
expect($request->name)->toBe('Paula Presse');
expect($request->email)->toBe('paula@example.test');
expect($request->order_reference)->toBe('STR-2026-0042');
expect($request->host)->toBe('pressekonto.test');
expect($request->status)->toBe('open');
// Gesetzlich vorgeschrieben: sofortige automatische Eingangsbestätigung.
Mail::assertQueued(WithdrawalRequestReceived::class, fn (WithdrawalRequestReceived $mail) => $mail->hasTo('paula@example.test'));
Mail::assertQueued(WithdrawalRequestSubmitted::class, fn (WithdrawalRequestSubmitted $mail) => $mail->hasTo('kontakt@pressekonto.de'));
});
test('the order reference is optional', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://pressekonto.test/widerruf', [
'name' => 'Paula Presse',
'email' => 'paula@example.test',
])->assertSessionHas('withdrawal-status');
expect(WithdrawalRequest::query()->firstOrFail()->order_reference)->toBeNull();
});
test('withdrawal validation errors land in the withdrawal error bag', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://pressekonto.test/widerruf', [
'name' => '',
'email' => 'keine-mail',
])->assertSessionHasErrorsIn('withdrawal', ['name', 'email']);
expect(WithdrawalRequest::query()->count())->toBe(0);
Mail::assertNothingOutgoing();
});
test('honeypot submissions are silently accepted without persisting or mailing', function () {
/** @var TestCase $this */
Mail::fake();
$this->post('https://pressekonto.test/widerruf', [
'name' => 'Bot',
'email' => 'bot@example.test',
'website' => 'https://spam.example',
])->assertSessionHas('withdrawal-status');
expect(WithdrawalRequest::query()->count())->toBe(0);
Mail::assertNothingOutgoing();
});
test('a withdrawal from a spoke domain goes to that brand address', function () {
/** @var TestCase $this */
Mail::fake();
config()->set('domains.domains.presseecho.brand.contact_email', 'redaktion@presseecho.de');
$this->post('https://presseecho.test/widerruf', [
'name' => 'Paula Presse',
'email' => 'paula@example.test',
])->assertSessionHas('withdrawal-status');
Mail::assertQueued(WithdrawalRequestSubmitted::class, fn (WithdrawalRequestSubmitted $mail) => $mail->hasTo('redaktion@presseecho.de'));
});