lsa-planer
LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.
/ tests ui textfeldLaenge.test.ts
| 1 | import { afterEach, describe, expect, it } from 'vitest'; |
| 2 | import { beschrifteTabelle, el } from '@/ui/dom'; |
| 3 | import { MAX_TEXTFELD_ZEICHEN, textCell } from '@/ui/inputs'; |
| 4 | |
| 5 | /** |
| 6 | * Laengengrenze der kompakten Textfelder, Befunde zur Fassung 5.10.0. |
| 7 | * |
| 8 | * BEFUND 40: Kein Eingabefeld trug eine Laengenbegrenzung - "maxlength" kam in |
| 9 | * src/ nicht vor. Eine in das Feld "Bezeichnung" einer Signalgruppe eingefuegte |
| 10 | * lange Zeichenkette ging ungekuerzt in das Zuordnungsbanner ueber der |
| 11 | * Zwischenzeitenmatrix; ab rund 7 000 Zeichen laeuft jspdf-autotable dort in |
| 12 | * `printFullRow` in eine Endlosteilung, und die Ausgabe bricht mit "Maximum |
| 13 | * call stack size exceeded" ab. Es entsteht dann ueberhaupt keine |
| 14 | * Planunterlage. Die Schranke in `matrixSatz` (src/services/export/pdf.ts) |
| 15 | * verschmaelert den Ausschnitt nur bis auf eine Spalte und ist dann erschoepft. |
| 16 | * |
| 17 | * Die Bezeichnung ist eine Plankennzeichnung ("Bezeichnung im Plan, z. B. K1, |
| 18 | * F2, R3"), keine Beschreibung. Sie wird beim Eintragen begrenzt und die |
| 19 | * Kuerzung gemeldet - wie `ganzzahlAbrunden` es bei den Zahlenfeldern vormacht. |
| 20 | */ |
| 21 | |
| 22 | afterEach(() => { |
| 23 | document.body.replaceChildren(); |
| 24 | }); |
| 25 | |
| 26 | function meldungen(): string[] { |
| 27 | return [...document.querySelectorAll('.meldung-warnung')].map((m) => m.textContent ?? ''); |
| 28 | } |
| 29 | |
| 30 | function tippe(feld: HTMLInputElement, text: string): void { |
| 31 | feld.value = text; |
| 32 | feld.dispatchEvent(new Event('change')); |
| 33 | } |
| 34 | |
| 35 | describe('Textfelder: Bezeichnungen sind in der Länge begrenzt (Befund 40)', () => { |
| 36 | it('trägt die Grenze als maxlength am Feld', () => { |
| 37 | const feld = textCell('K1', () => {}); |
| 38 | expect(feld.getAttribute('maxlength')).toBe(String(MAX_TEXTFELD_ZEICHEN)); |
| 39 | }); |
| 40 | |
| 41 | it('kürzt eine zu lange Eingabe und meldet die Kürzung', () => { |
| 42 | const angekommen: string[] = []; |
| 43 | // Ohne Optionen - genau so, wie die acht Aufrufstellen der Anwendung |
| 44 | // `textCell` benutzen (signalGroupsView, phasesView, projectView, |
| 45 | // lageplanView; settingsView nur mit `placeholder`). |
| 46 | const feld = textCell('K1', (wert) => angekommen.push(wert)); |
| 47 | document.body.append(feld); |
| 48 | |
| 49 | tippe(feld, 'A'.repeat(10_000)); |
| 50 | |
| 51 | expect(angekommen).toHaveLength(1); |
| 52 | expect(angekommen[0]).toHaveLength(MAX_TEXTFELD_ZEICHEN); |
| 53 | // Auch im Feld steht danach, was uebernommen wurde - sonst zeigte die |
| 54 | // Zelle einen Text, mit dem niemand mehr rechnet. |
| 55 | expect(feld.value).toHaveLength(MAX_TEXTFELD_ZEICHEN); |
| 56 | const gemeldet = meldungen(); |
| 57 | expect(gemeldet).toHaveLength(1); |
| 58 | expect(gemeldet[0]).toContain(String(MAX_TEXTFELD_ZEICHEN)); |
| 59 | }); |
| 60 | |
| 61 | it('nennt in der Meldung die Spalte und die Zeile der Tabellenzelle', () => { |
| 62 | /* |
| 63 | * NACHTRAG (Fassung 5.11.0). Die Meldung bildete den Feldnamen aus den |
| 64 | * OPTIONEN (`beschriftung ?? title ?? 'Der Text'`) - und kein einziger |
| 65 | * `textCell`-Aufruf der Anwendung uebergibt eines von beiden. In der |
| 66 | * Signalgruppentabelle mit ihren neunzehn Spalten und bis zu sechzehn |
| 67 | * Zeilen hiess die Warnung deshalb immer nur "Der Text: ...", und welche |
| 68 | * Bezeichnung gekuerzt wurde, stand nirgends. |
| 69 | * |
| 70 | * Den Namen bekommt das Feld erst beim Einhaengen, aus Spaltenkopf und |
| 71 | * Zeilenname (`beschrifteTabelle` -> `benenneBedienelemente`, ui/dom.ts). |
| 72 | * Genau dort liest ihn `numberCell` seit jeher - mit derselben Begruendung |
| 73 | * ("bei einer Tabelle mit sechzehn Spalten waere unklar, welche"). |
| 74 | */ |
| 75 | const feld = textCell('K1', () => {}); |
| 76 | const tabelle = el( |
| 77 | 'table', |
| 78 | {}, |
| 79 | el('thead', {}, el('tr', {}, el('th', { text: 'Bezeichnung' }))), |
| 80 | el('tbody', {}, el('tr', {}, el('td', {}, feld))), |
| 81 | ); |
| 82 | document.body.append(tabelle); |
| 83 | beschrifteTabelle(tabelle, { beschriftung: 'Signalgruppen' }); |
| 84 | expect(feld.getAttribute('aria-label'), 'Vorbedingung: die Tabelle benennt das Feld').toBe( |
| 85 | 'Bezeichnung, K1', |
| 86 | ); |
| 87 | |
| 88 | tippe(feld, 'A'.repeat(10_000)); |
| 89 | |
| 90 | const gemeldet = meldungen(); |
| 91 | expect(gemeldet).toHaveLength(1); |
| 92 | expect(gemeldet[0], 'die Meldung nennt das gekürzte Feld nicht').toContain('Bezeichnung, K1'); |
| 93 | }); |
| 94 | |
| 95 | it('lässt einen Text bis zur Grenze unverändert und meldet nichts', () => { |
| 96 | const angekommen: string[] = []; |
| 97 | const feld = textCell('', (wert) => angekommen.push(wert)); |
| 98 | document.body.append(feld); |
| 99 | |
| 100 | const gerade_noch = 'B'.repeat(MAX_TEXTFELD_ZEICHEN); |
| 101 | tippe(feld, gerade_noch); |
| 102 | |
| 103 | expect(angekommen).toEqual([gerade_noch]); |
| 104 | expect(meldungen()).toHaveLength(0); |
| 105 | }); |
| 106 | |
| 107 | it('zählt die Länge nach dem Abschneiden der Leerzeichen', () => { |
| 108 | const angekommen: string[] = []; |
| 109 | const feld = textCell('', (wert) => angekommen.push(wert)); |
| 110 | document.body.append(feld); |
| 111 | |
| 112 | tippe(feld, ` ${'C'.repeat(MAX_TEXTFELD_ZEICHEN)} `); |
| 113 | |
| 114 | expect(angekommen).toEqual(['C'.repeat(MAX_TEXTFELD_ZEICHEN)]); |
| 115 | expect(meldungen()).toHaveLength(0); |
| 116 | }); |
| 117 | |
| 118 | it('bleibt weit unter der Länge, an der die Zwischenzeitenmatrix im PDF abbricht', () => { |
| 119 | // Gemessen wurde: 6 000 Zeichen laufen durch, ab rund 7 000 bricht die |
| 120 | // Ausgabe ab. Der bestehende Test tests/export/pdfZwischenzeitenmatrix.test.ts |
| 121 | // haelt fest, dass zwoelf Gruppen mit 260 Zeichen langen Namen einen |
| 122 | // Ausdruck ergeben - die Grenze bleibt darunter. |
| 123 | expect(MAX_TEXTFELD_ZEICHEN).toBeLessThanOrEqual(260); |
| 124 | }); |
| 125 | }); |