CluPilotCloud/tests/Feature/Portal/OpenInvoicesTest.php

107 lines
3.6 KiB
PHP

<?php
use App\Livewire\OpenInvoices;
use App\Models\Customer;
use App\Models\User;
use App\Services\Stripe\FakeStripeClient;
use App\Services\Stripe\StripeClient;
use Livewire\Livewire;
function portalUserOwing(FakeStripeClient $fake): User
{
$fake->openInvoiceRows = [[
'id' => 'in_1', 'number' => 'R-1', 'amount_due_cents' => 21480,
'currency' => 'EUR', 'created_at' => '1750000000',
]];
$user = User::factory()->create(['email' => 'schuldner@portal.test', 'is_admin' => false]);
Customer::factory()->create(['email' => 'schuldner@portal.test', 'stripe_customer_id' => 'cus_42']);
return $user;
}
it('shows what is still owed', function () {
$fake = new FakeStripeClient;
app()->instance(StripeClient::class, $fake);
Livewire::actingAs(portalUserOwing($fake))
->test(OpenInvoices::class)
->assertSee('R-1')
->assertSee('214,80');
});
it('settles an invoice when the customer asks', function () {
$fake = new FakeStripeClient;
app()->instance(StripeClient::class, $fake);
Livewire::actingAs(portalUserOwing($fake))
->test(OpenInvoices::class)
->call('pay', 'in_1')
->assertHasNoErrors();
expect($fake->paidInvoices)->toBe(['in_1']);
});
it('shows a refusal instead of pretending it worked', function () {
// Der Fall, der wirklich eintritt. Eine grüne Meldung über einer
// abgelehnten Karte ist die teuerste Anzeige, die diese Seite haben kann:
// der Kunde geht davon aus, es sei erledigt, und die nächste Nachricht,
// die er bekommt, ist eine Mahnung.
$fake = new FakeStripeClient;
$fake->payDeclines = true;
app()->instance(StripeClient::class, $fake);
Livewire::actingAs(portalUserOwing($fake))
->test(OpenInvoices::class)
->call('pay', 'in_1')
->assertSee('declined');
expect($fake->paidInvoices)->toBe([]);
});
it('refuses to pay an invoice that is not this customer\'s', function () {
// Die ID kommt aus dem Browser. Ohne diese Prüfung könnte jemand eine
// fremde Rechnungs-ID einreichen — und Stripe zöge sie beim fremden Kunden
// ein, auf dessen Karte.
$fake = new FakeStripeClient;
app()->instance(StripeClient::class, $fake);
Livewire::actingAs(portalUserOwing($fake))
->test(OpenInvoices::class)
->call('pay', 'in_fremd')
->assertForbidden();
expect($fake->paidInvoices)->toBe([]);
});
it('stops paying the rest after the first refusal', function () {
// Alle weiteren scheitern an derselben Karte, und drei Ablehnungen
// hintereinander lassen Stripes Betrugserkennung anschlagen — danach
// lehnt sie auch die Karte ab, die in Ordnung wäre.
$fake = new FakeStripeClient;
$fake->payDeclines = true;
app()->instance(StripeClient::class, $fake);
$user = portalUserOwing($fake);
$fake->openInvoiceRows[] = [
'id' => 'in_2', 'number' => 'R-2', 'amount_due_cents' => 1000,
'currency' => 'EUR', 'created_at' => '1750000000',
];
Livewire::actingAs($user)->test(OpenInvoices::class)->call('payAll');
expect($fake->paidInvoices)->toBe([]);
});
it('says so plainly when nothing is open', function () {
$fake = new FakeStripeClient;
app()->instance(StripeClient::class, $fake);
$user = User::factory()->create(['email' => 'schuldenfrei@portal.test', 'is_admin' => false]);
Customer::factory()->create(['email' => 'schuldenfrei@portal.test', 'stripe_customer_id' => 'cus_9']);
Livewire::actingAs($user)
->test(OpenInvoices::class)
->assertSee(__('billing.invoices_none'));
});