76 lines
2.8 KiB
PHP
76 lines
2.8 KiB
PHP
<?php
|
||
|
||
use App\Mail\InvoiceMail;
|
||
use App\Models\Customer;
|
||
use App\Models\Order;
|
||
use App\Services\Billing\IssueInvoice;
|
||
use App\Support\CompanyProfile;
|
||
|
||
beforeEach(function () {
|
||
CompanyProfile::put([
|
||
'name' => 'CluPilot Cloud e.U.',
|
||
'address' => 'Dreherstraße 66/1/8',
|
||
'postcode' => '1110',
|
||
'city' => 'Wien',
|
||
'vat_id' => 'ATU00000000',
|
||
]);
|
||
});
|
||
|
||
function issuedInvoice(): App\Models\Invoice
|
||
{
|
||
$customer = Customer::factory()->create(['name' => 'Muster GmbH']);
|
||
$orders = collect([Order::factory()->create([
|
||
'customer_id' => $customer->id, 'amount_cents' => 1900, 'currency' => 'EUR', 'status' => 'paid',
|
||
])]);
|
||
|
||
return app(IssueInvoice::class)->forOrders($customer, $orders);
|
||
}
|
||
|
||
it('attaches the invoice as a PDF named after its number', function () {
|
||
// Filename and type only. The bytes are not asserted here and deliberately
|
||
// not: TCPDF embeds a creation time and a document id, so two renders of
|
||
// one invoice differ — a byte comparison would fail for a reason that has
|
||
// nothing to do with the mail. What the renderer produces is tested where
|
||
// the renderer is.
|
||
$invoice = issuedInvoice();
|
||
|
||
$attachment = (new InvoiceMail($invoice, 'Muster GmbH'))->attachments()[0];
|
||
|
||
expect($attachment->as)->toBe($invoice->number.'.pdf')
|
||
->and($attachment->mime)->toBe('application/pdf');
|
||
});
|
||
|
||
it('renders a real PDF for the attachment to carry', function () {
|
||
// The attachment is a closure, and a closure that returns nothing still
|
||
// makes a perfectly valid mail with a nought-byte file on it. This is the
|
||
// half that would be empty.
|
||
$bytes = app(App\Services\Billing\InvoiceRenderer::class)->forInvoice(issuedInvoice());
|
||
|
||
expect(substr($bytes, 0, 5))->toBe('%PDF-')
|
||
->and(strlen($bytes))->toBeGreaterThan(10000);
|
||
});
|
||
|
||
it('renders it from the frozen document, not from today’s settings', function () {
|
||
$invoice = issuedInvoice();
|
||
|
||
CompanyProfile::put(['name' => 'Ein ganz anderer Name GmbH']);
|
||
|
||
// The snapshot is what the renderer reads. The settings moved underneath
|
||
// it and the document did not.
|
||
expect($invoice->refresh()->snapshot['issuer']['name'])->toBe('CluPilot Cloud e.U.')
|
||
->and(app(App\Services\Billing\InvoiceRenderer::class)->forInvoice($invoice))
|
||
->toBeString()->not->toBeEmpty();
|
||
});
|
||
|
||
it('names the amount and the number where somebody can read them', function () {
|
||
// The attachment is the document; the mail still has to say what it is
|
||
// about, because some clients only reveal an attachment once opened.
|
||
$invoice = issuedInvoice();
|
||
|
||
$rendered = (new InvoiceMail($invoice, 'Muster GmbH'))->render();
|
||
|
||
expect($rendered)->toContain($invoice->number)
|
||
->toContain('22,80')
|
||
->toContain(__('mail.why_you_got_this'));
|
||
});
|