126 lines
4.9 KiB
PHP
126 lines
4.9 KiB
PHP
<?php
|
|
|
|
use App\Models\Operator;
|
|
use App\Support\Navigation;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
/**
|
|
* Die Seitenleiste der Konsole.
|
|
*
|
|
* Sie trug 26 Einträge in drei Gruppen, von denen eine — „Betrieb" — allein
|
|
* zwölf hielt: Maschinen, Geld und Post unter einem Wort, das auf alle drei
|
|
* zutrifft und deshalb keinem hilft. Neu geordnet in sechs Gruppen.
|
|
*
|
|
* Was diese Tests festhalten, ist nicht die Ordnung selbst (die darf sich
|
|
* ändern), sondern dass beim Umsortieren nichts verlorengeht und keine leere
|
|
* Überschrift entsteht.
|
|
*/
|
|
|
|
/** @return list<array{0:string,1:string,2:string,3:mixed}> */
|
|
function consoleItems(): array
|
|
{
|
|
return collect(Navigation::console())->flatMap(fn (array $g) => $g['items'])->all();
|
|
}
|
|
|
|
/**
|
|
* Die Gruppen-Überschrift, wie x-shell.nav sie zeichnet.
|
|
*
|
|
* Auf das Element geprüft und nicht auf das blanke Wort: „Post" steckt auch in
|
|
* „Posteingang". Ein Teilstring-Vergleich auf ein kurzes Wort besteht aus
|
|
* Gründen, die mit der Prüfung nichts zu tun haben.
|
|
*/
|
|
function navLabel(string $label): string
|
|
{
|
|
return 'lbl">'.e($label).'</p>';
|
|
}
|
|
|
|
it('verliert beim Umsortieren keinen Eintrag und legt keinen doppelt an', function () {
|
|
$routes = array_column(consoleItems(), 0);
|
|
|
|
// Doppelte wären beim Verschieben von Hand die naheliegende Panne: einmal
|
|
// an der neuen Stelle eingefügt, an der alten vergessen.
|
|
expect($routes)->toHaveCount(count(array_unique($routes)));
|
|
|
|
// Die Zahl steht hier bewusst als Zahl: sinkt sie, ist beim Umsortieren
|
|
// ein Eintrag unter den Tisch gefallen, und genau das sähe niemand.
|
|
expect($routes)->toHaveCount(27);
|
|
});
|
|
|
|
it('führt keinen Eintrag, dessen Route es nicht gibt', function () {
|
|
foreach (consoleItems() as [$route, , $key]) {
|
|
expect(Route::has($route))->toBeTrue("Route {$route} (Eintrag {$key}) existiert nicht.");
|
|
}
|
|
});
|
|
|
|
it('gibt jedem Eintrag eine übersetzte Beschriftung in beiden Sprachen', function () {
|
|
foreach (['de', 'en'] as $locale) {
|
|
app()->setLocale($locale);
|
|
|
|
foreach (consoleItems() as [, , $key]) {
|
|
expect(__('admin.nav.'.$key))->not->toBe('admin.nav.'.$key, "{$key} fehlt in lang/{$locale}/admin.php");
|
|
}
|
|
|
|
foreach (Navigation::console() as $group) {
|
|
if ($group['label'] !== null) {
|
|
expect($group['label'])->not->toStartWith('admin.nav_group.');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it('stellt jede Gruppe unter eine Überschrift — außer der Übersicht', function () {
|
|
$groups = Navigation::console();
|
|
|
|
// Die erste Gruppe trägt allein die Übersicht und braucht keine
|
|
// Überschrift: sie ist die Seite, auf der man landet.
|
|
expect($groups[0]['label'])->toBeNull()
|
|
->and($groups[0]['items'])->toHaveCount(1)
|
|
->and($groups[0]['items'][0][0])->toBe('admin.overview');
|
|
|
|
// Alle weiteren haben eine. Eine namenlose Gruppe mitten in der Leiste
|
|
// wäre wieder der Zustand, aus dem diese Arbeit kommt: sechs schwebende
|
|
// Einträge ohne Zugehörigkeit.
|
|
foreach (array_slice($groups, 1) as $group) {
|
|
expect($group['label'])->not->toBeNull()->and($group['label'])->not->toBe('');
|
|
}
|
|
});
|
|
|
|
it('lässt keine Gruppe so groß werden, dass sie wieder alles verschluckt', function () {
|
|
// „Betrieb" hielt zwölf. Die Grenze ist kein Selbstzweck: ab etwa sieben
|
|
// liest man eine Gruppe nicht mehr auf einen Blick, und dann fängt das
|
|
// Sortieren von vorne an.
|
|
foreach (Navigation::console() as $group) {
|
|
expect(count($group['items']))->toBeLessThanOrEqual(7, "Gruppe „{$group['label']}\" ist auf ".count($group['items']).' Einträge gewachsen.');
|
|
}
|
|
});
|
|
|
|
it('zeigt einem Betreiber ohne Berechtigungen keine leere Überschrift', function () {
|
|
// „Post" besteht ausschließlich aus geschützten Einträgen. Vor dieser
|
|
// Arbeit druckte x-shell.nav die Überschrift bedingungslos — die Gruppe
|
|
// hätte also als Wort ohne Inhalt dagestanden.
|
|
//
|
|
// „Read-only" trägt weder customers.manage noch mail.manage, sieht also
|
|
// keinen einzigen Eintrag dieser Gruppe.
|
|
$this->actingAs(Operator::factory()->role('Read-only')->create(), 'operator');
|
|
|
|
$html = $this->get(route('admin.overview'))->assertOk()->getContent();
|
|
|
|
// Auf das Überschriften-Element geprüft, nicht auf das blanke Wort:
|
|
// „Post" steckt auch in „Posteingang" und „Postausgang", und ein
|
|
// Teilstring-Vergleich hätte hier etwas anderes geprüft als behauptet.
|
|
expect($html)->not->toContain(navLabel(__('admin.nav_group.post')));
|
|
});
|
|
|
|
it('zeigt die Gruppe, sobald der Betreiber einen ihrer Einträge sehen darf', function () {
|
|
// Die Kehrseite: die Überschrift darf nicht aus Vorsicht verschwinden.
|
|
$this->actingAs(admin(), 'operator');
|
|
|
|
$html = $this->get(route('admin.overview'))->assertOk()->getContent();
|
|
|
|
foreach (Navigation::console() as $group) {
|
|
if ($group['label'] !== null) {
|
|
expect($html)->toContain(navLabel($group['label']));
|
|
}
|
|
}
|
|
});
|