Kundenansicht neu P7: Wechselseite schlank, Sofortbeginn-Häkchen nur privat

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 20:13:49 +00:00
1 parent c6ecb5242c
commit e7ac625f26
4 files changed
+270 -89

No files matched your search

+183 -38
View File
@@ -1,39 +1,131 @@
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { zeigeWechsel, gemerkteFunktion } from '../public/neu/ansicht-wechsel.js'
import { nimmHinweis } from '../public/neu/ansicht-hilfen.js'
import { sichtbarerText, ohneKopf, ladeAlteApp } from './support/knWortlautOrakel.js'
import { mit, me, abo, aboAntwort, neueWurzel, VORSCHAU } from './support/knDaten.js'
import { NEU, meMit, aboNeu } from './support/knBestellDaten.js'
const alt = ladeAlteApp()
const HOSTING = aboAntwort({ subscription: abo({ produkt: 'hosting', canSwitch: true, storage: { units: 2, pendingSetup: false, pendingReduction: null } }) })
const zeigeNeu = async (fx, daten = HOSTING, m = me(), titel = []) => { const w = neueWurzel(fx); w.addEventListener('kn:titel', (e) => titel.push(e.detail.text)); await zeigeWechsel(w, { route: { bereich: 'vertraege', etage: 'wechsel', query: '' }, me: m, nav: 'push', daten }); await fx.ruhe(); return w }
test('Wechsel: sichtbarer Text wie in app.js, Titel wird gemeldet', mit({ 'POST /api/abo/switch/preview': VORSCHAU }, async (fx) => {
const titel = []; assert.equal(sichtbarerText(await zeigeNeu(fx, HOSTING, me(), titel)), sichtbarerText(ohneKopf(await alt.wechsel(HOSTING, VORSCHAU)))); assert.deepEqual(titel, ['Wechsel ins Wartungs-Abo'])
// Wechselseite im schlanken Muster (Spec 5.6, Fassung 6): Block, Linkzeile, Häkchen nur privat mit Sperrzeile, Knopf, Kundenart-Zeile
const HOSTING = (o = {}) => aboNeu({ subscription: abo({ produkt: 'hosting', canSwitch: true, storage: { units: 2, pendingSetup: false, pendingReduction: null } }), ...o })
const SRV = { 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ body: { paymentUrl: 'https://pay.stripe.test/x', subscription: abo() } }) }
const IDS = ['switch-block', 'switch-linkzeile', 'switch-beginn', 'switch-sperre', 'switch-error', 'switch-buy', 'switch-kundenart']
const reihe = (fx, w) => fx.alle(fx.finde(w, '#switch-order'), (el) => IDS.includes(el.id)).map((el) => el.id)
const ROUTE = { bereich: 'vertraege', etage: 'wechsel', query: '' }
/** Seite zeigen; die gemeldeten Titel (kn:titel) sammelt fx.titel. */
async function zeige(fx, daten, meDaten) {
fx.titel = fx.titel ?? []
const w = neueWurzel(fx)
w.addEventListener('kn:titel', (e) => fx.titel.push(e.detail.text))
await zeigeWechsel(w, { route: ROUTE, me: meDaten, nav: 'push', daten })
await fx.ruhe()
return w
}
test('Betrieb: Block, Linkzeile, Knopf, kein Häkchen, Knopf nach der Vorschau frei, Body ohne earlyStart', mit(SRV, async (fx) => {
const w = await zeige(fx, HOSTING(), meMit('unternehmen'))
assert.deepEqual(fx.titel, ['Wechsel ins Wartungs-Abo'])
assert.equal(fx.alle(w, 'h1').length, 0) // Titel kommt als Ereignis, keine eigene h1
assert.deepEqual(reihe(fx, w), ['switch-block', 'switch-linkzeile', 'switch-error', 'switch-buy', 'switch-kundenart'])
const t = fx.text(fx.finde(w, '#switch-block'))
for (const s of ['Leistung', 'Wartungs-Abo', 'Zusatzspeicher', '2 Pakete (+10 GB)', 'Gutschrift für nicht genutzte Tage', '−15,00', 'Heute fällig', '30,00', 'Neuer Abbuchungstag', 'Laufzeit', 'Beginn', 'bei deiner Bank']) assert.ok(t.includes(s), s)
assert.equal(fx.finde(w, '#switch-buy').textContent, 'Zahlungspflichtig bestellen')
assert.equal(fx.finde(w, '#switch-buy').hasAttribute('disabled'), false)
assert.equal(fx.alle(w, 'details, dialog, input[type="checkbox"]').length, 0)
assert.equal(fx.text(fx.finde(w, '#switch-kundenart')), 'Du bestellst als Betrieb · Stimmt nicht? Schreib uns im Chat')
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.deepEqual(fx.fetchLog.find((a) => a.url === '/api/abo/switch').body, { acceptTerms: true, termsVersion: NEU, prorationDate: VORSCHAU.prorationDate, amountDueCents: VORSCHAU.amountDueCents })
assert.equal(fx.window.location.href, 'https://pay.stripe.test/x')
assert.match(fx.text(w), /Dein Wechsel wartet auf die Zahlung\. Wir leiten dich zur Zahlung weiter\./)
}))
test('Privat und leer: Knopf gesperrt mit Sperrzeile, nach dem Häkchen frei, Body mit earlyStart true', mit(SRV, async (fx) => {
for (const m of [meMit('privat'), meMit('')]) {
const w = await zeige(fx, HOSTING(), m)
assert.deepEqual(reihe(fx, w), ['switch-block', 'switch-linkzeile', 'switch-beginn', 'switch-sperre', 'switch-error', 'switch-buy', 'switch-kundenart'])
assert.equal(fx.finde(w, '#switch-buy').hasAttribute('disabled'), true)
assert.equal(fx.text(fx.finde(w, '#switch-sperre')), HOSTING().bestelltexte.wechsel.gesperrt)
assert.equal(fx.text(fx.finde(w, '#switch-beginn-text')), HOSTING().bestelltexte.wechsel.haken)
assert.equal(fx.finde(w, '#switch-beginn').checked, false)
await fx.klick(fx.finde(w, '#switch-beginn'))
assert.equal(fx.finde(w, '#switch-buy').hasAttribute('disabled'), false)
assert.equal(fx.finde(w, '#switch-sperre'), null)
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.deepEqual(fx.fetchLog.findLast((a) => a.url === '/api/abo/switch').body, { acceptTerms: true, earlyStart: true, termsVersion: NEU, prorationDate: VORSCHAU.prorationDate, amountDueCents: VORSCHAU.amountDueCents })
}
}))
test('Das Häkchen bleibt beim Neuzeichnen erhalten und lässt sich wieder abwählen', mit(SRV, async (fx) => {
const w = await zeige(fx, HOSTING(), meMit('privat'))
await fx.klick(fx.finde(w, '#switch-beginn'))
assert.equal(fx.finde(w, '#switch-beginn').checked, true)
await fx.klick(fx.finde(w, '#switch-beginn'))
assert.equal(fx.finde(w, '#switch-beginn').checked, false)
assert.equal(fx.finde(w, '#switch-buy').hasAttribute('disabled'), true)
assert.ok(fx.finde(w, '#switch-sperre'))
}))
test('Der Body enthält nie kundenart, unternehmer oder startChoice', mit(SRV, async (fx) => {
for (const m of [meMit('unternehmen'), meMit('privat')]) {
const w = await zeige(fx, HOSTING(), m)
if (fx.finde(w, '#switch-beginn')) await fx.klick(fx.finde(w, '#switch-beginn'))
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.deepEqual(Object.keys(fx.fetchLog.findLast((a) => a.url === '/api/abo/switch').body).filter((k) => /kundenart|startChoice|unternehmer/i.test(k)), [])
}
}))
test('Wechsel nicht möglich: Satz und Rückweg zu Verträgen', mit({}, async (fx) => {
fx.window.history.replaceState = (_s, _t, url) => { fx.window.location.hash = `#${String(url).split('#')[1] ?? ''}` }
const w = await zeigeNeu(fx, aboAntwort({ subscription: abo({ produkt: 'wartung' }) }))
assert.match(fx.text(w), /Ein Wechsel ist derzeit nicht möglich\. Details finden Sie unter Verträge\./); assert.equal(fx.window.location.hash, '#vertraege')
const w = await zeige(fx, aboNeu({ subscription: abo({ produkt: 'wartung' }) }), meMit('privat'))
assert.match(fx.text(w), /Ein Wechsel ist derzeit nicht möglich\. Details findest du unter Verträge\./)
assert.equal(fx.window.location.hash, '#vertraege')
}))
test('Wechsel: Prüfungen wörtlich, Body mit gemerkter Funktion, Schlüssel danach weg', mit({ 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ body: { paymentUrl: 'https://pay.stripe.com/x', subscription: abo() } }) }, async (fx) => {
const speicher = new Map(); globalThis.sessionStorage = { getItem: (k) => speicher.get(k) ?? null, setItem: (k, v) => speicher.set(k, v), removeItem: (k) => speicher.delete(k) }
test('Ohne Wortlaut oder ohne Sätze des Wechsels: nur ein Satz, kein Knopf, keine Vorschau-Abfrage', mit(SRV, async (fx) => {
const ohneWechsel = HOSTING()
delete ohneWechsel.bestelltexte.wechsel
for (const d of [aboAntwort({ termsVersion: NEU, subscription: abo({ produkt: 'hosting', canSwitch: true }) }), ohneWechsel]) {
const w = await zeige(fx, d, meMit('unternehmen'))
assert.match(fx.text(w), /Die Online-Bestellung wird gerade eingerichtet – schreib uns gern im Chat\./)
assert.equal(fx.finde(w, '#switch-buy'), null)
}
assert.equal(fx.fetchLog.filter((a) => a.url === '/api/abo/switch/preview').length, 0)
}))
test('Unsichere Linkadressen werden Text', mit(SRV, async (fx) => {
const boese = HOSTING()
boese.bestelltexte.wechsel.linkzeile.urls = ['javascript:alert(1)', '//evil.example']
assert.equal(fx.alle(await zeige(fx, boese, meMit('unternehmen')), '#switch-linkzeile a[href]').length, 0)
}))
test('Prüfungen: Body mit gemerkter Funktion, Schlüssel danach weg', mit(SRV, async (fx) => {
const speicher = new Map()
globalThis.sessionStorage = { getItem: (k) => speicher.get(k) ?? null, setItem: (k, v) => speicher.set(k, v), removeItem: (k) => speicher.delete(k) }
try {
const w = await zeigeNeu(fx)
await fx.klick(fx.finde(w, '#switch-buy')); assert.match(fx.text(w), /Bitte stimmen Sie den Vertragsbedingungen zu\./)
await fx.klick(fx.finde(w, '#switch-terms')); await fx.klick(fx.finde(w, '#switch-buy')); assert.match(fx.text(w), /Bitte bestätigen Sie den Sofortbeginn, sonst können wir den Wechsel nicht ausführen\./)
await fx.klick(fx.finde(w, '#switch-early')); speicher.set('kn-wechsel-funktion', JSON.stringify({ key: 'termine', projectId: 'p1' }))
await fx.klick(fx.finde(w, '#switch-buy')); await fx.ruhe()
assert.deepEqual(fx.fetchLog.find((a) => a.url === '/api/abo/switch').body, { acceptTerms: true, earlyStart: true, termsVersion: '2026-09-30-v5', prorationDate: 1760000000, amountDueCents: 3000, funktion: { key: 'termine', projectId: 'p1' } })
assert.equal(speicher.has('kn-wechsel-funktion'), false); assert.equal(fx.window.location.href, 'https://pay.stripe.com/x'); assert.match(fx.text(w), /Ihr Wechsel wartet auf die Zahlung\. Wir leiten Sie zur Zahlung weiter\./)
} finally { delete globalThis.sessionStorage }
const w = await zeige(fx, HOSTING(), meMit('privat'))
await fx.klick(fx.finde(w, '#switch-beginn'))
speicher.set('kn-wechsel-funktion', JSON.stringify({ key: 'termine', projectId: 'p1' }))
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.deepEqual(fx.fetchLog.find((a) => a.url === '/api/abo/switch').body, { acceptTerms: true, earlyStart: true, termsVersion: NEU, prorationDate: 1760000000, amountDueCents: 3000, funktion: { key: 'termine', projectId: 'p1' } })
assert.equal(speicher.has('kn-wechsel-funktion'), false)
assert.equal(fx.window.location.href, 'https://pay.stripe.test/x')
} finally {
delete globalThis.sessionStorage
}
}))
test('gemerkteFunktion: kaputte oder fremde Werte ergeben null', () => {
const wert = (v) => { globalThis.sessionStorage = { getItem: () => v }; try { return gemerkteFunktion() } finally { delete globalThis.sessionStorage } }
assert.deepEqual(wert('{"key":"shop","projectId":"p2"}'), { key: 'shop', projectId: 'p2' })
for (const v of ['kaputt', '{"key":"shop"}', '{"key":1,"projectId":"p"}', null]) assert.equal(wert(v), null)
assert.equal(gemerkteFunktion(), null) // ohne sessionStorage
})
const FUNKTION = { key: 'termine', projectId: 'p1' }
const WOHIN = (fx) => { fx.window.history.replaceState = (_s, _t, url) => { fx.window.location.hash = `#${String(url).split('#')[1] ?? ''}` }; fx.window.history.pushState = fx.window.history.replaceState }
for (const [name, gemerkt, antwort, nachgeladen, ziel] of [
@@ -44,36 +136,89 @@ for (const [name, gemerkt, antwort, nachgeladen, ziel] of [
]) {
test(`Wechsel ohne Zahlungsseite (${name}): Ziel ${ziel} (E14, C5)`, mit({
'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ body: { subscription: abo(antwort) } }),
'GET /api/abo': aboAntwort({ subscription: abo({ produkt: 'wartung', ...nachgeladen }) }),
'GET /api/abo': aboNeu({ subscription: abo({ produkt: 'wartung', ...nachgeladen }) }),
}, async (fx) => {
WOHIN(fx); const speicher = new Map(gemerkt ? [['kn-wechsel-funktion', JSON.stringify(FUNKTION)]] : [])
WOHIN(fx)
const speicher = new Map(gemerkt ? [['kn-wechsel-funktion', JSON.stringify(FUNKTION)]] : [])
globalThis.sessionStorage = { getItem: (k) => speicher.get(k) ?? null, setItem: (k, v) => speicher.set(k, v), removeItem: (k) => speicher.delete(k) }
try {
nimmHinweis()
const w = await zeigeNeu(fx); await fx.klick(fx.finde(w, '#switch-terms')); await fx.klick(fx.finde(w, '#switch-early')); await fx.klick(fx.finde(w, '#switch-buy')); await fx.ruhe()
assert.equal(fx.window.location.hash, ziel); assert.equal(speicher.has('kn-wechsel-funktion'), false)
const w = await zeige(fx, HOSTING(), meMit('unternehmen'))
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.equal(fx.window.location.hash, ziel)
assert.equal(speicher.has('kn-wechsel-funktion'), false)
assert.equal(nimmHinweis() !== '', ziel === '#vertraege') // bei #funktionen bleibt kein Hinweis für später liegen
assert.equal(fx.fetchLog.filter((a) => a.url === '/api/abo').length, gemerkt && !antwort.wechselFunktion ? 1 : 0) // höchstens ein Nachladen, nur mit gemerkter Funktion
} finally { delete globalThis.sessionStorage }
} finally {
delete globalThis.sessionStorage
}
}))
}
test('Wechsel: 409 lädt die Vorschau neu und behält die Meldung; Ansichtsmodus sperrt', mit({ 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ status: 409, body: { error: 'Betrag hat sich geändert.' } }) }, async (fx) => {
const w = await zeigeNeu(fx); await fx.klick(fx.finde(w, '#switch-terms')); await fx.klick(fx.finde(w, '#switch-early')); await fx.klick(fx.finde(w, '#switch-buy')); await fx.ruhe()
assert.match(fx.text(w), /Betrag hat sich geändert\./); assert.equal(fx.fetchLog.filter((a) => a.url === '/api/abo/switch/preview').length, 2)
const v = await zeigeNeu(fx, HOSTING, me({ viewAs: true })); assert.equal(fx.finde(v, '#switch-buy').hasAttribute('disabled'), true); assert.match(fx.text(v), /Im Ansichtsmodus nicht möglich\./)
test('Erfolgstexte in du: SEPA und Karte', mit({ 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ body: { subscription: abo({ switchPending: { type: 'wechsel' } }) } }) }, async (fx) => {
WOHIN(fx)
nimmHinweis()
const w = await zeige(fx, HOSTING(), meMit('unternehmen'))
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.equal(nimmHinweis(), 'Dein Wechsel ins Wartungs-Abo gilt ab sofort. Die Lastschrift wird noch eingezogen; wir bestätigen dir den Wechsel per E-Mail.')
fx.tabelle['POST /api/abo/switch'] = () => ({ body: { subscription: abo() } })
const v = await zeige(fx, HOSTING(), meMit('unternehmen'))
await fx.klick(fx.finde(v, '#switch-buy'))
await fx.ruhe()
assert.equal(nimmHinweis(), 'Dein Wechsel ins Wartungs-Abo ist abgeschlossen. Wir bestätigen ihn per E-Mail.')
}))
test('Wechsel: Vorschau-Fehler, hängende Bestellung nach pageshow, SEPA-Hinweis; im Ansichtsmodus geht kein POST raus', mit({
'POST /api/abo/switch/preview': () => ({ status: 500, body: { error: 'Vorschau kaputt.' } }) }, async (fx) => {
const w = await zeigeNeu(fx); assert.match(fx.text(w), /Vorschau kaputt\./); assert.equal(fx.finde(w, '#switch-buy').hasAttribute('disabled'), true)
fx.tabelle['POST /api/abo/switch/preview'] = VORSCHAU; fx.tabelle['POST /api/abo/switch'] = { paymentUrl: 'https://pay.stripe.com/y', subscription: abo() }
const v = await zeigeNeu(fx); await fx.klick(fx.finde(v, '#switch-terms')); await fx.klick(fx.finde(v, '#switch-early')); await fx.klick(fx.finde(v, '#switch-buy')); await fx.ruhe()
test('409 lädt die Vorschau neu und behält die Meldung; Ansichtsmodus sperrt Knopf und Häkchen', mit({ 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ status: 409, body: { error: 'Betrag hat sich geändert.' } }) }, async (fx) => {
const w = await zeige(fx, HOSTING(), meMit('privat'))
await fx.klick(fx.finde(w, '#switch-beginn'))
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.match(fx.text(w), /Betrag hat sich geändert\./)
assert.equal(fx.fetchLog.filter((a) => a.url === '/api/abo/switch/preview').length, 2)
assert.equal(fx.finde(w, '#switch-beginn').checked, true, 'das Häkchen bleibt nach dem Neuzeichnen')
const v = await zeige(fx, HOSTING(), meMit('privat', { viewAs: true }))
assert.equal(fx.finde(v, '#switch-buy').hasAttribute('disabled'), true)
assert.equal(fx.finde(v, '#switch-beginn').hasAttribute('disabled'), true)
assert.match(fx.text(v), /Im Ansichtsmodus nicht möglich\./)
}))
test('Vorschau-Fehler, hängende Bestellung nach pageshow; im Ansichtsmodus geht kein POST raus', mit({ 'POST /api/abo/switch/preview': () => ({ status: 500, body: { error: 'Vorschau kaputt.' } }) }, async (fx) => {
const w = await zeige(fx, HOSTING(), meMit('unternehmen'))
assert.match(fx.text(w), /Vorschau kaputt\./)
assert.equal(fx.finde(w, '#switch-buy').hasAttribute('disabled'), true)
fx.tabelle['POST /api/abo/switch/preview'] = VORSCHAU
fx.tabelle['POST /api/abo/switch'] = { paymentUrl: 'https://pay.stripe.test/y', subscription: abo() }
const v = await zeige(fx, HOSTING(), meMit('unternehmen'))
await fx.klick(fx.finde(v, '#switch-buy'))
await fx.ruhe()
assert.equal(fx.finde(v, '#switch-buy').hasAttribute('disabled'), true) // wartet auf die Zahlung
fx.window.dispatchEvent({ type: 'pageshow', persisted: true }); await fx.ruhe()
assert.equal(fx.finde(v, '#switch-buy').hasAttribute('disabled'), false); assert.equal(fx.finde(v, '#switch-buy').textContent, 'Zahlungspflichtig bestellen')
const vorher = fx.fetchLog.length; const a = await zeigeNeu(fx, HOSTING, me({ viewAs: true })); await fx.klick(fx.finde(a, '#switch-buy'))
fx.window.dispatchEvent({ type: 'pageshow', persisted: true })
await fx.ruhe()
assert.equal(fx.finde(v, '#switch-buy').hasAttribute('disabled'), false)
assert.equal(fx.finde(v, '#switch-buy').textContent, 'Zahlungspflichtig bestellen')
const vorher = fx.fetchLog.length
const a = await zeige(fx, HOSTING(), meMit('unternehmen', { viewAs: true }))
await fx.klick(fx.finde(a, '#switch-buy'))
assert.deepEqual(fx.fetchLog.slice(vorher).filter((x) => x.url === '/api/abo/switch'), [])
}))
test('Wechsel: unsichere Zahlungsadresse wird nicht geöffnet und nicht als Erfolg gezeigt', mit({ 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ body: { paymentUrl: 'javascript:alert(1)', subscription: abo() } }) }, async (fx) => {
nimmHinweis(); const w = await zeigeNeu(fx); await fx.klick(fx.finde(w, '#switch-terms')); await fx.klick(fx.finde(w, '#switch-early')); await fx.klick(fx.finde(w, '#switch-buy')); await fx.ruhe()
assert.notEqual(fx.window.location.href, 'javascript:alert(1)'); assert.match(fx.text(w), /Die Zahlungsseite konnte nicht geöffnet werden\./); assert.equal(nimmHinweis(), '')
test('Unsichere Zahlungsadresse wird nicht geöffnet und nicht als Erfolg gezeigt', mit({ 'POST /api/abo/switch/preview': VORSCHAU, 'POST /api/abo/switch': () => ({ body: { paymentUrl: 'javascript:alert(1)', subscription: abo() } }) }, async (fx) => {
nimmHinweis()
const w = await zeige(fx, HOSTING(), meMit('unternehmen'))
await fx.klick(fx.finde(w, '#switch-buy'))
await fx.ruhe()
assert.notEqual(fx.window.location.href, 'javascript:alert(1)')
assert.match(fx.text(w), /Die Zahlungsseite konnte nicht geöffnet werden\./)
assert.equal(nimmHinweis(), '')
}))
test('Quelltext: kein Sie, keine Klappe, alte Ids weg, Body ohne kundenart', () => {
const q = readFileSync(new URL('../public/neu/ansicht-wechsel.js', import.meta.url), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '')
assert.doesNotMatch(q, /\b(Sie|Ihr(e[nmrs]?)?|Ihnen)\b/)
assert.doesNotMatch(q, /details|dialog|innerHTML|switch-terms|switch-early/)
const aufruf = q.slice(q.indexOf('const body = {'), q.indexOf("api('/api/abo/switch'"))
assert.ok(aufruf.includes('acceptTerms: true'), 'der Body der Bestellung ist gefunden')
assert.doesNotMatch(aufruf, /startChoice|kundenart|unternehmer/)
})
+8
View File
@@ -52,6 +52,14 @@ test('baueLinkzeile, baueKundenartZeile, baueBlock', () =>
test('hatWortlaut', () => {
assert.equal(hatWortlaut(aboNeu()), true)
for (const d of [null, undefined, {}, { bestelltexte: {} }, { bestelltexte: { status: 'entwurf', knopf: 'x' } }, { bestelltexte: { status: 'entwurf', abo: { linkzeile: { text: 'a' } } } }]) assert.equal(hatWortlaut(d), false)
for (const art of ['abo', 'wechsel', 'speicher', 'gutschrift']) assert.equal(hatWortlaut(aboNeu(), art), true, art)
// jede Seite prüft ihre eigenen Sätze
const ohne = (teil) => { const d = aboNeu(); delete d.bestelltexte[teil]; return d }
assert.deepEqual(['abo', 'wechsel', 'speicher', 'gutschrift'].map((art) => hatWortlaut(ohne(art), art)), [false, false, false, false])
assert.equal(hatWortlaut(ohne('wechsel'), 'abo'), true)
const ohneGesperrt = aboNeu()
ohneGesperrt.bestelltexte.wechsel.gesperrt = ''
assert.equal(hatWortlaut(ohneGesperrt, 'wechsel'), false)
})
test('Quelltext: keine HTML-Einsetzung, Du-Form, keine h1', () => {