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

104 lines
6.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { h } from '../public/termine-dom.js'
import { initTermine } from '../public/termine.js'
import { bestellbarerStand } from './support/fragebogenStand.js'
import { einschaltenAttrappe, hoereAufKn, mitDom, routen } from './support/modulAbo.js'
// Terminplaner im Abo-Modell (P4 Task 3): der letzte Schritt des Fragebogens heißt „Prüfen und einschalten“ und mountet den Ablauf von P3
// statt der Bestellseite; keine Haken, kein Preisblock, kein Checkout. Ohne modell === 'abo' bleibt die Bestellseite wie heute.
const STAND = bestellbarerStand({ now: new Date('2026-10-16T08:00:00.000Z') })
const daten = (extra) => ({ state: 'off', einstellung: STAND.einstellung, fragebogen: STAND.fragebogen, version: 1, branchen: [], kundenansicht: false, abo: { ok: true }, offen: [], bestellung: null, ...extra })
const liste = (modell, state = 'off', feature = {}) => ({
body: {
...(modell === undefined ? {} : { modell }),
projects: [{ projectId: 'p1', projectName: 'Salon', features: { termine: { state, siteKey: 'abcdefghijklmnop', ...feature } } }],
termine: { verfuegbar: true, bestellbar: true, grund: null, preis: '149 €', einrichtung: 'meist in 1–2 Wochen', hinweis: null },
},
})
const BESTELLUNG = {
preis: '149 €',
preisHinweis: 'einmalig, ohne Umsatzsteuer gemäß § 19 UStG',
einrichtung: '',
belehrung: null,
dokumente: [],
consent: { version: 'v-test', knopf: 'Zahlungspflichtig bestellen · 149 €', items: [{ id: 'beginn', text: 'Ich verlange den sofortigen Beginn.', haken: true }] },
}
const EINSTELLUNGEN = 'GET /api/termine/einstellungen?projectId=p1'
async function oeffne(fx, tabelle, optionen) {
routen(fx, tabelle)
const wurzel = h('div')
document.body.append(wurzel)
await initTermine(wurzel, { projectId: 'p1', ...optionen })
await fx.ruhe()
return wurzel
}
test('Abo, alles bestätigt: letzter Schritt E1 mountet den Ablauf, ohne Haken, Preisblock und Checkout; keine Reiter', mitDom(async (fx) => {
const a = einschaltenAttrappe()
const k = hoereAufKn(fx)
const wurzel = await oeffne(fx, { 'GET /api/funktionen': liste('abo'), [EINSTELLUNGEN]: { body: daten() } }, { einschalten: a.fn })
assert.equal(fx.text(fx.finde(wurzel, '.tm-fb-bestellen h3')), 'Prüfen und einschalten')
assert.match(fx.text(fx.finde(wurzel, '.tm-schritt[aria-current="step"]')), /Prüfen und einschalten/)
assert.match(fx.text(fx.finde(wurzel, '.tm-schritt-stand')), /Prüfen und einschalten/)
assert.deepEqual(a.aufrufe.map((x) => [x.key, x.projectId, x.viewAs]), [['termine', 'p1', false]])
assert.equal(fx.alle(wurzel, 'input[type="checkbox"]').length, 0, 'auch kein Haken „gesundheit“')
for (const sel of ['[data-aktion="bestellen"]', '.tm-bestellen-preis', '.tm-rechtstext', '.tm-bestellen-zustimmung']) assert.ok(fx.finde(wurzel, sel) === null, sel)
assert.equal(fx.fetchLog.filter((x) => x.method === 'POST').length, 0)
assert.deepEqual(k.reiter.at(-1).eintraege, [])
}))
test('Abo, offene Punkte: kein Ablauf, Hinweis E2, „Zum Schritt“ führt zurück', mitDom(async (fx) => {
const a = einschaltenAttrappe()
const offen = [{ schritt: 'zeiten', text: 'Bitte wähle das Bundesland deines Betriebs.' }]
const wurzel = await oeffne(fx, { 'GET /api/funktionen': liste('abo'), [EINSTELLUNGEN]: { body: daten({ offen }) } }, { einschalten: a.fn })
assert.equal(a.aufrufe.length, 0)
assert.match(fx.text(wurzel), /Du kannst einschalten, sobald die offenen Punkte erledigt sind\./)
await fx.klick(fx.finde(wurzel, '[data-aktion="zum-schritt"][data-schritt="zeiten"]'))
assert.equal(fx.finde(wurzel, '.tm-schritt[aria-current="step"]').getAttribute('data-schritt'), 'zeiten')
}))
test('Abo: nach dem Einschalten lädt die Ansicht neu und zeigt die Statuskarte „In Einrichtung“ mit „Eingeschaltet am“', mitDom(async (fx) => {
const a = einschaltenAttrappe()
let n = 0
const wurzel = await oeffne(fx, {
'GET /api/funktionen': () => (n === 0 ? liste('abo') : liste('abo', 'setup', { orderedAt: '2026-10-16T09:00:00.000Z', ticketWoid: '100150' })),
[EINSTELLUNGEN]: () => ({ body: n === 0 ? daten() : daten({ state: 'setup' }) }),
}, { einschalten: a.fn })
n = 1
a.fertig(0)
await fx.ruhe()
const karte = fx.finde(wurzel, '.tm-statuskarte[data-state="setup"]')
assert.match(fx.text(karte), /Eingeschaltet am\s*16\.10\.2026/)
assert.doesNotMatch(fx.text(karte), /Bestellt am|Zahlung/)
}))
test('Abo: ohne Funktion einschalten steht E4; in der Kundenansicht steht F1 und der Ablauf bekommt viewAs true', mitDom(async (fx) => {
const ohne = await oeffne(fx, { 'GET /api/funktionen': liste('abo'), [EINSTELLUNGEN]: { body: daten() } })
assert.match(fx.text(ohne), /Das Einschalten ist gerade nicht verfügbar\. Bitte lade die Seite neu oder schreib uns im Chat\./)
const a = einschaltenAttrappe()
const ansicht = await oeffne(fx, { 'GET /api/funktionen': liste('abo'), [EINSTELLUNGEN]: { body: daten({ kundenansicht: true }) } }, { einschalten: a.fn })
assert.match(fx.text(ansicht), /Du siehst den Fragebogen in der Kundenansicht\. Angaben kannst du ändern, Schritte bestätigen und einschalten kann nur der Kunde selbst\./)
assert.equal(a.aufrufe[0].viewAs, true)
}))
test('Abo: die Zusammenfassung der Angaben bleibt auf der Einschalt-Seite (Gruppen mit „Ändern“)', mitDom(async (fx) => {
const a = einschaltenAttrappe()
const wurzel = await oeffne(fx, { 'GET /api/funktionen': liste('abo'), [EINSTELLUNGEN]: { body: daten() } }, { einschalten: a.fn })
assert.ok(fx.alle(wurzel, '.tm-bestellen-gruppe').length > 0)
assert.ok(fx.finde(wurzel, '[data-aktion="aendern"]'))
}))
test('Ohne modell (fehlt, leer, „Abo“, „abo “): unverändert Bestellseite mit Knopf des Registers, Ablauf wird nie gerufen', mitDom(async (fx) => {
for (const modell of [undefined, '', 'Abo', 'abo ']) {
const a = einschaltenAttrappe()
const wurzel = await oeffne(fx, { 'GET /api/funktionen': liste(modell), [EINSTELLUNGEN]: { body: daten({ bestellung: BESTELLUNG }) } }, { einschalten: a.fn })
assert.equal(a.aufrufe.length, 0, JSON.stringify(modell))
assert.equal(fx.text(fx.finde(wurzel, '[data-aktion="bestellen"]')), 'Zahlungspflichtig bestellen · 149 €')
assert.equal(fx.text(fx.finde(wurzel, '.tm-fb-bestellen h3')), 'Prüfen und bestellen')
assert.match(fx.text(fx.finde(wurzel, '.tm-schritt[aria-current="step"]')), /Prüfen und bestellen/)
}
}))