80 lines
7.0 KiB
JavaScript
80 lines
7.0 KiB
JavaScript
import { test } from 'node:test'
|
||
import assert from 'node:assert/strict'
|
||
import { installFakeDom } from './support/fakeDom.js'
|
||
import { h } from '../public/neu/dom.js'
|
||
import { initialenVon, installAngebot, kontoEintraege, baueAvatar, baueKonto } from '../public/neu/konto.js'
|
||
import { lies, handyTeil } from './support/knHuelle.js'
|
||
|
||
test('Reihenfolge, Texte und Ziele des Kontos (V3); Widerrufen immer da, "Frist läuft" nur in der Frist', () => {
|
||
const ids = (o) => kontoEintraege(o).map((e) => e.id)
|
||
assert.deepEqual(ids({ fristen: null, install: null }), ['passwort', 'datenschutz', 'impressum', 'kuendigen', 'widerrufen', 'abmelden'])
|
||
assert.deepEqual(ids({ fristen: null, install: 'ios' }), ['passwort', 'datenschutz', 'impressum', 'installieren', 'kuendigen', 'widerrufen', 'abmelden'])
|
||
const e = Object.fromEntries(kontoEintraege({ fristen: null, install: 'prompt' }).map((x) => [x.id, x]))
|
||
assert.deepEqual([e.passwort.text, e.passwort.href, e.datenschutz.href, e.impressum.href, e.kuendigen.href, e.kuendigen.betont], ['Passwort ändern', '#passwort', '/datenschutz.html', 'https://webklar.com/impressum', '/kuendigen.html', true])
|
||
assert.deepEqual([e.widerrufen.text, e.widerrufen.href, e.widerrufen.pille, e.installieren.text, e.abmelden.text], ['Vertrag widerrufen', '/widerrufen.html', undefined, 'App installieren', 'Abmelden'])
|
||
assert.equal(kontoEintraege({ fristen: { anzeigen: true }, install: null }).find((x) => x.id === 'widerrufen').pille, 'Frist läuft')
|
||
})
|
||
|
||
test('installAngebot: nur am Handy, nicht in der installierten App (wie app.js:2267)', () => {
|
||
assert.deepEqual([{ handy: true, standalone: false, prompt: true, ios: false }, { handy: true, standalone: false, prompt: false, ios: true }, { handy: true, standalone: true, prompt: true, ios: true }, { handy: false, standalone: false, prompt: true, ios: true }].map((o) => installAngebot(o)), ['prompt', 'ios', null, null])
|
||
})
|
||
|
||
test('initialenVon und Avatar: Bild erst nach load', async () => {
|
||
assert.deepEqual(['Salon Amin', 'Amin', '', ' ', 'Äsop Öl', '– Test'].map(initialenVon), ['SA', 'AM', '', '', 'ÄÖ', 'TE'])
|
||
const fx = installFakeDom()
|
||
try {
|
||
const a = baueAvatar({ name: 'Salon Amin', kundenId: 'c1' }); assert.deepEqual([a.textContent, a.getAttribute('aria-label')], ['SA', 'Mein Konto'])
|
||
const img = fx.finde(a, 'img'); assert.equal(img.getAttribute('src'), '/api/avatar.svg?c=c1')
|
||
await fx.sende(img, 'load'); assert.ok(a.classList.contains('has-img'))
|
||
} finally { fx.restore() }
|
||
})
|
||
|
||
test('baueKonto: Kopf als Text, Sheet-Verhalten, Overlay-Kopplung, Navigation, Abmelden, aktualisiere', async () => {
|
||
const fx = installFakeDom()
|
||
try {
|
||
const log = []; const trigger = h('button'); fx.document.body.append(trigger)
|
||
const me = { customer: { id: 'c1', name: 'Anna', companyName: '<img src=x onerror=alert(1)>Salon', email: 'a@b.de' } }
|
||
const k = baueKonto({ me, fristen: null, install: null, onAbmelden: () => log.push('abmelden'), onInstall() {}, overlay: { oeffne: (o) => log.push(['overlay', typeof o.schliesse]), beende: () => log.push('beende') }, navigiere: (hash) => log.push(['geheZu', hash]) })
|
||
fx.document.body.append(k.wurzel); const zeilen = () => fx.alle(k.wurzel, '.kn-konto-zeile')
|
||
assert.deepEqual([fx.finde(k.wurzel, '.kn-konto-name').textContent, fx.finde(k.wurzel, '.kn-konto-mail').textContent], ['<img src=x onerror=alert(1)>Salon', 'a@b.de'])
|
||
assert.deepEqual(zeilen().map((z) => z.textContent), ['Passwort ändern', 'Datenschutz', 'Impressum', 'Verträge kündigen', 'Vertrag widerrufen', 'Abmelden'])
|
||
assert.deepEqual([k.wurzel.getAttribute('role'), k.wurzel.getAttribute('aria-modal')], ['dialog', 'true'])
|
||
k.oeffne(trigger); assert.deepEqual([k.istOffen(), trigger.getAttribute('aria-expanded'), log[0]], [true, 'true', ['overlay', 'function']])
|
||
await fx.sende(k.wurzel, 'keydown', { key: 'Escape' }); assert.deepEqual([k.istOffen(), log.at(-1), fx.document.activeElement === trigger], [false, 'beende', true])
|
||
k.oeffne(trigger); await fx.klick(zeilen()[0]); assert.deepEqual(log.at(-1), ['geheZu', '#passwort'])
|
||
await fx.klick(zeilen().at(-1)); assert.equal(log.at(-1), 'abmelden')
|
||
k.aktualisiere({ fristen: { anzeigen: true }, install: 'ios' }); assert.ok(k.istOffen()); assert.match(fx.text(k.wurzel), /App installieren[\s\S]*Vertrag widerrufen.*Frist läuft/)
|
||
await fx.klick(fx.finde(k.wurzel, '.kn-konto-scrim')); assert.equal(k.istOffen(), false)
|
||
} finally { fx.restore() }
|
||
})
|
||
|
||
test('huelle.css (Konto): Popover als Desktop-Grundregel, Sheet am Handy', () => {
|
||
const css = lies('huelle.css')
|
||
assert.match(css, /\.kn-konto\s*\{(?=[^}]*width:\s*280px)(?=[^}]*top:)/s)
|
||
assert.match(handyTeil(css), /\.kn-konto\s*\{[^}]*border-radius:\s*12px 12px 0 0/s)
|
||
})
|
||
|
||
test('Konto: Router schließt ohne zweites Zurück, Links öffnen richtig, Tab bleibt im Sheet, Installieren und Hinweis am iPhone, Avatar ohne Bild', async () => {
|
||
const fx = installFakeDom()
|
||
try {
|
||
const log = []; const trigger = h('button'); fx.document.body.append(trigger); let vomRouter
|
||
const k = baueKonto({ me: { customer: { id: 'c1', name: '', companyName: '', email: 'a@b.de' } }, fristen: null, install: 'ios', onAbmelden() {}, onInstall: () => log.push('installieren'),
|
||
overlay: { oeffne: (o) => { vomRouter = o.schliesse }, beende: () => log.push('beende') }, navigiere() {} })
|
||
fx.document.body.append(k.wurzel); const zeilen = () => fx.alle(k.wurzel, '.kn-konto-zeile')
|
||
assert.equal(fx.finde(k.wurzel, '.kn-konto-name').textContent, 'a@b.de') // ohne Firma und Namen die E-Mail
|
||
const [pw, ds, im, inst] = zeilen()
|
||
assert.deepEqual([ds.getAttribute('target'), ds.getAttribute('rel'), im.getAttribute('target'), pw.hasAttribute('target')], ['_blank', 'noopener', '_blank', false])
|
||
assert.match(inst.textContent, /Tippe auf Teilen und dann auf Zum Home-Bildschirm\./)
|
||
k.oeffne(trigger); assert.equal(fx.document.activeElement, pw) // Fokus auf der ersten Zeile
|
||
await fx.klick(inst); assert.deepEqual(log, ['installieren'])
|
||
const letzte = zeilen().at(-1); const zu = fx.finde(k.wurzel, '.kn-konto-zu'); letzte.focus()
|
||
await fx.sende(letzte, 'keydown', { key: 'Tab' }); assert.equal(fx.document.activeElement, zu) // Tab vom letzten Element springt zum ersten
|
||
await fx.sende(zu, 'keydown', { key: 'Tab', shiftKey: true }); assert.equal(fx.document.activeElement, letzte)
|
||
vomRouter() // Zurück-Taste: der Router schließt und ruft schliesse des Besitzers
|
||
assert.deepEqual([k.istOffen(), log.includes('beende')], [false, false]) // kein zweites history.back()
|
||
k.oeffne(trigger); k.schliesse(); k.schliesse(); assert.deepEqual(log.filter((l) => l === 'beende').length, 1) // Schließen durch den Besitzer: einmal beende, zweites schliesse tut nichts
|
||
const a = baueAvatar({ name: 'Anna', kundenId: '' }); assert.equal(fx.alle(a, 'img').length, 0)
|
||
const b = baueAvatar({ name: 'Anna', kundenId: 'c1' }); await fx.sende(fx.finde(b, 'img'), 'error'); assert.deepEqual([fx.alle(b, 'img').length, b.classList.contains('has-img')], [0, false])
|
||
} finally { fx.restore() }
|
||
})
|