dashboard.html und die öffentlichen Seiten setzen viewport-fit=cover, aber kein Rand nutzte env(safe-area-inset-left|right): Im Querformat am iPhone rutschten die ersten Zeichen unter Notch und Insel. Kopf, Hauptseite, Blatt, Streifen, Konto-Sheet, Fehlerzeile, Leiste, Banner und die Sperre sowie Login, Rechtsseiten, Auftrag, Offline-Seite und die Kopfzeile des Chat-Vollbilds bauen ihre Ränder jetzt mit max(Wert, env(safe-area-inset-left|right)). Am Desktop und ohne Notch ändert sich nichts (Inset 0). Pins in test/knEfixCss.test.js. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
56 lines
3.7 KiB
JavaScript
56 lines
3.7 KiB
JavaScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { lies, handyTeil } from './support/knHuelle.js'
|
|
|
|
// Abschlussprüfung Phase E (Fix-Welle): Pins für die CSS-Befunde der neuen Seite. Sie lesen nur Quelltext, kein Browser.
|
|
const HUELLE = lies('huelle.css')
|
|
const regel = (css, selektor) => {
|
|
const m = css.match(new RegExp(`(?:^|\\n)${selektor.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\{([^}]*)\\}`))
|
|
return m ? m[1] : ''
|
|
}
|
|
|
|
test('F2: die Sperre der Mitarbeiter-Kundenansicht (.kb-view-overlay) ist in der neuen Seite eine echte Sperre', () => {
|
|
const o = regel(HUELLE, '.kb-view-overlay')
|
|
assert.match(o, /position:\s*fixed/)
|
|
assert.match(o, /inset:\s*0\b/)
|
|
assert.match(o, /z-index:\s*(\d{3,})/) // über Konto (60), Leiste (40) und Banner
|
|
assert.ok(Number(o.match(/z-index:\s*(\d+)/)?.[1]) > 60)
|
|
assert.match(o, /background:\s*var\(--kn-bg\)/) // deckend weiß, kein Glas, kein rgba mit Durchsicht
|
|
assert.doesNotMatch(o, /rgba|transparent|opacity/)
|
|
const karte = regel(HUELLE, '.kb-view-overlay-card')
|
|
assert.match(karte, /max-width:\s*\d+px/)
|
|
const knopf = regel(HUELLE, '.kb-view-overlay-card button')
|
|
assert.match(knopf, /min-height:\s*44px/)
|
|
assert.match(knopf, /background:\s*var\(--kn-accent\)/)
|
|
assert.match(regel(HUELLE, '.kb-view-overlay-card p'), /font-size:\s*\d+px/)
|
|
})
|
|
|
|
test('F3: Fokusring der Shell-Reiter liegt innen (Spezifität über .kn [tabindex]:focus-visible aus module.css, 0-3-0)', () => {
|
|
const BASIS = lies('basis.css')
|
|
assert.match(HUELLE, /\n\.kn \.kn-t\[role="tab"\]:focus-visible\s*\{[^}]*outline-offset:\s*-2px/)
|
|
assert.match(BASIS, /\n\.kn \.kn-reiter-t\[role="tab"\]:focus-visible\s*\{[^}]*outline-offset:\s*-2px/)
|
|
// keine Regel mit niedrigerer Spezifität, die den Versatz setzt
|
|
assert.doesNotMatch(HUELLE, /\n\.kn-t:focus-visible/)
|
|
assert.doesNotMatch(BASIS, /\n\.kn-reiter-t:focus-visible/)
|
|
// der aktive Reiter liegt auf dem schwarzen Gleiter: heller Innenring dort
|
|
assert.match(HUELLE, /\.kn \.kn-balken:has\(\.kn-t:focus-visible\) \.kn-gleiter\s*\{[^}]*outline:\s*2px solid #fff[^}]*outline-offset:\s*-3px/)
|
|
})
|
|
|
|
test('F3: Pflicht- und Zahlungslinks haben am Handy eine Tippfläche von 44 px', () => {
|
|
const handy = handyTeil(lies('ansichten.css'))
|
|
assert.match(handy, /\.kn-kuendigen a,\s*\.kn-widerruf a,\s*\.kn-links a,\s*\.kn-rechnung-offen a\s*\{[^}]*display:\s*inline-flex[^}]*min-height:\s*44px/)
|
|
})
|
|
|
|
// F3: Safe-Area links und rechts (Querformat am iPhone, viewport-fit=cover): jeder feste Seitenrand der Hülle und der öffentlichen Seiten
|
|
// wird mit max(Wert, env(safe-area-inset-left|right)) gebaut
|
|
const alleRegeln = (css) => [...css.matchAll(/([^{}]+)\{([^{}]*)\}/g)].map((m) => ({ selektoren: m[1].replace(/\/\*[\s\S]*?\*\//g, '').split(',').map((x) => x.trim()), text: m[2] }))
|
|
const hatInsets = (css, selektor) => alleRegeln(css).some((r) => r.selektoren.includes(selektor) && /env\(safe-area-inset-left\b/.test(r.text) && /env\(safe-area-inset-right\b/.test(r.text))
|
|
test('F3: Seitenränder der Hülle berücksichtigen die Safe-Area links und rechts', () => {
|
|
for (const sel of ['.kn-kopf', '.kn-haupt', '.kn-blatt', '.kn-streifen', '.kn-konto', '#kn-fehler', '.kn-rw', '.kn-banner', '.kb-view-overlay']) assert.ok(hatInsets(HUELLE, sel), `huelle.css: ${sel}`)
|
|
})
|
|
test('F3: Seitenränder der öffentlichen Seiten und des Chats berücksichtigen die Safe-Area links und rechts', () => {
|
|
const oeff = lies('oeffentlich/oeffentlich.css')
|
|
for (const sel of ['.kn-login-kopf', '.kn-login-haupt', '.kn-recht main', '.ab-seite .ab-innen']) assert.ok(hatInsets(oeff, sel), `oeffentlich.css: ${sel}`)
|
|
assert.ok(hatInsets(lies('chat-composer.css'), '.chat-ov-top'), 'chat-composer.css: .chat-ov-top')
|
|
})
|