get('https://pressekonto.test/')->assertSuccessful(); expect($response->getContent()) ->toContain('Verträge hier kündigen') ->toContain(route('kuendigung', ['edition' => 'de'])); }); test('the termination confirmation page renders the § 312k form with the hub shell', function () { /** @var TestCase $this */ $response = $this->get('https://pressekonto.test/de/kuendigung')->assertSuccessful(); $content = $response->getContent(); expect($content) // Pflichtangaben der Bestätigungsseite (§ 312k Abs. 2 BGB). ->toContain('Ordentliche Kündigung') ->toContain('Außerordentliche Kündigung') ->toContain('name="kind"') ->toContain('name="reason"') ->toContain('name="terminate_mode"') ->toContain('Zum nächstmöglichen Zeitpunkt') // Bestätigungsschaltfläche mit gesetzeskonformer Aufschrift. ->toContain('jetzt kündigen') // Hub-Gerüst (host-aware static-page). ->toContain('Publisher · Hub'); }); test('an ordinary termination is persisted and both mails are sent immediately', function () { /** @var TestCase $this */ Mail::fake(); config()->set('domains.domains.pressekonto.brand.contact_email', 'kontakt@pressekonto.de'); $this->from('https://pressekonto.test/de/kuendigung') ->post('https://pressekonto.test/de/kuendigung', [ 'kind' => 'ordentlich', 'name' => 'Paula Presse', 'email' => 'paula@example.test', 'contract_reference' => 'STR-2026-0042', 'terminate_mode' => 'asap', ]) ->assertRedirect('https://pressekonto.test/de/kuendigung') ->assertSessionHas('termination-status'); $request = TerminationRequest::query()->firstOrFail(); expect($request->kind)->toBe('ordentlich'); expect($request->reason)->toBeNull(); expect($request->name)->toBe('Paula Presse'); expect($request->email)->toBe('paula@example.test'); expect($request->contract_reference)->toBe('STR-2026-0042'); expect($request->terminate_at)->toBeNull(); expect($request->host)->toBe('pressekonto.test'); expect($request->status)->toBe('open'); // § 312k Abs. 4 BGB: sofortige automatische Zugangsbestätigung. Mail::assertSent(TerminationRequestReceived::class, fn (TerminationRequestReceived $mail) => $mail->hasTo('paula@example.test')); Mail::assertSent(TerminationRequestSubmitted::class, fn (TerminationRequestSubmitted $mail) => $mail->hasTo('kontakt@pressekonto.de')); }); test('an extraordinary termination requires a reason', function () { /** @var TestCase $this */ Mail::fake(); $this->post('https://pressekonto.test/de/kuendigung', [ 'kind' => 'ausserordentlich', 'name' => 'Paula Presse', 'email' => 'paula@example.test', 'terminate_mode' => 'asap', ])->assertSessionHasErrorsIn('termination', ['reason']); expect(TerminationRequest::query()->count())->toBe(0); Mail::assertNothingSent(); $this->post('https://pressekonto.test/de/kuendigung', [ 'kind' => 'ausserordentlich', 'reason' => 'Wiederholte Störung der Leistung.', 'name' => 'Paula Presse', 'email' => 'paula@example.test', 'terminate_mode' => 'asap', ])->assertSessionHas('termination-status'); expect(TerminationRequest::query()->firstOrFail()->reason)->toBe('Wiederholte Störung der Leistung.'); }); test('a termination to a specific date requires and persists the date', function () { /** @var TestCase $this */ Mail::fake(); $this->post('https://pressekonto.test/de/kuendigung', [ 'kind' => 'ordentlich', 'name' => 'Paula Presse', 'email' => 'paula@example.test', 'terminate_mode' => 'date', ])->assertSessionHasErrorsIn('termination', ['terminate_at']); $this->post('https://pressekonto.test/de/kuendigung', [ 'kind' => 'ordentlich', 'name' => 'Paula Presse', 'email' => 'paula@example.test', 'terminate_mode' => 'date', 'terminate_at' => '2026-08-31', ])->assertSessionHas('termination-status'); expect(TerminationRequest::query()->firstOrFail()->terminate_at->format('Y-m-d'))->toBe('2026-08-31'); }); test('termination validation errors land in the termination error bag', function () { /** @var TestCase $this */ Mail::fake(); $this->post('https://pressekonto.test/de/kuendigung', [ 'name' => '', 'email' => 'keine-mail', ])->assertSessionHasErrorsIn('termination', ['kind', 'name', 'email', 'terminate_mode']); expect(TerminationRequest::query()->count())->toBe(0); Mail::assertNothingSent(); }); test('honeypot submissions are silently accepted without persisting or mailing', function () { /** @var TestCase $this */ Mail::fake(); $this->post('https://pressekonto.test/de/kuendigung', [ 'kind' => 'ordentlich', 'name' => 'Bot', 'email' => 'bot@example.test', 'terminate_mode' => 'asap', 'website' => 'https://spam.example', ])->assertSessionHas('termination-status'); expect(TerminationRequest::query()->count())->toBe(0); Mail::assertNothingSent(); });