create([ 'user_id' => $user->id, 'user_payment_id' => null, 'number' => 'STR-00042', 'status' => InvoiceStatus::Paid->value, 'stripe_invoice_id' => 'in_test_42', ...$overrides, ]); } test('without billing settings the account gets the pdf and no second address is used', function () { $user = User::factory()->create(); $delivery = InvoiceDelivery::for($user); expect($delivery->attachPdfForAccount)->toBeTrue(); expect($delivery->invoiceEmail)->toBeNull(); }); test('an enabled invoice email is used and the account pdf follows its own switch', function () { $user = User::factory()->create(); BillingAddress::factory()->create([ 'user_id' => $user->id, 'invoice_email' => 'buchhaltung@example.com', 'invoice_pdf_to_account' => false, 'invoice_pdf_to_invoice_email' => true, ]); $delivery = InvoiceDelivery::for($user); expect($delivery->attachPdfForAccount)->toBeFalse(); expect($delivery->invoiceEmail)->toBe('buchhaltung@example.com'); }); test('a disabled invoice email is not used', function () { $user = User::factory()->create(); BillingAddress::factory()->create([ 'user_id' => $user->id, 'invoice_email' => 'buchhaltung@example.com', 'invoice_pdf_to_invoice_email' => false, ]); expect(InvoiceDelivery::for($user)->invoiceEmail)->toBeNull(); }); test('an invoice email equal to the account email collapses into one mail with pdf', function () { $user = User::factory()->create(['email' => 'max@example.com']); BillingAddress::factory()->create([ 'user_id' => $user->id, 'invoice_email' => 'MAX@example.com', 'invoice_pdf_to_account' => false, 'invoice_pdf_to_invoice_email' => true, ]); $delivery = InvoiceDelivery::for($user); expect($delivery->attachPdfForAccount)->toBeTrue(); expect($delivery->invoiceEmail)->toBeNull(); }); test('the payment confirmation attaches the stripe pdf only when asked to', function () { $user = User::factory()->create(); $invoice = deliveryInvoice($user); $this->mock(StripeInvoicePdf::class, function ($mock) { $mock->shouldReceive('filename')->andReturn('Rechnung-STR-00042.pdf'); $mock->shouldReceive('contents')->andReturn('%PDF-1.4 test'); }); $withPdf = new BookingPaymentConfirmed($user, $invoice, attachPdf: true); $withPdf->assertHasAttachedData('%PDF-1.4 test', 'Rechnung-STR-00042.pdf', ['mime' => 'application/pdf']); $withPdf->assertSeeInHtml('als PDF im Anhang'); $withoutPdf = new BookingPaymentConfirmed($user, $invoice); expect($withoutPdf->attachments())->toBe([]); $withoutPdf->assertDontSeeInHtml('als PDF im Anhang'); }); test('the copy for the invoice email names the account and skips the bcc and login button', function () { $user = User::factory()->create(['name' => 'Max Muster', 'email' => 'max@example.com']); $invoice = deliveryInvoice($user); $this->mock(StripeInvoicePdf::class, function ($mock) { $mock->shouldReceive('filename')->andReturn('Rechnung-STR-00042.pdf'); $mock->shouldReceive('contents')->andReturn('%PDF-1.4 test'); }); $mail = new BookingPaymentConfirmed($user, $invoice, attachPdf: true, forInvoiceRecipient: true); $mail->assertHasSubject('Rechnung STR-00042 — pressekonto'); $mail->assertSeeInHtml('im Auftrag von Max Muster (max@example.com)'); $mail->assertDontSeeInHtml('Rechnung im Konto ansehen'); expect($mail->hasBcc((string) config('legal.contact_email')))->toBeFalse(); }); test('a stored stripe pdf is served without asking stripe again', function () { Storage::fake('local'); Storage::disk('local')->put('invoices/stripe/STR-00042.pdf', '%PDF-1.4 cached'); $invoice = deliveryInvoice(User::factory()->create()); expect(app(StripeInvoicePdf::class)->contents($invoice))->toBe('%PDF-1.4 cached'); }); test('an invoice without stripe id has no stripe pdf', function () { $invoice = deliveryInvoice(User::factory()->create(), ['stripe_invoice_id' => null, 'number' => 'MAN-00001']); expect(fn () => app(StripeInvoicePdf::class)->contents($invoice))->toThrow(RuntimeException::class); }); test('the owner opens the stripe invoice pdf inline, others get a 404', function () { /** @var TestCase $this */ $this->seed(RolesAndPermissionsSeeder::class); Storage::fake('local'); Storage::disk('local')->put('invoices/stripe/STR-00042.pdf', '%PDF-1.4 cached'); $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $intruder = User::factory()->create(['is_active' => true]); $intruder->assignRole('customer'); $invoice = deliveryInvoice($customer); $this->actingAs($customer) ->get(route('me.invoices.stripe-pdf', $invoice)) ->assertSuccessful() ->assertHeader('Content-Type', 'application/pdf') ->assertHeader('Content-Disposition', 'inline; filename="Rechnung-STR-00042.pdf"'); $this->actingAs($intruder) ->get(route('me.invoices.stripe-pdf', $invoice)) ->assertNotFound(); }); test('an unreachable stripe pdf sends the customer back with a notice', function () { /** @var TestCase $this */ $this->seed(RolesAndPermissionsSeeder::class); $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $invoice = deliveryInvoice($customer); $this->mock(StripeInvoicePdf::class, function ($mock) { $mock->shouldReceive('inlineResponse')->andThrow(new RuntimeException('Stripe down')); }); $this->actingAs($customer) ->get(route('me.invoices.stripe-pdf', $invoice)) ->assertRedirect(route('me.invoices.index')) ->assertSessionHas('invoice-error'); }); test('the profile stores the invoice email and both pdf switches with the billing address', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $this->actingAs($customer); Livewire::test('customer.profile') ->set('billingLastName', 'Mustermann') ->set('billingAddress1', 'Musterstrasse 1') ->set('billingPostalCode', '10115') ->set('billingCity', 'Berlin') ->set('billingCountryCode', 'DE') ->set('invoiceEmail', 'buchhaltung@example.com') ->assertSee('Rechnungen als PDF an diese Adresse senden') ->set('invoicePdfToAccount', false) ->set('invoicePdfToInvoiceEmail', true) ->call('saveProfile') ->assertHasNoErrors(); $billing = $customer->fresh()->billingAddress; expect($billing->invoice_email)->toBe('buchhaltung@example.com'); expect($billing->invoice_pdf_to_account)->toBeFalse(); expect($billing->invoice_pdf_to_invoice_email)->toBeTrue(); }); test('the invoice email must be valid and needs a complete billing address', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $this->actingAs($customer); Livewire::test('customer.profile') ->set('invoiceEmail', 'keine-adresse') ->call('saveProfile') ->assertHasErrors(['invoiceEmail', 'billingLastName', 'billingAddress1']); });