Dauerhafte Pruefung: Wanderung und linkToInstanceAdmin() bleiben gleich
Die Gleichheit zwischen der eingefrorenen Wanderungsfassung und der Modellmethode war bisher nur mit einer geloeschten Testdatei belegt - gut fuer heute, nicht fuer morgen. Nach dem Muster von HostTokenKeyMigrationTest laedt der neue Test die echte Wanderungsdatei per require() und haelt sie gegen linkToInstanceAdmin(): einmal die entschluesselte Falle direkt geprueft (nc_username darf nie Chiffretext werden), einmal beide Wege bei derselben Ausgangslage gegeneinander.feat/versandtakt
parent
80974108b1
commit
320e485215
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Customer;
|
||||
use App\Models\Instance;
|
||||
use App\Models\Seat;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* Laedt eine frische Instanz der Wanderung bei jedem Aufruf.
|
||||
*
|
||||
* `require`, nicht `require_once`: PHP wertet den `return new class ...`-
|
||||
* Ausdruck bei jedem Aufruf neu aus, jeder Aufruf bekommt also seine eigene
|
||||
* Instanz.
|
||||
*/
|
||||
function loadSeatNextcloudColumnsMigration(): object
|
||||
{
|
||||
return require database_path('migrations/2026_08_03_180000_add_nextcloud_columns_to_seats.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stellt den Vor-Wanderungs-Zustand nach: RefreshDatabase hat up() schon
|
||||
* einmal auf einer leeren seats-Tabelle laufen lassen, die vier Spalten
|
||||
* stehen also schon. Ein zweiter Schema::table()-Aufruf auf bereits
|
||||
* vorhandene Spalten wuerde scheitern — hier weg damit, Zeilen bleiben.
|
||||
*/
|
||||
function dropSeatNextcloudColumns(): void
|
||||
{
|
||||
Schema::table('seats', fn ($table) => $table->dropColumn(['nc_username', 'nc_state', 'nc_error', 'nc_synced_at']));
|
||||
}
|
||||
|
||||
it('verknuepft einen bestehenden Inhaber-Sitz mit dem entschluesselten Anmeldenamen, nicht mit dem Chiffretext', function () {
|
||||
// Genau die Zusicherung, die die Verschluesselungsfalle aus der
|
||||
// Nachbesserung fuer die Zukunft absichert: nc_admin_ref ist am
|
||||
// Instance-Modell 'encrypted' gecastet. Faellt Crypt::decryptString()
|
||||
// in der Wanderung wieder heraus, landet hier der Chiffretext statt
|
||||
// 'admin' — dieser Test bricht dann, nicht erst eine echte Instanz.
|
||||
$customer = Customer::factory()->create();
|
||||
Instance::factory()->for($customer)->create(['nc_admin_ref' => 'admin', 'status' => 'active']);
|
||||
$sitz = Seat::factory()->for($customer)->create(['role' => 'owner']);
|
||||
|
||||
dropSeatNextcloudColumns();
|
||||
loadSeatNextcloudColumnsMigration()->up();
|
||||
|
||||
$zeile = DB::table('seats')->where('id', $sitz->id)->first();
|
||||
|
||||
expect($zeile->nc_username)->toBe('admin')
|
||||
->and($zeile->nc_state)->toBe('synced');
|
||||
});
|
||||
|
||||
it('kommt bei derselben Ausgangslage zum selben Ergebnis wie Seat::linkToInstanceAdmin()', function () {
|
||||
// Der Preis des Einfrierens: zwei Fassungen derselben Auswahl koennen
|
||||
// auseinanderdriften, ohne dass es jemand merkt. Die Erwartung wird
|
||||
// ueber die Modellmethode eingeholt, BEVOR die Wanderung dieselbe Zeile
|
||||
// ueber ihren eigenen, eingefrorenen Weg anfasst — derselbe Kunde,
|
||||
// dieselbe Instanz, derselbe Sitz, zwei Wege dorthin.
|
||||
//
|
||||
// Verglichen werden nur nc_username/nc_state, nicht der ganze
|
||||
// Datensatz: das rohe update() der Wanderung setzt updated_at nicht,
|
||||
// save() ueber das Modell schon — das ist gewollt (siehe andere
|
||||
// Nachbefuellungen im Bestand) und keine Abweichung, die dieser Test
|
||||
// aufdecken soll.
|
||||
$customer = Customer::factory()->create();
|
||||
Instance::factory()->for($customer)->create(['nc_admin_ref' => 'gleicher-name', 'status' => 'active']);
|
||||
$sitz = Seat::factory()->for($customer)->create(['role' => 'owner']);
|
||||
|
||||
$sitz->linkToInstanceAdmin();
|
||||
$erwarteterUsername = $sitz->nc_username;
|
||||
$erwarteterState = $sitz->nc_state;
|
||||
|
||||
dropSeatNextcloudColumns();
|
||||
loadSeatNextcloudColumnsMigration()->up();
|
||||
|
||||
$zeile = DB::table('seats')->where('id', $sitz->id)->first();
|
||||
|
||||
expect($zeile->nc_username)->toBe($erwarteterUsername)
|
||||
->and($zeile->nc_state)->toBe($erwarteterState);
|
||||
});
|
||||
Loading…
Reference in New Issue