129 lines
5.2 KiB
PHP
129 lines
5.2 KiB
PHP
<?php // tests/Feature/Cancellation/CancelAsksAboutExportTest.php
|
|
|
|
use App\Livewire\ConfirmCancelPackage;
|
|
use App\Models\Customer;
|
|
use App\Models\Instance;
|
|
use App\Models\Order;
|
|
use App\Models\User;
|
|
use Livewire\Livewire;
|
|
|
|
/**
|
|
* Abweichung vom Zettel: keine der drei Prüfungen unten setzt im Original
|
|
* `reason`. Im Bestand verlangt ConfirmCancelPackage::cancelPackage() aber
|
|
* schon länger einen gültigen Grund (Subscription::CANCEL_REASONS) und
|
|
* bricht sonst VOR jeder Schreibaktion mit einem eigenen Fehler ab — das war
|
|
* so, bevor diese Aufgabe begann, und diese Aufgabe ändert daran nichts. Ohne
|
|
* `->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');
|
|
});
|