110 lines
6.7 KiB
JavaScript
110 lines
6.7 KiB
JavaScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { h } from '../public/termine-dom.js'
|
|
import { initZeiten } from '../public/zeiten.js'
|
|
import { zeitenStatusKarte } from '../public/zeiten-bestellen.js'
|
|
import { KEIN_PREIS, einschaltenAttrappe, mitDom, routen } from './support/modulAbo.js'
|
|
|
|
// Öffnungszeiten live im Abo-Modell (P4 Task 7): Einschalten über den Ablauf von P3, kein Behalten-Weg, Abo-Ende und Abschaltung ohne Preis
|
|
// (Texte Z2, Z3, E5). Ohne modell === 'abo' bleiben Bestellseite, „Für 30 € behalten“ und „Bestellt am“.
|
|
|
|
const EDITOR = { state: 'active', daten: null, version: 0, kundenansicht: false, vorschau: null, feiertage: [], googleText: '' } // Antwort von GET /api/zeiten/p1
|
|
const feature = (state, extra = {}) => ({
|
|
state, siteKey: null, ticketWoid: null, orderedAt: null, activatedAt: null, invoiceUrl: null, disabledReason: null, disabledAt: null, loeschungAm: null,
|
|
unlockedBy: state === 'off' ? null : 'abo', aboEndeAt: null, einbau: null, ...extra,
|
|
})
|
|
const liste = (modell, state = 'off', extra = {}, angebot = {}) => ({
|
|
body: {
|
|
...(modell ? { modell } : {}),
|
|
projects: [{ projectId: 'p1', projectName: 'Website p1', liveUrl: '', features: { news: { state: 'off' }, zeiten: feature(state, extra) }, zeitenStatus: null, zeitenLeer: false }],
|
|
features: {
|
|
zeiten: {
|
|
priceLabel: '30 €',
|
|
consent: { version: 'v', knopf: 'Zahlungspflichtig bestellen · 30 €', items: [] },
|
|
leistungsbeschreibung: { version: '2026-10-05', url: '/vertragsunterlagen/zeiten-leistungsbeschreibung.html' },
|
|
},
|
|
},
|
|
ustHinweis: 'ohne Umsatzsteuer gemäß § 19 UStG',
|
|
zeiten: {
|
|
verfuegbar: true,
|
|
inklusive: true,
|
|
grund: null,
|
|
preis: '30 €',
|
|
einschalten: { consent: { version: 'v', knopf: 'Einschalten', items: [] }, leistungsbeschreibung: { version: '2026-10-05', url: '/vertragsunterlagen/zeiten-leistungsbeschreibung.html' } },
|
|
belehrung: 'Belehrung',
|
|
...angebot,
|
|
},
|
|
},
|
|
})
|
|
async function oeffne(fx, antwort, { einschalten, dataset = {} } = {}) {
|
|
routen(fx, { 'GET /api/funktionen': antwort, 'GET /api/zeiten/p1': { body: EDITOR } })
|
|
const root = h('div')
|
|
document.body.append(root)
|
|
Object.assign(root.dataset, dataset)
|
|
await initZeiten(root, { projectId: 'p1', einschalten })
|
|
await fx.ruhe()
|
|
return root
|
|
}
|
|
const ALT_ENDE = { aboEndeAt: '2026-09-01T00:00:00.000Z' }
|
|
const KEIN_ABO = { inklusive: false, grund: 'kein_abo' }
|
|
|
|
test('Abo, off: Einschalt-Seite mit key zeiten, ohne Haken, Preis und Behalten; nach onFertig die Danke-Zeile', mitDom(async (fx) => {
|
|
const a = einschaltenAttrappe()
|
|
let n = 0
|
|
const root = await oeffne(fx, () => (n === 0 ? liste('abo') : liste('abo', 'setup')), { einschalten: a.fn })
|
|
assert.deepEqual([a.aufrufe[0].key, a.aufrufe[0].projectId, a.aufrufe[0].viewAs], ['zeiten', 'p1', false])
|
|
assert.equal(fx.alle(root, 'input[type="checkbox"]').length, 0)
|
|
assert.ok(fx.finde(root, '[data-aktion="behalten"], [data-aktion="bestellen"], [data-aktion="einschalten"]') === null)
|
|
assert.doesNotMatch(fx.text(root), KEIN_PREIS)
|
|
n = 1
|
|
a.fertig(0)
|
|
await fx.ruhe()
|
|
assert.match(fx.text(fx.finde(root, '.zt-status')), /Öffnungszeiten live ist eingeschaltet\./)
|
|
}))
|
|
|
|
test('Abo, off ohne Funktion einschalten: Fehlerkarte E4', mitDom(async (fx) => {
|
|
const root = await oeffne(fx, liste('abo'))
|
|
assert.match(fx.text(root), /Das Einschalten ist gerade nicht verfügbar\. Bitte lade die Seite neu oder schreib uns im Chat\./)
|
|
}))
|
|
|
|
test('Abo: Abo-Ende in active nennt die Frist (Z2) und „Eingeschaltet am“, ohne Preis und ohne Behalten-Knopf', mitDom(async (fx) => {
|
|
const karte = zeitenStatusKarte({ projekt: { projectId: 'p1', zeitenLeer: false }, feature: { state: 'active', orderedAt: '2026-08-01T10:00:00.000Z', ...ALT_ENDE }, angebot: { ...KEIN_ABO, preis: '30 €' }, modell: 'abo' }, {})
|
|
assert.match(fx.text(karte), /Dein Wartungs-Abo ist beendet\. Öffnungszeiten live läuft noch bis 01\.10\.2026 und schaltet sich dann ab\./)
|
|
assert.match(fx.text(karte), /Eingeschaltet am\s*01\.08\.2026/)
|
|
assert.ok(fx.finde(karte, '[data-aktion="behalten"]') === null)
|
|
assert.doesNotMatch(fx.text(karte), KEIN_PREIS)
|
|
}))
|
|
|
|
test('Abo: abgeschaltet mit Daten (Z3), ohne Behalten-Knopf', mitDom(async (fx) => {
|
|
const karte = zeitenStatusKarte({ projekt: { projectId: 'p1', zeitenLeer: false }, feature: { state: 'disabled', disabledReason: 'abo_ende', loeschungAm: '2099-12-31' }, angebot: { ...KEIN_ABO, preis: '30 €' }, modell: 'abo' }, {})
|
|
assert.match(fx.text(karte), /Deine Eingaben bleiben bis 31\.12\.2099 gespeichert\. Mit einem neuen Wartungs-Abo schaltet sich Öffnungszeiten live wieder ein\./)
|
|
assert.ok(fx.finde(karte, '[data-aktion="behalten"]') === null)
|
|
assert.doesNotMatch(fx.text(karte), KEIN_PREIS)
|
|
const ohneDatum = zeitenStatusKarte({ projekt: { projectId: 'p1', zeitenLeer: false }, feature: { state: 'disabled', disabledReason: 'abo_ende' }, angebot: { ...KEIN_ABO, preis: '30 €' }, modell: 'abo' }, {})
|
|
assert.match(fx.text(ohneDatum), /Deine Eingaben bleiben gespeichert\. Mit einem neuen Wartungs-Abo schaltet sich Öffnungszeiten live wieder ein\./)
|
|
}))
|
|
|
|
test('wunschWeg „behalten“: im Abo-Modell ohne Wirkung, ohne modell die Behalten-Seite und der Knopf „Für 30 € behalten“', mitDom(async (fx) => {
|
|
const wunsch = { dataset: { wunschWeg: 'behalten' } }
|
|
const abo = await oeffne(fx, liste('abo', 'active', ALT_ENDE, KEIN_ABO), wunsch)
|
|
assert.ok(fx.finde(abo, '[data-variante="behalten"]') === null)
|
|
assert.ok(fx.finde(abo, '[data-aktion="behalten"]') === null)
|
|
assert.ok(fx.finde(abo, '.zt-status'))
|
|
assert.equal(abo.dataset.wunschWeg, undefined)
|
|
const alt = await oeffne(fx, liste(undefined, 'active', ALT_ENDE, KEIN_ABO), wunsch)
|
|
assert.ok(fx.finde(alt, '[data-variante="behalten"]'))
|
|
const karte = zeitenStatusKarte({ projekt: { projectId: 'p1', zeitenLeer: false }, feature: { state: 'active', ...ALT_ENDE }, angebot: { ...KEIN_ABO, preis: '30 €' } }, {})
|
|
assert.equal(fx.text(fx.finde(karte, '[data-aktion="behalten"]')), 'Für 30 € behalten')
|
|
}))
|
|
|
|
test('Ohne modell (fehlt, „Abo“, „abo “): Bestellseite wie bisher, „Bestellt am“, der Ablauf wird nie gerufen', mitDom(async (fx) => {
|
|
for (const modell of [undefined, 'Abo', 'abo ']) {
|
|
const a = einschaltenAttrappe()
|
|
const bestellen = await oeffne(fx, liste(modell, 'off', {}, KEIN_ABO), { einschalten: a.fn })
|
|
assert.ok(fx.finde(bestellen, '[data-aktion="bestellen"]'), String(modell))
|
|
assert.equal(a.aufrufe.length, 0)
|
|
const karte = zeitenStatusKarte({ projekt: { projectId: 'p1', zeitenLeer: false }, feature: { state: 'active', orderedAt: '2026-08-01T10:00:00.000Z' }, angebot: { inklusive: true }, modell }, {})
|
|
assert.match(fx.text(karte), /Bestellt am\s*01\.08\.2026/)
|
|
}
|
|
}))
|