CluPilotCloud/tests/Feature/Mail/InstanceRelaySeedMigrationT...

97 lines
3.8 KiB
PHP

<?php // tests/Feature/Mail/InstanceRelaySeedMigrationTest.php
use App\Models\Instance;
use App\Models\Mailbox;
use App\Services\Mail\GuestMailConfig;
use App\Support\Settings;
/**
* Lädt bei jedem Aufruf eine frische Instanz der anonymen Klasse — `require`,
* nicht `require_once`, aus demselben Grund wie in MailboxSeedMigrationTest:
* PHP wertet den `return new class …`-Ausdruck jedes Mal neu aus, und nur so
* lässt sich up() gegen eine Datenbank fahren, die RefreshDatabase längst
* einmal migriert hat.
*/
function loadInstanceRelaySeedMigration(): object
{
return require database_path('migrations/2026_08_03_190000_ein_versandkonto_fuer_die_kundeninstanzen.php');
}
it('legt das gemeinsame Versandkonto der Kundeninstanzen an', function () {
// Ohne diesen Datensatz käme der Betreiber ohne Tinker gar nicht an den
// Start: GuestMailConfig sucht genau diesen Schlüssel, und die Konsole
// kann Postfächer nur bearbeiten, nicht erstellen.
$box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);
expect($box)->not->toBeNull()
->and($box->address)->toBe('noreply@clupilot.cloud');
});
it('legt es inaktiv und ohne Zugangsdaten an', function () {
// Ein Postfach, das ohne Zutun des Betreibers als einsatzbereit dastünde,
// wäre das nächste stille Versprechen: ConfigureInstanceMail schriebe
// dann Werte in die Kunden-Nextcloud, die niemand je eingetragen hat.
$box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);
expect($box->active)->toBeFalse()
->and($box->getRawOriginal('password'))->toBeNull()
->and($box->isConfigured())->toBeFalse();
});
it('hält GuestMailConfig davon ab, halb eingetragene Werte zu liefern', function () {
// Die Probe aufs Exempel: solange niemand das Postfach ausgefüllt hat,
// muss `no_mailbox` herauskommen — auch jetzt, wo es die Zeile GIBT.
Settings::set('mail.host', 'mail.clupilot.cloud');
Settings::set('mail.port', 587);
$config = GuestMailConfig::for(Instance::factory()->create());
expect($config->available())->toBeFalse()
->and($config->problem())->toBe('no_mailbox');
});
it('ist zweimal zu laufen unbedenklich', function () {
// `firstOrNew`, nicht `new Mailbox`: eine Wanderung, die auf halbem Weg
// scheitert, steht nicht in der migrations-Tabelle — der zweite Lauf muss
// die Zeile aktualisieren, nicht an der Eindeutigkeit des Schlüssels
// abprallen.
$threw = null;
try {
loadInstanceRelaySeedMigration()->up();
} catch (Throwable $e) {
$threw = $e;
}
expect($threw)->toBeNull()
->and(Mailbox::query()->where('key', GuestMailConfig::RELAY_KEY)->count())->toBe(1);
});
it('lässt ein bereits ausgefülltes Postfach beim zweiten Lauf in Ruhe', function () {
// Der Fall, der wirklich weh täte: der Betreiber hat Adresse und Passwort
// eingetragen und das Konto scharfgeschaltet, dann läuft die Wanderung
// aus irgendeinem Grund erneut. Sie darf ihm den Versand nicht wieder
// abschalten.
Mailbox::findByKey(GuestMailConfig::RELAY_KEY)->update([
'address' => 'versand@kunde.example',
'password' => 'geheim',
'active' => true,
]);
loadInstanceRelaySeedMigration()->up();
$box = Mailbox::findByKey(GuestMailConfig::RELAY_KEY);
expect($box->address)->toBe('versand@kunde.example')
->and($box->active)->toBeTrue()
->and($box->password)->toBe('geheim');
});
it('nimmt beim Zurücknehmen nur das eigene Postfach mit', function () {
loadInstanceRelaySeedMigration()->down();
expect(Mailbox::findByKey(GuestMailConfig::RELAY_KEY))->toBeNull()
// Die fünf Postfächer der früheren Wanderung gehören ihr, nicht
// dieser hier.
->and(Mailbox::findByKey('no-reply'))->not->toBeNull();
});