Kundenansicht neu E-Fix F1: Kerninfo und Knopf der Bestellseiten passen in den nutzbaren Bereich (390x844, 375x667)

Die Messung im Werkzeug nahm innerHeight; nutzbar ist am Handy nur der Bereich zwischen Kopf und fester Leiste (735 px bei 844, 558 px bei 667).
Gemessen vor der Korrektur (Blockanfang bis Knopfunterkante, 375x667): Abo bestellen privat 799 px, Wechsel privat 888 px, Zusatzspeicher 567 px.

- Block knapp: Leistung als eine Zeile mit Link "Leistungen ansehen" auf die Leistungsbeschreibung, Preis, Fällig, Beginn, Laufzeit und Zahlung in je ein bis zwei Zeilen.
- Die ausführlichen Sätze stehen unter dem Knopf und der Kundenart-Zeile (baueEinzelheiten), ohne Klappe.
- Handy: Beschriftung läuft in der Zeile mit, kleinere Überschrift, knappere Abstände.
- Die Wortlaute des Blocks sind gekürzt und gehören in die Rechtsrunde.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 21:25:48 +00:00
1 parent 779320c080
commit d4050f870a
8 files changed
+148 -41

No files matched your search

+25 -12
View File
@@ -8,7 +8,7 @@ import { NEU, TERMS_URL, meMit, aboNeu } from './support/knBestellDaten.js'
const route = (produkt) => ({ bereich: 'vertraege', etage: 'bestellen', produkt, query: '' })
// fmtEuro setzt ein geschütztes Leerzeichen vor das Euro-Zeichen
const eur = (text) => text.replaceAll(' €', '\u00a0€')
const IDS = ['abo-block', 'abo-linkzeile', 'abo-beginn', 'abo-error', 'abo-buy', 'abo-kundenart']
const IDS = ['abo-block', 'abo-linkzeile', 'abo-beginn', 'abo-error', 'abo-buy', 'abo-kundenart', 'abo-einzelheiten']
/** Seite zeigen; die Titel, die die Ansicht meldet (Ereignis kn:titel), sammelt fx.titel. */
async function zeige(fx, daten, meDaten, produkt = 'wartung') {
@@ -24,11 +24,11 @@ const reihe = (fx, w) => fx.alle(fx.finde(w, '#abo-order'), (el) => IDS.includes
test('Betrieb: Block, Linkzeile, Knopf, Kundenart-Zeile in dieser Reihenfolge, ohne Häkchen und ohne Klappe', mit({}, async (fx) => {
const w = await zeige(fx, aboNeu(), meMit('unternehmen'))
assert.deepEqual(reihe(fx, w), ['abo-block', 'abo-linkzeile', 'abo-error', 'abo-buy', 'abo-kundenart'])
assert.deepEqual(reihe(fx, w), ['abo-block', 'abo-linkzeile', 'abo-error', 'abo-buy', 'abo-kundenart', 'abo-einzelheiten'])
assert.equal(fx.finde(w, '#abo-buy').textContent, 'Zahlungspflichtig bestellen')
assert.equal(fx.alle(w, 'details, dialog, input[type="radio"], input[type="checkbox"]').length, 0)
const t = fx.text(fx.finde(w, '#abo-block'))
for (const s of ['Leistung', 'Preis', 'Fällig', 'Beginn', 'Laufzeit', 'Zahlung', '50,00', 'gemäß § 19 UStG ohne Umsatzsteuer', 'Heute fällig: 50,00']) assert.ok(t.includes(s), s)
for (const s of ['Leistung', 'Preis', 'Fällig', 'Beginn', 'Laufzeit', 'Zahlung', '50,00', 'gemäß § 19 UStG ohne Umsatzsteuer', 'heute 50,00']) assert.ok(t.includes(s), s)
// die Zeilen „Anbieter“ und „Abrechnung“ entfallen (N37); das Wort steht nur im Satz zur Kündigung („Abrechnungsmonats“)
assert.deepEqual(fx.alle(fx.finde(w, '#abo-block'), 'dt').map((e) => fx.text(e)), ['Leistung', 'Preis', 'Fällig', 'Beginn', 'Laufzeit', 'Zahlung'])
assert.equal(fx.text(fx.finde(w, '#abo-start-summary')), 'sofort')
@@ -37,14 +37,27 @@ test('Betrieb: Block, Linkzeile, Knopf, Kundenart-Zeile in dieser Reihenfolge, o
assert.equal(fx.text(fx.finde(w, '#abo-linkzeile')), 'Es gelten die Vertragsbedingungen mit Leistungsbeschreibung, Auftragsverarbeitung und Widerrufsbelehrung (Fassung ' + NEU + '). Alles kommt danach auch als PDF per Mail. Datenschutz')
}))
test('Block: feste Zeilentexte (Preis, Laufzeit, Zahlung)', mit({}, async (fx) => {
test('Block: knappe Zeilentexte über dem Knopf, die ausführlichen Sätze unter dem Knopf (F1)', mit({}, async (fx) => {
const w = await zeige(fx, aboNeu(), meMit('unternehmen'))
const zeilen = fx.alle(fx.finde(w, '#abo-block'), '.kn-block-zeile').map((z) => [fx.text(fx.finde(z, 'dt')), fx.text(fx.finde(z, 'dd'))])
assert.deepEqual(zeilen.map(([l]) => l), ['Leistung', 'Preis', 'Fällig', 'Beginn', 'Laufzeit', 'Zahlung'])
assert.deepEqual(zeilen[0], ['Leistung', 'WEBklar Wartungs-Abo: Wartung'])
assert.deepEqual(zeilen[1], ['Preis', eur('50,00 € pro Monat (Gesamtpreis, gemäß § 19 UStG ohne Umsatzsteuer), keine weiteren Kosten')])
assert.deepEqual(zeilen[4], ['Laufzeit', 'Mindestlaufzeit 12 Monate ab Leistungsbeginn, kündbar zum Ende der Mindestlaufzeit bis einen Monat vorher; danach jederzeit zum Ende des Abrechnungsmonats kündbar'])
assert.deepEqual(zeilen[5], ['Zahlung', 'Kreditkarte oder SEPA-Lastschrift über Stripe; die Zahlungsart hinterlegst du im nächsten Schritt, bis zum Abschluss dort kannst du abbrechen'])
// Leistung: eine kurze Zeile mit Link auf die Leistungsbeschreibung B (Wartung), kein Aufzählungstext
assert.deepEqual(zeilen[0], ['Leistung', 'Wartungs-Abo · Leistungen ansehen'])
assert.deepEqual([fx.finde(fx.finde(w, '#abo-block'), 'a').getAttribute('href'), fx.finde(fx.finde(w, '#abo-block'), 'a').getAttribute('target')], [`${TERMS_URL}#wartung`, '_blank'])
assert.deepEqual(zeilen[1], ['Preis', eur('50,00 € pro Monat (Gesamtpreis, gemäß § 19 UStG ohne Umsatzsteuer)')])
assert.deepEqual(zeilen[2], ['Fällig', eur('heute 50,00 €')])
assert.deepEqual(zeilen[4], ['Laufzeit', 'Mindestlaufzeit 12 Monate, kündbar bis 1 Monat vor Ende; danach monatlich'])
assert.deepEqual(zeilen[5], ['Zahlung', 'Karte oder SEPA über Stripe'])
// jede Zeile höchstens 110 Zeichen: sonst passt die Kerninfo am Handy nicht mehr auf den Bildschirm
for (const [l, t] of zeilen) assert.ok(t.length <= 110, `${l}: ${t.length} Zeichen`)
// unter dem Knopf und der Kundenart-Zeile: die ausführlichen Sätze, ohne Klappe
const ein = fx.finde(w, '#abo-einzelheiten')
assert.equal(fx.alle(w, '#abo-order > *').map((e) => e.id).filter(Boolean).at(-1), 'abo-einzelheiten')
const z2 = fx.alle(ein, '.kn-block-zeile').map((z) => [fx.text(fx.finde(z, 'dt')), fx.text(fx.finde(z, 'dd'))])
assert.deepEqual(z2.map(([l]) => l), ['Laufzeit', 'Zahlung', 'Kosten'])
assert.equal(z2[0][1], 'Mindestlaufzeit 12 Monate ab Leistungsbeginn, kündbar zum Ende der Mindestlaufzeit bis einen Monat vorher; danach jederzeit zum Ende des Abrechnungsmonats kündbar')
assert.equal(z2[1][1], 'Kreditkarte oder SEPA-Lastschrift über Stripe; die Zahlungsart hinterlegst du im nächsten Schritt, bis zum Abschluss dort kannst du abbrechen')
assert.equal(z2[2][1], 'keine weiteren Kosten')
}))
test('Titel: Produktname als Ereignis, keine eigene h1 (P2, P1 VF11)', mit({}, async (fx) => {
@@ -65,11 +78,11 @@ test('Betrieb: Body ohne earlyStart, lateStartAt, startChoice und Kundenart', mi
test('Privat und leer: ein Häkchen aus dem Wortlaut, ungehakt nach der Frist, gehakt sofort', mit({ 'POST /api/abo/checkout': { url: 'https://checkout.stripe.test/x' } }, async (fx) => {
for (const m of [meMit('privat'), meMit('')]) {
const w = await zeige(fx, aboNeu(), m)
assert.deepEqual(reihe(fx, w), ['abo-block', 'abo-linkzeile', 'abo-beginn', 'abo-error', 'abo-buy', 'abo-kundenart'])
assert.deepEqual(reihe(fx, w), ['abo-block', 'abo-linkzeile', 'abo-beginn', 'abo-error', 'abo-buy', 'abo-kundenart', 'abo-einzelheiten'])
assert.equal(fx.finde(w, '#abo-beginn').checked, false)
assert.equal(fx.text(fx.finde(w, '#abo-beginn-text')), aboNeu().bestelltexte.abo.haken)
assert.ok(fx.text(fx.finde(w, '#abo-start-summary')).startsWith('nach Ablauf der 14-tägigen Widerrufsfrist (am '))
assert.ok(fx.text(fx.finde(w, '#abo-due-summary')).startsWith('Erste Abbuchung am '))
assert.ok(fx.text(fx.finde(w, '#abo-due-summary')).startsWith('erst am '))
assert.ok(fx.text(fx.finde(w, '#abo-kundenart')).startsWith('Du bestellst privat · '))
await fx.klick(fx.finde(w, '#abo-buy'))
await fx.ruhe()
@@ -77,7 +90,7 @@ test('Privat und leer: ein Häkchen aus dem Wortlaut, ungehakt nach der Frist, g
const v = await zeige(fx, aboNeu(), m)
await fx.klick(fx.finde(v, '#abo-beginn'))
assert.ok(fx.text(fx.finde(v, '#abo-start-summary')).startsWith('sofort, auf deinen ausdrücklichen Wunsch'))
assert.ok(fx.text(fx.finde(v, '#abo-due-summary')).startsWith('Heute fällig: '))
assert.ok(fx.text(fx.finde(v, '#abo-due-summary')).startsWith('heute '))
await fx.klick(fx.finde(v, '#abo-buy'))
await fx.ruhe()
assert.equal(fx.fetchLog.at(-1).body.earlyStart, true)
@@ -101,7 +114,7 @@ test('Angebot: Angebotsnummer im Body, Text in Abschnitt und Preiszeile', mit({}
assert.ok(fx.text(fx.finde(w, '#abo-angebot')).includes(angebot().text))
assert.ok(fx.text(fx.finde(w, '#abo-block')).includes(`individuelles Angebot: ${angebot().text}`))
assert.ok(fx.text(fx.finde(w, '#abo-block')).includes(eur('25,00 € pro Monat für die ersten 2 Monate, danach 50,00 € pro Monat')))
assert.ok(fx.text(fx.finde(w, '#abo-due-summary')).startsWith('Heute fällig: 25,00'))
assert.ok(fx.text(fx.finde(w, '#abo-due-summary')).startsWith('heute 25,00'))
await fx.klick(fx.finde(w, '#abo-buy'))
await fx.ruhe()
assert.equal(fx.fetchLog.at(-1).body.offerId, angebot().id)