Öffnungszeiten live: im Abo-Modell Einschalten und kein Behalten-Weg
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5f3d8f3e96
commit
c37faabcd3
9 files changed
+190
-18
No files matched your search
@@ -78,3 +78,10 @@ test('Ohne modell (fehlt, „Abo“): Formular mit „199 € einmalig“, angen
|
||||
assert.equal(a.aufrufe.length, 0)
|
||||
}
|
||||
}))
|
||||
|
||||
test('Abo, Kundenansicht der Mitarbeiter (window.KbView.id): der Ablauf bekommt viewAs true', mitDom(async (fx) => {
|
||||
fx.window.KbView = { id: () => 'view1' }
|
||||
const a = einschaltenAttrappe()
|
||||
await oeffne(fx, { kopf: { modell: 'abo' }, anfrage: ZUGESAGT, einschalten: a.fn })
|
||||
assert.equal(a.aufrufe[0].viewAs, true)
|
||||
}))
|
||||
@@ -81,3 +81,14 @@ test('wunschProjekt aus dem Behälter wählt das Projekt und wird entfernt', asy
|
||||
assert.equal(a.aufrufe[0].projectId, 'p2')
|
||||
assert.equal(root.dataset.wunschProjekt, undefined)
|
||||
})
|
||||
|
||||
test('Abo, Kundenansicht der Mitarbeiter (window.KbView.id): der Ablauf bekommt viewAs true', async () => {
|
||||
globalThis.window.KbView = { id: () => 'view1' }
|
||||
try {
|
||||
const a = einschaltenAttrappe()
|
||||
await lauf({ modell: 'abo', einschalten: a.fn })
|
||||
assert.equal(a.aufrufe[0].viewAs, true)
|
||||
} finally {
|
||||
delete globalThis.window.KbView
|
||||
}
|
||||
})
|
||||
@@ -107,3 +107,10 @@ test('Ohne modell (fehlt, „Abo“): Formular mit Unternehmer-Haken und 299 €
|
||||
assert.equal(a.aufrufe.length, 0)
|
||||
}
|
||||
}))
|
||||
|
||||
test('Abo, Kundenansicht der Mitarbeiter (window.KbView.id): der Ablauf bekommt viewAs true', mitDom(async (fx) => {
|
||||
fx.window.KbView = { id: () => 'view1' }
|
||||
const a = einschaltenAttrappe()
|
||||
await oeffne(fx, { kopf: { modell: 'abo', kundenart: 'unternehmen' }, anfrage: ZUGESAGT, einschalten: a.fn })
|
||||
assert.equal(a.aufrufe[0].viewAs, true)
|
||||
}))
|
||||
@@ -0,0 +1,109 @@
|
||||
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/)
|
||||
}
|
||||
}))
|
||||
Reference in new issue
Block a user