Kundenansicht neu (Aufträge): Zeitleiste barrierefrei, "mehr anzeigen" mit Auftragstitel im Namen und aria-controls, "Im Chat antworten" bricht nicht um
Der Knopf "mehr anzeigen"/"weniger anzeigen" bekommt einen aria-label mit dem Auftragstitel (der sichtbare Text steht vorn im Namen, der Titel nur als Text) und aria-controls auf die Liste seines Auftrags (eindeutige Id je Liste); beides zieht beim Umschalten mit. Der Linktext "Im Chat antworten" trägt white-space: nowrap und bleibt in einer Zeile beisammen. Tests: DOM-Test für Name, Verknüpfung, Umschalten, fremden Titel und Ersatztitel; CSS-Test für nowrap. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
14dc2ad1bf
commit
ace4c85e72
3 files changed
+55
-8
No files matched your search
@@ -99,6 +99,37 @@ test('Aktivität: Zeitleiste mit Datum und Kurztext, drei sichtbar, „mehr anze
|
||||
assert.equal(fx.alle(el, '[data-mehr]').length, 1)
|
||||
}))
|
||||
|
||||
// Barrierefreiheit: Mehrere Knöpfe „mehr anzeigen“ auf einer Seite sind für Screenreader nicht zu unterscheiden. Der Name nennt darum den Auftrag (und enthält den sichtbaren
|
||||
// Text, WCAG 2.5.3), aria-controls zeigt auf die Liste, die der Knopf aufklappt.
|
||||
test('Zeitleiste: „mehr anzeigen“ trägt aria-label mit dem Auftragstitel und aria-controls auf die eigene Liste, auch nach dem Umschalten', () => mitDom((fx) => {
|
||||
const vier = (nr, titel) => auftrag(nr, 'arbeit', '2026-10-06T10:00:00Z', ['a', 'b', 'c', 'd'].map((t, j) => eintrag(`2026-10-1${j}`, t)), titel)
|
||||
const el = baueAktivitaet([vier(1, 'Speisekarte als PDF'), vier(2, 'Neue Fotos <b>für</b> die Startseite')], JETZT)
|
||||
const [erster, zweiter] = fx.alle(el, '[data-auftrag]')
|
||||
const knopf = (block) => fx.finde(block, '[data-mehr]')
|
||||
const liste = (block) => fx.finde(block, '.kn-az-zeilen')
|
||||
assert.equal(knopf(erster).textContent, 'mehr anzeigen')
|
||||
assert.equal(knopf(erster).getAttribute('aria-label'), 'mehr anzeigen zu „Speisekarte als PDF“')
|
||||
assert.equal(knopf(zweiter).getAttribute('aria-label'), 'mehr anzeigen zu „Neue Fotos <b>für</b> die Startseite“') // nur Text, nie HTML
|
||||
// aria-controls: die Id der Liste desselben Auftrags, eindeutig auf der Seite
|
||||
const ids = [liste(erster).getAttribute('id'), liste(zweiter).getAttribute('id')]
|
||||
assert.ok(ids.every((id) => /^[A-Za-z][\w-]*$/.test(id)) && ids[0] !== ids[1], ids.join())
|
||||
assert.deepEqual([knopf(erster), knopf(zweiter)].map((k) => k.getAttribute('aria-controls')), ids)
|
||||
assert.ok(knopf(erster).getAttribute('aria-label').startsWith(knopf(erster).textContent)) // der sichtbare Text steht im Namen
|
||||
// Umschalten: Text, Zustand und Name ziehen mit, die Verknüpfung bleibt
|
||||
fx.klick(knopf(erster))
|
||||
assert.equal(knopf(erster).textContent, 'weniger anzeigen')
|
||||
assert.equal(knopf(erster).getAttribute('aria-label'), 'weniger anzeigen zu „Speisekarte als PDF“')
|
||||
assert.equal(knopf(erster).getAttribute('aria-controls'), ids[0])
|
||||
assert.equal(knopf(zweiter).getAttribute('aria-label'), 'mehr anzeigen zu „Neue Fotos <b>für</b> die Startseite“') // der andere Knopf bleibt
|
||||
fx.klick(knopf(erster))
|
||||
assert.equal(knopf(erster).getAttribute('aria-label'), 'mehr anzeigen zu „Speisekarte als PDF“')
|
||||
// ohne Titel gilt der Ersatztitel der Überschrift; „Ältere Aufträge anzeigen“ bleibt wie es war
|
||||
const ohneTitel = baueAktivitaet([{ ...vier(3, ''), topic: '' }], JETZT)
|
||||
assert.equal(fx.finde(ohneTitel, '[data-mehr]').getAttribute('aria-label'), 'mehr anzeigen zu „Dein Auftrag“')
|
||||
const sechs = baueAktivitaet(Array.from({ length: 6 }, (_, i) => vier(10 + i, `T${i}`)), JETZT)
|
||||
assert.equal(fx.finde(sechs, '[data-aeltere]').getAttribute('aria-label'), null)
|
||||
}))
|
||||
|
||||
test('Aktivität: Auftrag ohne Einträge zeigt einen ruhigen Satz statt einer leeren Zeitleiste', () => mitDom((fx) => {
|
||||
const el = baueAktivitaet([auftrag(1, 'arbeit', '2026-10-05T00:00:00Z', [])], JETZT)
|
||||
assert.equal(fx.finde(el, '.kn-az-zeitleiste'), null); assert.match(fx.text(el), /Noch keine Arbeiten dokumentiert\./)
|
||||
@@ -175,6 +206,13 @@ test('Rückfrage-Link: am Handy ein Block (kein flex) mit Innenabstand für 44 p
|
||||
assert.doesNotMatch(css, /\.kn-az-info a \{[^}]*display: *(inline-)?flex/)
|
||||
})
|
||||
|
||||
// Browserlauf 17.10. (Prüfbefund): „Im Chat antworten“ brach am schmalen Handy mitten im Text um. Der Linktext bleibt zusammen; passt er nicht mehr in die Zeile, wandert er ganz in die nächste.
|
||||
test('Rückfrage-Link: der Linktext „Im Chat antworten“ bricht nicht um (white-space: nowrap auf .kn-az-info-link)', () => {
|
||||
const css = readFileSync(new URL('../public/neu/ansichten.css', import.meta.url), 'utf8')
|
||||
assert.match(css, /\n\.kn-az-info-link \{[^}]*\bwhite-space: nowrap;[^}]*\}/)
|
||||
assert.doesNotMatch(css, /\.kn-az-info a \{[^}]*white-space: nowrap/) // der Satz davor darf umbrechen
|
||||
})
|
||||
|
||||
test('Zeitleiste: trägt ein Eintrag das Jahr (Vorjahr), richten sich alle Datumsspalten des Auftrags danach', () => mitDom((fx) => {
|
||||
const mitJahr = baueAktivitaet([auftrag(1, 'arbeit', '2026-10-05T00:00:00Z', [eintrag('2026-10-06', 'neu'), eintrag('2025-12-24', 'alt')])], JETZT)
|
||||
assert.deepEqual(fx.alle(mitJahr, 'time').map((t) => t.textContent), ['06.10.', '24.12.25']); assert.ok(fx.finde(mitJahr, '.kn-az-zeilen').classList.contains('kn-az-mit-jahr'))
|
||||
|
||||
Reference in new issue
Block a user