'), 'Ohne Cookie steht die Leiste offen');
$this->assert(str_contains($offen, 'aria-expanded="true"'), 'Der Schalter meldet die offene Leiste');
$this->assert(str_contains($offen, 'title="Seitenleiste einklappen"'), 'Und lädt zum Einklappen ein');
$eingeklappt = $this->rendere('/', 'eingeklappt');
$this->assert(
str_contains($eingeklappt, '
'),
'Mit Cookie rendert der Server die schmale Leiste sofort'
);
$this->assert(str_contains($eingeklappt, 'aria-expanded="false"'), 'Der Schalter meldet die schmale Leiste');
$this->assert(
str_contains($eingeklappt, 'title="Seitenleiste ausklappen"'),
'Und lädt zum Ausklappen ein'
);
$unsinn = $this->rendere('/', 'irgendwas');
$this->assert(
str_contains($unsinn, '
'),
'Ein fremder Cookie-Wert lässt die Leiste offen'
);
}
private function stilblattSchiebtNurDieBeschriftungenWeg(): void
{
$stil = $this->stilblatt();
$this->assert(
(bool)preg_match('#\.rahmen\.eingeklappt\s*\{[^}]*grid-template-columns:\s*64px 1fr#', $stil),
'Eingeklappt bleibt nur eine Symbolspalte stehen'
);
$this->assert(
(bool)preg_match('#\.rahmen\s*\{[^}]*grid-template-columns:\s*232px 1fr#', $stil),
'Offen behält die Leiste ihre ursprüngliche Breite'
);
// display:none nähme den Verweisen ihren Namen – deshalb wird die
// Beschriftung nur aus dem Bild geschoben.
$this->assert(
(bool)preg_match(
'#\.rahmen\.eingeklappt \.marken-text,\s*\.rahmen\.eingeklappt \.beschriftung\s*\{[^}]*clip-path:\s*inset\(50%\)#',
$stil
),
'Die Beschriftungen verschwinden aus dem Bild, nicht aus dem Baum'
);
$this->assert(
!preg_match('#\.rahmen\.eingeklappt \.marken-symbol[^{]*\{[^}]*display:\s*none#', $stil),
'Das Markensymbol bleibt eingeklappt sichtbar'
);
$this->assert(
(bool)preg_match('#\.seitenleisten-marke\s*\{[^}]*cursor:\s*pointer#', $stil),
'Die Marke zeigt sich als anklickbar'
);
$this->assert(
(bool)preg_match('#\.marken-text span\s*\{\s*color:\s*var\(--navi-marke\)#', $stil),
'Die zweite Worthälfte trägt die Akzentfarbe'
);
$this->assert(
(bool)preg_match('#--navi-marke:\s*#', $stil),
'Die Akzentfarbe steht als Custom Property'
);
// In schmalen Fenstern liegt die Navigation waagerecht - dort gibt es
// nichts einzusparen.
$schmal = substr($stil, (int)strpos($stil, '@media (max-width: 820px)'));
$this->assert(
(bool)preg_match('#\.rahmen,\s*\.rahmen\.eingeklappt\s*\{\s*grid-template-columns:\s*1fr#', $schmal),
'Im schmalen Fenster spielt das Einklappen keine Rolle'
);
$this->assert(
(bool)preg_match('#\.rahmen\.eingeklappt \.beschriftung\s*\{[^}]*clip-path:\s*none#', $schmal),
'Und die Beschriftungen bleiben dort lesbar'
);
}
private function skriptMerktSichDenZustand(): void
{
$skript = (string)file_get_contents(dirname(__DIR__) . '/public/static/app.js');
$this->assert(
str_contains($skript, "querySelector('[data-seitenleiste-schalter]')"),
'Das Skript findet den Schalter'
);
$this->assert(
str_contains($skript, "rahmen.classList.toggle('eingeklappt')"),
'Ein Klick klappt die Leiste um'
);
$this->assert(
(bool)preg_match("#document\.cookie = 'seitenleiste='#", $skript),
'Der Zustand landet im Cookie, damit der Server ihn kennt'
);
$this->assert(
str_contains($skript, 'samesite=lax'),
'Das Cookie reist nicht zu fremden Seiten mit'
);
$this->assert(
str_contains($skript, "schalter.setAttribute('aria-expanded'"),
'Der Schalter meldet den neuen Zustand'
);
}
private function stilblatt(): string
{
return (string)file_get_contents(dirname(__DIR__) . '/public/static/app.css');
}
private function rendere(string $pfad, ?string $cookie = null): string
{
$vorher = $_COOKIE['seitenleiste'] ?? null;
if ($cookie === null) {
unset($_COOKIE['seitenleiste']);
} else {
$_COOKIE['seitenleiste'] = $cookie;
}
$titel = 'Test';
$flash = [];
$benutzer = null;
$csrfToken = 'x';
$aktuellerPfad = $pfad;
ob_start();
include dirname(__DIR__) . '/src/Views/layout/kopf.php';
$html = (string)ob_get_clean();
if ($vorher === null) {
unset($_COOKIE['seitenleiste']);
} else {
$_COOKIE['seitenleiste'] = $vorher;
}
return $html;
}
/** Nur die Seitenleiste – Verweise im Inhalt sollen nicht mitzählen. */
private function seitenleiste(string $html): string
{
$anfang = (int)strpos($html, '');
return substr($html, $anfang, $ende - $anfang);
}
}