firstWhere('key', $key); } /** * `mail.default = log` heißt: die VM läuft, der Beleg ist geschrieben, und die * Mail, die dem Kunden seine fertige Cloud ankündigt, liegt in einer Datei auf * dem Server. Der Kunde erfährt nie, dass er eine Cloud hat. Kein Fehler * taucht irgendwo auf. */ it('refuses to call an installation ready while mail goes to the log file', function () { config()->set('mail.default', 'log'); expect(deliveryCheck('delivery.mailer_not_log')->satisfied)->toBeFalse(); }); /** * Fix-Runde (Befund 1): `!== 'log'` allein ist zu eng. MailboxTransport:: * NON_DELIVERING kennt bereits die vollständige Liste — 'array' (der * MAIL_MAILER, den phpunit.xml der GANZEN Suite aufzwingt) und der * unkonfigurierte Fall (null) liefern genauso wenig zu wie 'log'. Eine * Prüfung, die nur 'log' kennt, war unter dem eigenen Testlauf grün, obwohl * hier nie eine Mail hinausginge — genau das Grün-aus-falschem-Grund, gegen * das diese Seite gebaut ist. Jeder Wert der Liste wird hier durchgegangen, * nicht nur der eine, den der ursprüngliche Vorfall zeigte. */ it('does not accept any value MailboxTransport itself treats as non-delivering', function (?string $default) { config()->set('mail.default', $default); expect(deliveryCheck('delivery.mailer_not_log')->satisfied)->toBeFalse(); })->with([ 'log' => ['log'], 'array (the suite\'s own MAIL_MAILER)' => ['array'], 'unset' => [null], ]); it('accepts a real mailer', function () { config()->set('mail.default', 'smtp'); expect(deliveryCheck('delivery.mailer_not_log')->satisfied)->toBeTrue(); }); it('needs at least one mailbox to send from', function () { // Eine Migration seedet fünf Mailboxen (no-reply, support, billing, // office, info) für jede Installation — auch für diese Suite. Auf den // leeren Zustand zurückgesetzt, den dieser Test eigentlich prüft (siehe // clearMailboxSeed() in Pest.php). clearMailboxSeed(); // CompleteProvisioning verschickt CloudReady SYNCHRON und wirft, wenn // MailboxResolver keine Mailbox findet — der letzte Schritt der // Bereitstellung scheitert dann, nachdem die Maschine schon läuft und der // Kunde schon bezahlt hat. expect(deliveryCheck('delivery.mailbox')->satisfied)->toBeFalse(); Mailbox::factory()->create(); expect(deliveryCheck('delivery.mailbox')->satisfied)->toBeTrue(); }); it('treats missing reply templates as a warning, never as a blocker', function () { // Eine Migration seedet einen Grundstock an Antwortvorlagen für jede // Installation — auch für diese Suite. Geleert, um den leeren Zustand zu // prüfen, den ein frisches Setup ohne diese Migration tatsächlich hätte. MailTemplate::query()->delete(); expect(deliveryCheck('delivery.mail_templates')->satisfied)->toBeFalse(); expect(deliveryCheck('delivery.mail_templates')->severity)->toBe(Check::SEVERITY_WARNING); MailTemplate::query()->create([ 'name' => 'Test Template', 'subject' => 'Re: your question', 'body' => 'Thanks for reaching out.', 'sort' => 1, 'active' => true, ]); expect(deliveryCheck('delivery.mail_templates')->satisfied)->toBeTrue(); }); it('treats a missing inbound mail password as a warning, never as a blocker', function () { OperatingMode::set(OperatingMode::Live); expect(deliveryCheck('delivery.inbound_mail_password')->satisfied)->toBeFalse(); expect(deliveryCheck('delivery.inbound_mail_password')->severity)->toBe(Check::SEVERITY_WARNING); app(SecretVault::class)->put('inbound_mail.password', 'secret', Operator::factory()->create(), OperatingMode::Live); expect(deliveryCheck('delivery.inbound_mail_password')->satisfied)->toBeTrue(); }); it('names what breaks for every delivery check, not just what is missing', function () { foreach ([ 'delivery.mailer_not_log', 'delivery.mailbox', 'delivery.mail_templates', 'delivery.inbound_mail_password', ] as $key) { expect(deliveryCheck($key)->breaks)->not->toBe(''); } });