import { afterEach, describe, expect, it } from 'vitest'; import { Shell } from '@/ui/shell'; import { ProjectStore } from '@/app/store'; import { createEmptyProject } from '@/domain/model/factory'; import { ANLAGENART_KURZ, ANLAGENART_LABELS } from '@/domain/rilsa/constants'; import type { Anlagenart } from '@/domain/model/project'; /** * Die Anlagenart in der Statusleiste. * * Die Leiste fuehrt Umlaufzeit, Signalgruppen und Phasen. Ohne die Anlagenart * daneben laesst sich keine dieser Zahlen einordnen: Eine Umlaufzeit von 240 s * ist am Knotenpunkt weit ueber der Sicherheitsgrenze von 120 s, an einer * Arbeitsstelle mit langer Engstelle dagegen zwangslaeufig. Und wer die * Anlagenart versehentlich falsch gesetzt hat, merkt es sonst nirgends im * laufenden Betrieb. */ const FIXED_DATE = new Date('2026-01-01T00:00:00Z'); let laufend: Shell | null = null; afterEach(() => { laufend?.stop(); laufend = null; document.body.replaceChildren(); }); function baueShell(anlagenart: Anlagenart): HTMLElement { const wurzel = document.createElement('div'); document.body.append(wurzel); const store = new ProjectStore(createEmptyProject('Baustelle', FIXED_DATE, anlagenart)); const shell = new Shell(wurzel, store, '5.1.0'); shell.addView({ id: 'test', label: 'Test', group: 'Test', description: 'Nur zum Aufbau der Shell', render: () => () => {}, }); shell.start('test'); laufend = shell; return wurzel; } function leistentext(anlagenart: Anlagenart): string { const leiste = baueShell(anlagenart).querySelector('footer.leiste'); return leiste?.textContent ?? ''; } describe('Anlagenart in der Statusleiste', () => { it('fuehrt die Anlagenart neben Umlaufzeit, Signalgruppen und Phasen', () => { for (const art of ['knotenpunkt', 'fussgaengerschutzanlage', 'einstreifig'] as const) { const text = leistentext(art); expect(text, art).toContain(`Anlagenart: ${ANLAGENART_KURZ[art]}`); expect(text, art).toContain('Umlaufzeit'); laufend?.stop(); laufend = null; document.body.replaceChildren(); } }); it('benennt sie mit derselben Kurzform wie der Ausdruck', () => { // Eine eigene Formulierung fuer den Bildschirm liefe beim naechsten // Wortwechsel gegenueber der Planunterlage auseinander. Die Statusleiste // nimmt die Kurzform, der Ausdruck die lange Beschriftung - beide muessen // mit demselben Wortlaut anfangen, sonst benennt das Programm dieselbe // Anlage auf dem Bildschirm anders als in der Unterlage. for (const art of ['knotenpunkt', 'fussgaengerschutzanlage', 'einstreifig'] as const) { expect(ANLAGENART_LABELS[art], art).toMatch( new RegExp(`^${ANLAGENART_KURZ[art].replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`), ); } }); it('sagt die Anlagenart im Ansageraum mit an', () => { // Die Sprachausgabe liest nur diesen Bereich. Stuende dort allein die // Umlaufzeit, waere die Zahl fuer einen blinden Bearbeiter nicht // einzuordnen. const ansage = baueShell('einstreifig').querySelector('[role="status"]'); expect(ansage?.textContent ?? '').toContain(`Anlagenart ${ANLAGENART_KURZ.einstreifig}`); }); });