Files
Webklar-Kundenbereich/test/knAnsichtAbo.test.js
T
2026-10-16 17:02:10 +00:00

55 lines
6.5 KiB
JavaScript

import { test } from 'node:test'
import assert from 'node:assert/strict'
import { zeigeAbo, aboZustand, aboZeile, laufzeitText } from '../public/neu/vertraege-abo.js'
import { mit, me, abo, aboAntwort, angebot, neueWurzel } from './support/knDaten.js'
const WARTUNG = aboAntwort({ subscription: abo({ priceAmount: 5000, currentPeriodEnd: '2026-11-16T00:00:00.000Z', minTermEnd: '2099-06-01T00:00:00.000Z', termsUrl: '/abo-bedingungen.html', termsPdfUrl: '/WEBklar-Abo-Vertragsunterlagen.pdf' }) })
const zeige = async (fx, daten, m = me()) => { const b = neueWurzel(fx); await zeigeAbo(b, { daten, me: m }); await fx.ruhe(); return b }
const SRV = { 'GET /api/abo/takeover-credits': { requests: [{ status: 'rueckfrage' }, { status: 'offen' }], limits: {} } }
test('aboZustand', () => {
assert.deepEqual([aboAntwort(), aboAntwort({ subscription: abo({ active: false }) }), WARTUNG, aboAntwort({ subscription: abo({ cancelAtPeriodEnd: true }) })].map(aboZustand), ['ohne', 'beendet', 'laeuft', 'gekuendigt'])
})
test('Abo Wartung: Vertrag, Preis, Laufzeit, Bedingungen, Gutschrift-Einstieg mit Rückfragen', mit(SRV, async (fx) => {
const b = await zeige(fx, WARTUNG); const t = fx.text(b)
for (const s of ['Mein Vertrag', 'aktiv', 'Wartungs-Abo', 'Gemäß § 19 UStG ohne Umsatzsteuer.', 'nächste Abbuchung 16.11.2026', 'Mindestlaufzeit bis 01.06.2099. Kündigung frühestens zu diesem Termin, mit einem Monat Frist.']) assert.ok(t.includes(s), s)
assert.equal(fx.finde(b, 'a[href="/WEBklar-Abo-Vertragsunterlagen.pdf"]').textContent, 'als PDF')
assert.equal(fx.finde(b, 'a[href="#gutschrift"][data-view="takeover"] [data-badge]').textContent, '1')
}))
test('Abo Hosting: Wechsel-Einstieg; wartende Zahlung nur mit sicherer Adresse; gekündigt ohne Wechsel-Karte', mit(SRV, async (fx) => {
const hosting = (o) => aboAntwort({ subscription: abo({ produkt: 'hosting', canSwitch: true, ...o }) })
const w = fx.finde(await zeige(fx, hosting({})), 'a[data-view="wechsel"]'); assert.deepEqual([w.textContent, w.getAttribute('href')], ['Zum Wartungs-Abo wechseln', '#wechsel'])
const sicher = await zeige(fx, hosting({ switchPending: { since: 'x', paymentUrl: 'https://pay.stripe.com/x' } })); assert.equal(fx.finde(sicher, 'a[href="https://pay.stripe.com/x"]').textContent, 'Jetzt bezahlen')
const unsicher = await zeige(fx, hosting({ switchPending: { since: 'x', paymentUrl: 'javascript:alert(1)' } })); assert.match(fx.text(unsicher), /Schreib uns gern im Chat, wenn du Hilfe brauchst\./)
const gekuendigt = await zeige(fx, hosting({ cancelAtPeriodEnd: true })); assert.equal(fx.finde(gekuendigt, 'a[data-view="wechsel"]'), null); assert.match(fx.text(gekuendigt), /Dein Abo ist gekündigt\. Bitte schreib uns im Chat, wenn du zum Wartungs-Abo wechseln möchtest\./)
}))
test('Zahlungsproblem: Knopf öffnet das Stripe-Portal; Widerruf nur in der Frist; Ansichtsmodus sperrt', mit({ ...SRV, 'POST /api/abo/portal': { url: 'https://billing.stripe.com/x' } }, async (fx) => {
const daten = aboAntwort({ subscription: abo({ paymentProblem: true, withdrawalOpen: true, withdrawalUntil: '2026-10-17T21:59:00.000Z' }) })
const b = await zeige(fx, daten); assert.match(fx.text(b), /Bitte aktualisiere deine Zahlungsart, damit deine Website online bleibt\./); assert.match(fx.finde(b, 'a[href="/widerrufen.html"]').textContent, /^Vertrag widerrufen · bis 17\.10\./)
await fx.klick(fx.finde(b, (e) => e.textContent === 'Zahlungsart aktualisieren')); assert.equal(fx.window.location.href, 'https://billing.stripe.com/x')
const ansicht = await zeige(fx, daten, me({ viewAs: true })); assert.equal(fx.finde(ansicht, (e) => e.textContent === 'Zahlungsart aktualisieren').hasAttribute('disabled'), true)
assert.equal(fx.finde(await zeige(fx, WARTUNG), 'a[href="/widerrufen.html"]'), null)
}))
test('Ohne Abo: zwei Produkte mit Link zur Bestellung, nicht verfügbar sperrt, beendet sagt es', mit(SRV, async (fx) => {
const b = await zeige(fx, aboAntwort()); assert.deepEqual(['hosting', 'wartung'].map((k) => fx.finde(b, `[data-produkt="${k}"] a`).getAttribute('href')), ['#bestellen-hosting', '#bestellen-wartung'])
assert.match(fx.text(b), /20,00 €/)
const aus = await zeige(fx, aboAntwort({ available: false })); assert.equal(fx.finde(aus, '[data-produkt="hosting"] a').getAttribute('aria-disabled'), 'true'); assert.match(fx.text(aus), /schreib uns gern im Chat\./)
assert.match(fx.text(await zeige(fx, aboAntwort({ subscription: abo({ active: false }) }))), /Dein bisheriges Abo ist beendet\. Du kannst jederzeit ein neues abschließen\./)
}))
test('Abo: Ausfall der Rückfragen-Abfrage lässt den Einstieg stehen', mit({ 'GET /api/abo/takeover-credits': () => ({ status: 500, body: { error: 'x' } }) }, async (fx) => {
const b = await zeige(fx, WARTUNG); assert.ok(fx.finde(b, 'a[href="#gutschrift"]')); assert.equal(fx.finde(b, '[data-badge]'), null)
}))
test('Texte aus app.js: Zeile und Laufzeit', () => {
assert.equal(aboZeile(abo({ cancelAtPeriodEnd: true, cancelAt: '2026-12-01T00:00:00.000Z' })), 'Leistungen bis 01.12.2026')
assert.equal(aboZeile(abo({ serviceStartsAt: '2026-10-30T00:00:00.000Z' })), 'Beginn und erste Abbuchung am 30.10.2026')
assert.equal(laufzeitText(abo({ cancelAtPeriodEnd: true, currentPeriodEnd: '2026-12-01T00:00:00.000Z' })), 'Gekündigt zum 01.12.2026. Bis dahin bleiben alle Leistungen verfügbar.')
assert.equal(laufzeitText(abo({ minTermEnd: '2000-01-01T00:00:00.000Z' })), 'Monatlich kündbar zum Ende des Abrechnungsmonats.')
})
test('Ohne Abo: Angebot mit Etikett und Gültigkeit; Fußsatz mit Link; Zusatzspeicher und Beginn nach Frist beim laufenden Abo', mit(SRV, async (fx) => {
const b = await zeige(fx, aboAntwort({ offers: { hosting: null, wartung: angebot({ text: 'Erste 2 Monate je 25,00 €', validUntil: '2026-11-30T00:00:00.000Z' }) } }))
assert.match(fx.text(fx.finde(b, '[data-produkt="wartung"]')), /Dein persönliches AngebotErste 2 Monate je 25,00 € · gültig bis 30\.11\.2026/)
assert.doesNotMatch(fx.text(fx.finde(b, '[data-produkt="hosting"]')), /Dein persönliches Angebot/)
assert.equal(fx.finde(b, 'a[href="/abo-bedingungen.html"]').textContent, 'Vertragsbedingungen'); assert.match(fx.text(b), /Alle Preise gemäß § 19 UStG ohne Umsatzsteuer\. Es gelten die Vertragsbedingungen\./)
const l = await zeige(fx, aboAntwort({ subscription: abo({ storage: { units: 2, pendingSetup: false, pendingReduction: null }, serviceStartsAt: '2026-10-30T00:00:00.000Z' }) }))
assert.match(fx.text(l), /E-Mail-Speicher15 GB \(2 Zusatzpakete\)/); assert.match(fx.text(l), /Wie gewählt beginnen wir nach Ablauf der Widerrufsfrist am 30\.10\.2026\. Dann wird auch zum ersten Mal abgebucht\./)
}))