Files
Webklar-Kundenbereich/test/kundenansichtNeuModulEinschalten.test.js

116 lines
6.2 KiB
JavaScript

import { test } from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { h } from '../public/termine-dom.js'
import { renderEinschaltSeite, statusKarte } from '../public/funktion-bestellen.js'
import { KEIN_PREIS, einschaltenAttrappe, mitDom } from './support/modulAbo.js'
// Gemeinsame Einschalt-Seite der Funktionsmodule im Abo-Modell (P4 Task 2): Zusammenfassung und offene Punkte, danach der Ablauf von P3
// (zeigeEinschalten) im Platz div.tm-einschalten-platz; keine Haken, kein Preis, kein Checkout.
function seite(optionen) {
const wurzel = h('div')
document.body.append(wurzel)
renderEinschaltSeite(wurzel, { ctx: { projectId: 'p1' }, daten: { offen: [], kundenansicht: false }, key: 'shop', ...optionen })
return wurzel
}
const GRUPPEN = () => [{ schritt: 'anfrage', titel: 'Deine Anfrage', zeilen: ['Was du verkaufst: Kleidung'] }]
test('mountet den Ablauf genau einmal in den Platz, mit key, projectId und viewAs; ohne Haken, Preis und Überschrift', mitDom(async (fx) => {
const a = einschaltenAttrappe()
const wurzel = seite({ einschalten: a.fn })
assert.equal(a.aufrufe.length, 1)
assert.deepEqual([a.aufrufe[0].key, a.aufrufe[0].projectId, a.aufrufe[0].viewAs], ['shop', 'p1', false])
assert.ok(a.aufrufe[0].wurzel === fx.finde(wurzel, '[data-einschalten="shop"]'))
assert.ok(fx.finde(wurzel, '.tm-einschalten-platz'))
assert.ok(fx.finde(wurzel, 'h3') === null)
assert.equal(fx.alle(wurzel, 'input').length, 0)
assert.doesNotMatch(fx.text(wurzel), KEIN_PREIS)
const hulle = fx.finde(wurzel, 'section.kb-panel.tm-bestellen.tm-einschalten')
assert.equal(hulle.getAttribute('data-key'), 'shop')
}))
test('Zusammenfassung mit E1; offene Punkte sperren den Ablauf (E2); „Ändern“ und „Zum Schritt“ rufen zumSchritt', mitDom(async (fx) => {
const a = einschaltenAttrappe()
const schritte = []
const wurzel = seite({ einschalten: a.fn, zusammenfassung: GRUPPEN, zumSchritt: (k) => schritte.push(k), daten: { offen: [{ schritt: 'zeiten', text: 'Bitte wähle das Bundesland.' }], kundenansicht: false } })
assert.equal(fx.text(fx.finde(wurzel, 'h3')), 'Prüfen und einschalten')
assert.equal(a.aufrufe.length, 0)
assert.ok(fx.finde(wurzel, '.tm-einschalten-platz') === null)
assert.match(fx.text(wurzel), /Du kannst einschalten, sobald die offenen Punkte erledigt sind\./)
assert.doesNotMatch(fx.text(wurzel), /bestellen/i)
await fx.klick(fx.finde(wurzel, '[data-aktion="zum-schritt"][data-schritt="zeiten"]'))
await fx.klick(fx.finde(wurzel, '[data-aktion="aendern"][data-schritt="anfrage"]'))
assert.deepEqual(schritte, ['zeiten', 'anfrage'])
}))
test('Zusammenfassung ohne offene Punkte: Gruppe, dann der Platz mit dem Ablauf', mitDom(async (fx) => {
const a = einschaltenAttrappe()
const wurzel = seite({ einschalten: a.fn, zusammenfassung: GRUPPEN })
assert.equal(fx.text(fx.finde(wurzel, 'h3')), 'Prüfen und einschalten')
assert.equal(fx.text(fx.finde(wurzel, '.tm-bestellen-gruppe h4')), 'Deine Anfrage')
assert.equal(a.aufrufe.length, 1)
assert.doesNotMatch(fx.text(wurzel), /Du kannst einschalten, sobald/)
assert.ok(fx.finde(wurzel, '[data-aktion="aendern"]') === null, 'ohne zumSchritt kein „Ändern“')
}))
test('Kundenansicht: der Ablauf bekommt viewAs true (daten und ctx)', mitDom(async () => {
const a = einschaltenAttrappe()
seite({ einschalten: a.fn, daten: { offen: [], kundenansicht: true } })
const b = einschaltenAttrappe()
seite({ einschalten: b.fn, ctx: { projectId: 'p1', kundenansicht: true } })
assert.equal(a.aufrufe[0].viewAs, true)
assert.equal(b.aufrufe[0].viewAs, true)
}))
test('onFertig: höchstens einmal, nicht nach ctx.aktuell() === false', mitDom(async (fx) => {
let n = 0
const a = einschaltenAttrappe()
seite({ einschalten: a.fn, nachEinschalten: () => { n += 1 } })
a.fertig(0)
a.fertig(0)
await fx.ruhe()
assert.equal(n, 1)
const b = einschaltenAttrappe()
seite({ einschalten: b.fn, ctx: { projectId: 'p1', aktuell: () => false }, nachEinschalten: () => { n += 1 } })
b.fertig(0)
await fx.ruhe()
assert.equal(n, 1)
}))
test('nachEinschalten darf scheitern, ohne dass ein Promise unbehandelt bleibt', mitDom(async (fx) => {
const a = einschaltenAttrappe()
seite({ einschalten: a.fn, nachEinschalten: async () => { throw new Error('Netz weg') } })
a.fertig(0)
await fx.ruhe()
}))
test('ohne Funktion einschalten: Fehlerkarte E4 statt Absturz', mitDom(async (fx) => {
const wurzel = seite({})
assert.match(fx.text(wurzel), /Das Einschalten ist gerade nicht verfügbar\. Bitte lade die Seite neu oder schreib uns im Chat\./)
assert.ok(fx.finde(wurzel, '[role="alert"]'))
}))
test('wirft oder scheitert einschalten, steht E4 im Platz', mitDom(async (fx) => {
const wurzel = seite({ einschalten: () => { throw new Error('kaputt') } })
assert.match(fx.text(fx.finde(wurzel, '.tm-einschalten-platz')), /Das Einschalten ist gerade nicht verfügbar\./)
const spaeter = seite({ einschalten: () => Promise.reject(new Error('kaputt')) })
await fx.ruhe()
assert.match(fx.text(fx.finde(spaeter, '.tm-einschalten-platz')), /Das Einschalten ist gerade nicht verfügbar\./)
}))
test('statusKarte: Abo-Modell „Eingeschaltet am“, sonst „Bestellt am“ (auch bei „Abo“ und leer)', mitDom(async (fx) => {
const args = { projekt: { projectId: 'p1' }, bestellung: { state: 'setup', orderedAt: '2026-10-16T09:00:00.000Z', ticketWoid: '100150' } }
assert.match(fx.text(statusKarte({ ...args, modell: 'abo' })), /Eingeschaltet am\s*16\.10\.2026/)
assert.match(fx.text(statusKarte(args)), /Bestellt am\s*16\.10\.2026/)
for (const modell of ['Abo', '', 'abo ']) assert.match(fx.text(statusKarte({ ...args, modell })), /Bestellt am/, JSON.stringify(modell))
assert.doesNotMatch(fx.text(statusKarte({ ...args, modell: 'abo' })), /Bestellt am/)
}))
test('Quelltext: renderEinschaltSeite kommt ohne neue Importe, href, innerHTML und Pin-Wörter aus', () => {
const roh = readFileSync(new URL('../public/funktion-bestellen.js', import.meta.url), 'utf8')
const code = roh.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|\s)\/\/.*$/gm, '')
assert.deepEqual(code.match(/from '[^']+'/g), ["from './termine-dom.js'", "from './termine-view.js'"])
assert.doesNotMatch(code, /import\s*\(/)
})