CluPilotCloud/tests/Feature/Admin/RoleManagementTest.php

149 lines
5.5 KiB
PHP

<?php
use App\Livewire\Admin\Roles;
use App\Models\Operator;
use Livewire\Livewire;
use Spatie\Permission\Models\Role;
/**
* Rollen und ihre Rechte waren fest im Code. Zuweisbar war in der Konsole nur
* die Rolle selbst — was sie DARF, stand in Migrationen.
*
* Beim Nachsehen fiel zweierlei auf, und beides ist der Grund, warum die Liste
* jetzt aus der Datenbank kommt statt aus einer Konstanten:
*
* - `Developer` existiert als Rolle, wurde vom Einladen-Formular aber nie
* angeboten: die zulässigen Namen standen an DREI Stellen (zwei
* Validierungsregeln plus Operator::OPERATOR_ROLES), und eine davon war
* nicht mitgezogen worden.
* - `dpa.manage` lag zusätzlich auf dem `web`-Guard, wo kein Betreiber je
* hinsieht — eine Migration hatte den Guard verwechselt.
*/
it('offers every role that actually exists, not a list written down elsewhere', function () {
Role::findOrCreate('Buchhaltung', 'operator');
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->assertSee('Buchhaltung')
->assertSee('Developer');
});
it('lets the owner give a role a capability', function () {
$role = Role::findOrCreate('Buchhaltung', 'operator');
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->set("granted.{$role->id}", ['console.view', 'billing.manage'])
->call('save', $role->id)
->assertHasNoErrors();
expect($role->fresh()->permissions->pluck('name')->sort()->values()->all())
->toBe(['billing.manage', 'console.view']);
});
it('takes a capability away again', function () {
$role = Role::findOrCreate('Buchhaltung', 'operator');
$role->givePermissionTo('billing.manage', 'console.view');
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->set("granted.{$role->id}", ['console.view'])
->call('save', $role->id);
expect($role->fresh()->permissions->pluck('name')->all())->toBe(['console.view']);
});
it('refuses to let Owner be stripped', function () {
// Sonst sperrt sich der Betreiber mit einem Klick selbst aus, und es gibt
// niemanden mehr, der es zurücknehmen könnte. Die einzige Rolle, die
// dieser Bildschirm nicht anfassen darf.
$owner = Role::where('name', 'Owner')->where('guard_name', 'operator')->firstOrFail();
$vorher = $owner->permissions->pluck('name')->sort()->values()->all();
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->set("granted.{$owner->id}", ['console.view'])
->call('save', $owner->id)
->assertHasErrors();
expect($owner->fresh()->permissions->pluck('name')->sort()->values()->all())->toBe($vorher);
});
it('creates a role', function () {
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->set('newRole', 'Buchhaltung')
->call('create')
->assertHasNoErrors();
expect(Role::where('name', 'Buchhaltung')->where('guard_name', 'operator')->exists())->toBeTrue();
});
it('never creates a role on the wrong guard', function () {
// Genau der Fehler, der `dpa.manage` auf dem web-Guard hinterlassen hat:
// ein Eintrag, den kein Betreiber je sieht, weil Operator gegen
// `operator` auflöst.
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->set('newRole', 'Buchhaltung')
->call('create');
expect(Role::where('name', 'Buchhaltung')->where('guard_name', 'web')->exists())->toBeFalse();
});
it('will not delete a role somebody still holds', function () {
$role = Role::findOrCreate('Buchhaltung', 'operator');
Operator::factory()->create()->assignRole($role);
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->call('delete', $role->id)
->assertHasErrors();
expect(Role::where('name', 'Buchhaltung')->exists())->toBeTrue();
});
it('deletes a role nobody holds', function () {
$role = Role::findOrCreate('Buchhaltung', 'operator');
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->call('delete', $role->id)
->assertHasNoErrors();
expect(Role::where('name', 'Buchhaltung')->exists())->toBeFalse();
});
it('is not reachable without staff.manage', function () {
// Wer bestimmen darf, was eine Rolle kann, bestimmt alles andere gleich
// mit. Dasselbe Recht wie das Einladen von Mitarbeitern.
Livewire::actingAs(operator('Admin'), 'operator')
->test(Roles::class)
->assertForbidden();
});
it('keeps counting capabilities correctly past the first role', function () {
// Ein Fehler, den ich beim Umbau selbst gebaut habe: die Ansicht nannte
// die Zählvariable `$granted` — genauso wie die Eigenschaft des Bauteils.
// Ab der zweiten Rolle war sie eine Zahl statt der Liste, und die Seite
// starb an `count(int)`. Mit einer Rolle wäre es nie aufgefallen.
Role::findOrCreate('Buchhaltung', 'operator')->givePermissionTo('console.view');
Role::findOrCreate('Werkstatt', 'operator');
Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->assertOk()
->assertSee('Buchhaltung')
->assertSee('Werkstatt');
});
it('groups the capabilities instead of listing twenty-one in a row', function () {
$groups = Livewire::actingAs(operator('Owner'), 'operator')
->test(Roles::class)
->viewData('groups');
expect($groups)->toHaveKey('billing')
->and($groups)->toHaveKey('provisioning')
->and(count($groups))->toBeLessThan(21);
});