import { afterEach, describe, expect, it } from 'vitest'; import { ProjectStore } from '@/app/store'; import * as actions from '@/app/actions'; import { createConflict, createEmptyProject } from '@/domain/model/factory'; import type { Project } from '@/domain/model/project'; import type { ViewContext } from '@/ui/shell'; import { compatibilityView, zaehleFeindlichePaare } from '@/ui/views/compatibilityView'; /** * Befund 74 zur Fassung 5.10.0. * * `zaehleFeindlichePaare` bildete den ungerichteten Paarschluessel als * `[fromId, toId].sort().join('|')`. Fuer die Kennungen "a|b", "c", "a" und * "b|c" ergibt das zweimal denselben Schluessel "a|b|c": Zwei verschiedene * Paare fallen zusammen, und die Zahl ist zu klein. * * Sie steht an zwei sichtbaren Stellen - in der Ueberschrift der Ansicht und * in der Rueckfrage vor "Alle aufheben", die sagt, wie viele Konflikte * entfernt werden. Beide widersprechen dann der Matrix daneben. * * Dieselbe Bauart hat Befund 61 (Fassung 5.9.0) in `signalPlan.ts` und in * `parseConflicts` bereits beseitigt; eine Signalgruppenkennung kommt * ungeprueft aus der Projektdatei - `parseSignalGroups` beanstandet nur leere * und doppelt vergebene Kennungen, kein Zeichenrepertoire. */ const FESTES_DATUM = new Date('2026-01-01T00:00:00Z'); afterEach(() => { document.body.replaceChildren(); }); /** * Vier Signalgruppen mit Kennungen, die den verbindenden Strich enthalten, und * zwei feindliche Paare: "a|b" gegen "c" und "a" gegen "b|c". */ function projektMitTrennzeichen(): Project { const leer = createEmptyProject('Kennungen', FESTES_DATUM); let projekt = leer; for (let i = 0; i < 4; i += 1) projekt = actions.addSignalGroup(projekt, 'kfz'); const kennungen = ['a|b', 'c', 'a', 'b|c']; const signalGroups = projekt.signalGroups.map((g, i) => ({ ...g, id: kennungen[i]! })); return { ...projekt, signalGroups, conflicts: [ createConflict('a|b', 'c'), createConflict('c', 'a|b'), createConflict('a', 'b|c'), createConflict('b|c', 'a'), ], }; } describe('Befund 74 - Zaehlung der feindlichen Paare bleibt bei "|" in der Kennung eindeutig', () => { it('zaehlt zwei Paare, die denselben zusammengeklebten Schluessel ergaeben', () => { // ['a|b','c'].sort().join('|') === 'a|b|c' === ['a','b|c'].sort().join('|') expect(zaehleFeindlichePaare(projektMitTrennzeichen())).toBe(2); }); it('zaehlt gewoehnliche Kennungen unveraendert', () => { let projekt = createEmptyProject('Regelfall', FESTES_DATUM); projekt = actions.addSignalGroup(actions.addSignalGroup(projekt, 'kfz'), 'kfz'); const [a, b] = projekt.signalGroups; expect(zaehleFeindlichePaare(projekt)).toBe(0); projekt = actions.toggleConflictPair(projekt, a!.id, b!.id); expect(zaehleFeindlichePaare(projekt)).toBe(1); }); it('nennt in der Ueberschrift dieselbe Zahl, die die Matrix zeigt', () => { const wurzel = document.createElement('div'); document.body.append(wurzel); const context: ViewContext = { store: new ProjectStore(projektMitTrennzeichen()), refresh: () => {}, navigate: () => {}, target: null, }; const abmelden = compatibilityView.render(wurzel, context); try { const feindlicheZellen = [...wurzel.querySelectorAll('button')].filter((b) => (b.textContent ?? '').trim().startsWith('feindlich'), ); expect(feindlicheZellen).toHaveLength(2); const titel = [...wurzel.querySelectorAll('.abschnitt-titel')] .map((t) => t.textContent ?? '') .find((t) => t.includes('feindlich')); expect(titel, 'Keine Überschrift zur Matrix').toBeDefined(); expect(titel, 'Die Überschrift widerspricht der Matrix daneben').toContain('2 von'); } finally { abmelden(); wurzel.remove(); } }); });