set('reason', ...)` würde jede der drei Prüfungen an dieser * vorgelagerten Stelle scheitern, nicht an der Exportfrage, die hier geprüft * werden soll. Alle drei setzen deshalb zusätzlich einen gültigen Grund. */ /** * Ein aktives Paket, dessen Besitzer den Kündigungsdialog erreichen kann — * nach dem Muster von settingsSetup() (tests/Feature/SettingsTest.php) und * cancellablePackage() (tests/Feature/Billing/PackageCancellationTest.php): * Nutzer, Kunde, Bestellung, aktive Instanz. Bewusst OHNE eigenen * Subscription-Datensatz: ConfirmCancelPackage::contractFor() findet dann * keinen Vertrag, und stopBilling(null) gibt ungefragt true zurück (derselbe * Weg wie bei einem geschenkten Paket) — Stripe bleibt außen vor, weil es in * dieser Aufgabe ausschließlich um die Exportfrage geht. * * @return array{0: User, 1: Instance} */ function kuendbareInstanz(): array { $user = User::factory()->create(['email' => 'kuendigt@example.test', 'email_verified_at' => now()]); $customer = Customer::factory()->create([ 'email' => 'kuendigt@example.test', 'user_id' => $user->id, 'status' => 'active', ]); $order = Order::factory()->create(['customer_id' => $customer->id, 'plan' => 'team']); $instance = Instance::factory()->create([ 'customer_id' => $customer->id, 'order_id' => $order->id, 'plan' => 'team', 'status' => 'active', 'subdomain' => 'kuendigt', ]); return [$user, $instance->refresh()]; } it('schreibt die Antwort des Kunden an die Instanz', function () { [$user, $instance] = kuendbareInstanz(); Livewire::actingAs($user)->test(ConfirmCancelPackage::class) ->set('confirmName', $instance->subdomain) ->set('reason', 'no_longer_needed') ->set('exportWish', true) ->call('cancelPackage') ->assertHasNoErrors(); expect($instance->fresh()->export_wish)->toBeTrue(); }); it('nimmt auch ein Nein als Antwort — und nicht als fehlende Antwort', function () { // Das ist die Zusicherung, um die es geht: wer bewusst nein sagt, soll // nicht wie jemand behandelt werden, den niemand gefragt hat. Nur das // erspart ihm die Erinnerungen und uns die Arbeit. [$user, $instance] = kuendbareInstanz(); Livewire::actingAs($user)->test(ConfirmCancelPackage::class) ->set('confirmName', $instance->subdomain) ->set('reason', 'no_longer_needed') ->set('exportWish', false) ->call('cancelPackage') ->assertHasNoErrors(); expect($instance->fresh()->export_wish)->toBeFalse() ->and($instance->fresh()->export_wish)->not->toBeNull(); }); it('verspricht im Kündigungsdialog keinen Export, den es noch nicht gibt', function (string $sprache, array $verboten) { // Die Fix-Welle hat drei von vier Stellen zurückgenommen; diese vierte ist // die wirksamste, weil sie im Moment der Entscheidung steht. Der Kunde las // hier einen Liefergegenstand („einen Link zum Herunterladen"), klickte // einmal auf Ja — und die Vertragsseite sagte ihm danach nur noch, sein // Wunsch sei vermerkt. Geprüft in beiden Sprachen und am gerenderten // Dialog, nicht an der Sprachdatei: der Widerspruch entstand dadurch, dass // ein Satz irgendwo stehen blieb, und genau das fällt nur auf, wenn die // Prüfung dorthin schaut, wo der Kunde liest. app()->setLocale($sprache); [$user] = kuendbareInstanz(); $dialog = Livewire::actingAs($user)->test(ConfirmCancelPackage::class); foreach ($verboten as $versprechen) { $dialog->assertDontSee($versprechen); } // Und der Satz, der stattdessen dort steht, muss auch wirklich ankommen — // sonst wäre die Prüfung oben schon dadurch grün, dass der Dialog gar // nichts über den Export sagt. $dialog->assertSee(__('settings.cancel_export_hint')) ->assertSee(__('settings.cancel_point_export')); })->with([ ['de', ['Link zum Herunterladen', 'erhalten Sie auf Wunsch einen vollständigen Datenexport']], ['en', ['download link', 'you receive a full data export']], ]); it('kündigt nicht ohne eine Antwort auf die Frage', function () { // Eine Frage, die man überspringen kann, ist keine Frage — und die // Kündigung ist der einzige Moment, in dem der Kunde ohnehin über seine // Daten nachdenkt. [$user, $instance] = kuendbareInstanz(); Livewire::actingAs($user)->test(ConfirmCancelPackage::class) ->set('confirmName', $instance->subdomain) ->set('reason', 'no_longer_needed') ->call('cancelPackage') ->assertHasErrors('exportWish'); expect($instance->fresh()->status)->toBe('active'); });