import { afterEach, describe, expect, it } from 'vitest'; import { numberCell } from '@/ui/inputs'; /** * Befund 66 zur Fassung 5.8.0. * * Die beiden Rueckfallwege von `numberCell` setzen den vorherigen Wert wieder * in das Feld und sagen in der Meldung, welcher Wert das war. Beide bildeten * diesen Satz aus `String(value)` - dieselbe Zeichenkette, die in das * `input[type=number]` zurueckgeschrieben wird und dort den englischen * Dezimalpunkt braucht. In der Meldung ist der Punkt falsch: Sie ist die * einzige Rueckmeldung auf die abgelehnte Eingabe, und eine Sprachausgabe * liest den Punkt als Satzende - "zwoelf Punkt fuenf" statt "zwoelf Komma * fuenf". Dieselbe Datei begruendet das acht Zeilen vorher im Bereichshinweis * ausdruecklich, und `mitEinheit()` in derselben Funktion formatiert bereits * ueber `fmt.numShort`. */ afterEach(() => { document.body.replaceChildren(); }); function letzteWarnung(): string { const meldungen = [...document.querySelectorAll('.meldung-warnung')]; return meldungen[meldungen.length - 1]?.textContent ?? ''; } describe('Zahlenfeld: die Wiederherstellungsmeldung nennt den Wert in deutscher Schreibweise (Befund 66)', () => { it('meldet beim geleerten Pflichtfeld "12,5" statt "12.5"', () => { // Zwischenzeitfenster, Feld "Räumweg": aus dem Lageplan abgeleitete Wege // haben zwei Nachkommastellen, und die Schrittweite 0,1 erzeugt sie auch // ueber die Pfeiltasten. let gemeldet: number | null = -1; const feld = numberCell( 12.5, (wert) => { gemeldet = wert; }, { min: 0, max: 100, step: 0.1, einheit: 'm' }, ); feld.setAttribute('aria-label', 'Räumweg'); document.body.append(feld); feld.value = ''; feld.dispatchEvent(new Event('change')); const meldung = letzteWarnung(); expect(meldung).toContain('Der vorherige Wert 12,5 wurde wiederhergestellt'); // Kein englischer Dezimalpunkt im vorgelesenen Satz. expect(meldung).not.toMatch(/\d\.\d/); // Das Feld selbst behaelt den Punkt: `input[type=number]` nimmt nur ihn an. expect(feld.value, 'vorheriger Wert steht wieder im Feld').toBe('12.5'); expect(gemeldet, 'ein abgelehnter Wert darf nicht weitergereicht werden').toBe(-1); }); it('meldet bei unlesbarer Eingabe "0,75" statt "0.75"', () => { /* * Der zweite Rueckfallweg. Ein `input[type=number]` gibt eine unlesbare * Eingabe als leere Zeichenkette heraus - jsdom wie der Browser. Um genau * diesen Zweig zu erreichen, wird der Feldtyp fuer die Eingabe kurz auf * `text` gestellt; der Empfaenger liest nur `input.value` und sieht davon * nichts. */ const feld = numberCell(0.75, () => {}, { min: 0, max: 1, step: 0.05 }); feld.setAttribute('aria-label', 'Lastzuganteil'); document.body.append(feld); feld.setAttribute('type', 'text'); feld.value = '12,5,3'; feld.dispatchEvent(new Event('change')); const meldung = letzteWarnung(); expect(meldung).toContain('Der vorherige Wert 0,75 gilt weiter'); expect(meldung).not.toMatch(/\d\.\d/); }); it('laesst die Wertangabe weg, wenn es gar keinen vorherigen Wert gab', () => { // Gegenprobe: Bei `null` bleibt das Feld leer, und der Satz nennt keine // Zahl - die Kennzeichnung als offene Pflichtangabe bleibt richtig. const feld = numberCell(null, () => {}, { min: 0, max: 100 }); document.body.append(feld); feld.value = ''; feld.dispatchEvent(new Event('change')); expect(feld.value).toBe(''); expect(feld.getAttribute('aria-invalid')).toBe('true'); const meldung = letzteWarnung(); expect(meldung).toContain('Das Feld darf nicht leer bleiben'); expect(meldung, 'ohne vorherigen Wert steht keine Zahl im Satz').not.toMatch(/\d/); }); });