Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
/**
* Der Aufbau der Modul-Übersichtsseiten.
*
* Der Styleguide gibt eine Reihenfolge vor – Content Header, KPI-Kacheln,
* Filterleiste, Tabelle – und **eine** Komponentenbibliothek für alles darin.
* Die Abstände kommen von diesen Komponenten; wo eine Seite sie einzeln
* nachjustiert, sieht sie anders aus als die daneben, und niemand merkt es,
* bis jemand beide nebeneinander aufruft.
*
* Geprüft wird deshalb, dass keine Übersichtsseite den Seitenkörper zerlegt
* oder sein Polster überschreibt, und dass die Filterleiste überall denselben
* Abstand zur Tabelle hält.
*/
return static function (): void {
$wurzel = dirname(__DIR__);
/** @return array<string,string> Modulname => Inhalt der Übersichtsseite */
$seiten = static function () use ($wurzel): array {
$alle = [];
foreach ((array)glob($wurzel . '/templates/*/index.php') as $datei) {
$modul = basename(dirname((string)$datei));
$alle[$modul] = (string)file_get_contents((string)$datei);
}
return $alle;
};
test('Es gibt Übersichtsseiten zu prüfen', function () use ($seiten) {
assertTrue(count($seiten()) > 15, 'Es wurden kaum Übersichtsseiten gefunden');
});
test('Eine Seite hat einen Seitenkörper, nicht mehrere', function () use ($seiten) {
// Zwei Körper übereinander ergeben zwischen ihnen das doppelte Polster;
// wer das ausgleicht, setzt es an beiden von Hand – und damit anders
// als jede andere Seite.
foreach ($seiten() as $modul => $inhalt) {
$anzahl = substr_count($inhalt, 'class="page-body');
assertTrue(
$anzahl <= 1,
'Die Übersicht von ' . $modul . ' hat ' . $anzahl . ' Seitenkörper'
);
}
});
test('Der Seitenkörper behält sein Polster', function () use ($seiten) {
foreach ($seiten() as $modul => $inhalt) {
assertFalse(
(bool)preg_match('/class="page-body[^"]*"\s+style="[^"]*padding/', $inhalt),
'Die Übersicht von ' . $modul . ' überschreibt das Polster des Seitenkörpers'
);
}
});
test('Die Filterleiste hält überall denselben Abstand zur Tabelle', function () use ($seiten) {
// `mb-3` ist der Abstand, den die Übersichtsseiten gemeinsam führen.
// Ein kleinerer rückt die Tabelle enger heran als überall sonst.
$engere = ['mb-0', 'mb-1', 'mb-2'];
foreach ($seiten() as $modul => $inhalt) {
if (!preg_match_all('/class="card card-outline card-primary([^"]*)"/', $inhalt, $treffer)) {
continue;
}
foreach ($treffer[1] as $zusatz) {
foreach ($engere as $klasse) {
assertFalse(
(bool)preg_match('/\b' . preg_quote($klasse, '/') . '\b/', $zusatz),
'Die Filterleiste von ' . $modul . ' rückt mit ' . $klasse . ' näher an die Tabelle als die übrigen'
);
}
}
}
});
test('Die Reihenfolge stimmt: erst Kacheln, dann Filter, dann Tabelle', function () use ($seiten) {
foreach ($seiten() as $modul => $inhalt) {
// Gemessen wird im Seitenkörper. Davor kann eine Seite eine eigene
// Karte führen – etwa den Abo-Link eines Kalenders –, die dieselbe
// Polsterung nutzt, aber keine Filterleiste ist.
$koerper = strpos($inhalt, 'class="page-body');
if ($koerper === false) {
continue;
}
$kpi = strpos($inhalt, 'class="kpi-row', $koerper);
$filter = strpos($inhalt, 'class="filter-card-body', $koerper);
$tabs = strpos($inhalt, 'class="table-wrapper', $koerper);
if ($kpi !== false && $filter !== false) {
assertTrue($kpi < $filter, 'Bei ' . $modul . ' steht die Filterleiste vor den Kacheln');
}
if ($filter !== false && $tabs !== false) {
assertTrue($filter < $tabs, 'Bei ' . $modul . ' steht die Tabelle vor der Filterleiste');
}
}
});
};