CluPilotCloud/tests/Feature/Mail/MailboxTransportTest.php

79 lines
3.5 KiB
PHP

<?php
use App\Mail\Transport\MailboxTransport;
use App\Models\Mailbox;
use App\Services\Mail\MailPurpose;
use App\Support\Settings;
use Illuminate\Mail\Transport\LogTransport;
use Illuminate\Support\Facades\Mail;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
beforeEach(function () {
config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
Settings::set('mail.host', 'mail.example.test');
Settings::set('mail.port', 587);
Settings::set('mail.encryption', 'tls');
});
it('registers a mailer per purpose without touching the database at boot', function () {
// The five entries exist as plain config — no query has run to build them.
foreach (MailPurpose::ALL as $purpose) {
expect(config('mail.mailers.cp_'.$purpose))
->toMatchArray(['transport' => 'mailbox', 'purpose' => $purpose]);
}
});
it('builds the transport from the mailbox that is current at send time', function () {
Mailbox::factory()->create(['key' => 'support', 'address' => 'support@clupilot.com']);
Settings::set(MailPurpose::settingKey(MailPurpose::SUPPORT), 'support');
config()->set('mail.default', 'smtp'); // delivery on, as on live
$transport = Mail::mailer('cp_support')->getSymfonyTransport();
expect($transport)->toBeInstanceOf(MailboxTransport::class)
->and((string) $transport)->toContain('support@clupilot.com');
});
it('logs instead of delivering while MAIL_MAILER is log', function () {
Mailbox::factory()->create(['key' => 'support', 'address' => 'support@clupilot.com']);
Settings::set(MailPurpose::settingKey(MailPurpose::SUPPORT), 'support');
config()->set('mail.default', 'log');
$transport = Mail::mailer('cp_support')->getSymfonyTransport();
// Still our transport — but it hands the message to the log, so a seeder
// run cannot mail a real customer from a development machine.
expect((string) $transport)->toContain('log');
});
/*
| __toString() and send() decide "log or SMTP" through two SEPARATE code
| paths (describe() vs delegate()). The test above only exercises the first —
| it would keep passing even if delegate() lost its own guard and sent every
| purpose-mailer through real SMTP regardless of MAIL_MAILER. Reach into the
| method that actually sends, so that regression cannot hide behind a passing
| __toString() assertion. No real socket is opened either way: EsmtpTransport
| connects lazily on send(), never in its constructor.
*/
it('actually delegates to the log transport, not SMTP, while MAIL_MAILER is log', function () {
Mailbox::factory()->create(['key' => 'support', 'address' => 'support@clupilot.com']);
Settings::set(MailPurpose::settingKey(MailPurpose::SUPPORT), 'support');
config()->set('mail.default', 'log');
$transport = Mail::mailer('cp_support')->getSymfonyTransport();
$delegate = Closure::bind(fn () => $this->delegate(), $transport, MailboxTransport::class)();
expect($delegate)->toBeInstanceOf(LogTransport::class);
});
it('delegates to a real SMTP transport once MAIL_MAILER is no longer log', function () {
Mailbox::factory()->create(['key' => 'support', 'address' => 'support@clupilot.com']);
Settings::set(MailPurpose::settingKey(MailPurpose::SUPPORT), 'support');
config()->set('mail.default', 'smtp');
$transport = Mail::mailer('cp_support')->getSymfonyTransport();
$delegate = Closure::bind(fn () => $this->delegate(), $transport, MailboxTransport::class)();
expect($delegate)->toBeInstanceOf(EsmtpTransport::class);
});