Files
tickte-system/tests/unit/workersFocus.test.mjs
T
ClaudeandClaude Sonnet 5.5 7c974ab6db Workers P4 Endprüfung W3: Fokus bleibt nach Pult-Aktionen erhalten statt auf <body> zu fallen
Jede Aktion sperrt die Knöpfe der Zeile; Chromium nimmt einem gesperrten Knopf den Fokus und gibt ihn nicht
zurück, Tastatur- und Screenreader-Nutzer standen danach am Seitenanfang. begin() merkt sich das fokussierte
Bedienelement und das offene Feld; ist die Anfrage vorbei, geht der Fokus zurück an den Knopf, sonst ans
Textfeld, an den Knopf, der das Feld öffnete, sonst an die Zeile (tabIndex -1). Verlässt die Zeile die
Liste, nimmt die Meldung oben (tabIndex -1) den Fokus, auch bei gleichem Text zweimal nacheinander. Es wird
nur eingegriffen, wenn der Fokus wirklich verloren ging und vor der Aktion ein Bedienelement ihn hatte
(Safari fokussiert Knöpfe nicht). Neues Modul workersFocus.js (rein, document wird übergeben).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 23:14:11 +00:00

60 lines
3.5 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { loadModule } from './load.mjs'
// Fokus nach Pult-Aktionen (Endprüfung P4, W3): ein gesperrter Knopf verliert den Fokus an <body>; die Zeile gibt ihn danach zurück,
// aber nur, wenn er wirklich verloren ging. Reine Logik mit einer document-Attrappe, kein DOM nötig.
const { activeControl, focusLost, restoreFocus } = await loadModule('src/lib/workersFocus.js')
function fakeDoc() {
const body = { name: 'body' }
const doc = { body, documentElement: { name: 'html' }, activeElement: body }
const el = (name, extra = {}) => ({ name, isConnected: true, disabled: false, focusCalls: 0, focus() { this.focusCalls += 1; doc.activeElement = this }, ...extra })
return { doc, body, el }
}
test('focusLost: body, Wurzel, nichts, gesperrtes oder ausgehängtes Element gelten als verloren, ein bedienbares Element nicht', () => {
const { doc, body, el } = fakeDoc()
assert.equal(focusLost(doc), true) // activeElement = body
doc.activeElement = doc.documentElement; assert.equal(focusLost(doc), true)
for (const nothing of [null, undefined]) { doc.activeElement = nothing; assert.equal(focusLost(doc), true, String(nothing)) }
doc.activeElement = el('a', { disabled: true }); assert.equal(focusLost(doc), true) // der Browser lässt es erst beim nächsten Takt los
doc.activeElement = el('b', { isConnected: false }); assert.equal(focusLost(doc), true)
doc.activeElement = el('c'); assert.equal(focusLost(doc), false)
// ohne document (Node, Server) gibt es nichts zurückzugeben
for (const none of [null, undefined]) assert.equal(focusLost(none), false)
assert.equal(body.name, 'body')
})
test('activeControl: das fokussierte Bedienelement, sonst null (body und Wurzel zählen nicht)', () => {
const { doc, el } = fakeDoc()
assert.equal(activeControl(doc), null)
doc.activeElement = doc.documentElement; assert.equal(activeControl(doc), null)
doc.activeElement = null; assert.equal(activeControl(doc), null)
const button = el('button'); doc.activeElement = button
assert.equal(activeControl(doc), button)
assert.equal(activeControl(null), null); assert.equal(activeControl(undefined), null)
})
test('restoreFocus: nimmt den ersten Kandidaten, der noch da und frei ist; greift nur ein, wenn der Fokus verloren ging', () => {
const { doc, body, el } = fakeDoc()
const gone = el('gone', { isConnected: false })
const locked = el('locked', { disabled: true })
const first = el('first')
const second = el('second')
assert.equal(restoreFocus(doc, [null, undefined, gone, locked, first, second]), true)
assert.equal(doc.activeElement, first); assert.deepEqual([first.focusCalls, second.focusCalls, gone.focusCalls, locked.focusCalls], [1, 0, 0, 0])
// der Fokus liegt woanders (die Person hat inzwischen selbst gewählt): nichts wird angefasst
const other = el('other'); doc.activeElement = other
assert.equal(restoreFocus(doc, [first]), false)
assert.equal(doc.activeElement, other); assert.equal(first.focusCalls, 1)
// kein brauchbarer Kandidat, kein document, keine Liste: false, nichts passiert
doc.activeElement = body
assert.equal(restoreFocus(doc, [null, gone, locked]), false); assert.equal(doc.activeElement, body)
assert.equal(restoreFocus(null, [first]), false); assert.equal(restoreFocus(doc, []), false)
// Dinge ohne focus() (Attrappen, Textknoten) werden übersprungen
assert.equal(restoreFocus(doc, [{ isConnected: true }, 'text', 7, second]), true); assert.equal(doc.activeElement, second)
})