Shop Review B I-2, I-3: Gewaehrleistungskasten vor der Zusammenfassung, AGB-Hinweis ueber dem Bestellknopf

Die amtliche Gewaehrleistungsgrafik steht in hervorgehobenem Kasten mit Ueberschrift vor der
Zusammenfassung der Kasse (hoechstens 420 px breit, sofort geladen, Vergroessern oeffnet sie in
einem mit Esc und Knopf schliessbaren Dialog). Direkt ueber "Zahlungspflichtig bestellen" steht
"Es gelten unsere AGB. Informationen zu Ihrem Widerrufsrecht finden Sie in der
Widerrufsbelehrung." mit Links auf beide Texte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 09:47:28 +00:00
1 parent 72fb37edcc
commit 7104f97feb
2 files changed
+88 -17

No files matched your search

+55 -16
View File
@@ -113,8 +113,13 @@
'.wks-summen .wks-gesamt{font-weight:700;font-size:1.1rem;border-top:1px solid var(--wks-i-rand);padding-top:.35rem}',
'.wks-zusammen{margin:0 0 1rem;display:grid;grid-template-columns:max-content 1fr;gap:.35rem 1rem}',
'.wks-zusammen dt{font-weight:600}.wks-zusammen dd{margin:0;overflow-wrap:anywhere;white-space:pre-line}',
'.wks-gewaehr{margin:.75rem 0}',
'.wks-gewaehr img{display:block;max-width:100%;height:auto;border:1px solid var(--wks-i-rand);border-radius:calc(var(--wks-i-radius) * .7)}',
'.wks-gewaehr{margin:1.25rem 0;padding:.9rem 1rem;border:2px solid var(--wks-i-akzent);border-radius:var(--wks-i-radius);background:var(--wks-i-weich)}',
'.wks-gewaehr h4{font-size:1rem;margin:0 0 .6rem}',
'.wks-gewaehr img{display:block;width:100%;max-width:420px;height:auto;margin:0 0 .6rem;border:1px solid var(--wks-i-rand);border-radius:calc(var(--wks-i-radius) * .7);background:#fff}',
'.wks-gewaehr>:last-child{margin-bottom:0}',
'.wks-agb-hinweis{margin:0 0 .75rem}',
'dialog.wks-dialog.wks-dialog-gross{width:min(64rem,calc(100vw - 1.5rem))}',
'.wks-dialog-bild{display:block;max-width:100%;height:auto;margin:0 auto 1rem;background:#fff}',
'.wks-links{display:flex;flex-wrap:wrap;gap:.25rem 1.25rem;margin:0 0 .75rem}',
'.wks-box{margin:0 0 1rem;padding:.75rem 1rem;border-radius:var(--wks-i-radius);background:var(--wks-i-weich)}',
'.wks-box h4{font-size:1rem;margin:0 0 .25rem}',
@@ -645,9 +650,12 @@
dlg = el('dialog', 'wks-dialog')
dlg.addEventListener('click', function (e) { if (e.target === dlg) dialogSchliessen() })
dlg.addEventListener('close', function () { if (dlgAusloeser && dlgAusloeser.focus) dlgAusloeser.focus() })
// Esc schliesst auch dort, wo showModal fehlt (der Browser erledigt es sonst selbst)
dlg.addEventListener('keydown', function (e) { if (e.key === 'Escape' || e.key === 'Esc') { e.preventDefault(); dialogSchliessen() } })
root.appendChild(dlg)
}
dlgAusloeser = ausloeser || null
dlg.className = 'wks-dialog' + (bloecke.some(function (b) { return !!b.bild }) ? ' wks-dialog-gross' : '')
dlg.textContent = ''
var innen = el('div', 'wks-dialog-innen')
var zu = knopf('wks-schliessen', '×', dialogSchliessen)
@@ -661,6 +669,14 @@
text.setAttribute('role', 'region')
text.setAttribute('aria-label', ueberschrift)
bloecke.forEach(function (b) {
if (b.bild) {
var gross = el('img', 'wks-dialog-bild')
gross.src = b.bild
gross.alt = nichtLeer(b.text) ? b.text : ''
gross.decoding = 'async'
text.appendChild(gross)
return
}
if (!nichtLeer(b.text)) return
if (b.titel) text.appendChild(el('h4', 'wks-untertitel', b.titel))
text.appendChild(absaetze(b.text, ''))
@@ -705,6 +721,31 @@
dialogOeffnen('Versand und Zahlung', bloecke, ausloeser)
}
// Hinweis auf das gesetzliche Gewaehrleistungsrecht (Art. 246a § 1 Abs. 1 S. 1 Nr. 11 EGBGB): amtliche Grafik in hervorgehobenem
// Kasten vor der Zusammenfassung der Kasse, sofort geladen, mit dem woertlichen Text als Alternativtext und einer Vergroesserung
function gewaehrKasten () {
var g = gewaehr()
if (!g) return null
var kasten = el('section', 'wks-gewaehr')
kasten.setAttribute('aria-label', 'Ihre gesetzlichen Gewährleistungsrechte')
kasten.appendChild(el('h4', '', 'Ihre gesetzlichen Gewährleistungsrechte'))
var bildUrl = httpsUrl(g.bild)
if (bildUrl) {
var img = el('img')
img.src = bildUrl
img.alt = g.text
img.loading = 'eager'
img.decoding = 'async'
kasten.appendChild(img)
kasten.appendChild(knopf('wks-btn wks-btn-sek', 'Vergrößern', function (e) {
dialogOeffnen('Ihre gesetzlichen Gewährleistungsrechte', [{ bild: bildUrl, text: g.text }], e.currentTarget)
}))
} else {
kasten.appendChild(absaetze(g.text, 'wks-text'))
}
return kasten
}
// ------------------------------------------------------------ Formularhelfer
function honigfeld () {
@@ -1258,6 +1299,10 @@
landSichtbar()
landSel.addEventListener('change', function () { S.land = landSel.value; pruefe() })
// Gewaehrleistungshinweis: hervorgehoben vor der Zusammenfassung (wird nicht mit der Zusammenfassung neu aufgebaut)
var gkasten = gewaehrKasten()
if (gkasten) form.appendChild(gkasten)
// Pflichtinformationen: stehen unmittelbar ueber dem Knopf und kommen zum grossen Teil vom Server (/pruefen)
var pflicht = el('div', 'wks-pflicht')
form.appendChild(pflicht)
@@ -1265,6 +1310,14 @@
form.appendChild(honigfeld())
var fehlerBox = el('div', 'wks-fehlerbox')
form.appendChild(fehlerBox)
// Einbeziehung der AGB (§ 305 Abs. 2 BGB): ausdruecklicher Hinweis unmittelbar ueber dem Knopf, beide Texte oeffnen sich im Dialog
var agbHinweis = el('p', 'wks-agb-hinweis')
agbHinweis.appendChild(document.createTextNode('Es gelten unsere '))
agbHinweis.appendChild(knopf('wks-link', 'AGB', function (e) { zeigeAgb(e.currentTarget) }))
agbHinweis.appendChild(document.createTextNode('. Informationen zu Ihrem Widerrufsrecht finden Sie in der '))
agbHinweis.appendChild(knopf('wks-link', 'Widerrufsbelehrung', function (e) { zeigeBelehrung(e.currentTarget) }))
agbHinweis.appendChild(document.createTextNode('.'))
form.appendChild(agbHinweis)
var senden = el('button', 'wks-btn', 'Zahlungspflichtig bestellen')
senden.type = 'submit'
senden.disabled = true
@@ -1333,20 +1386,6 @@
links.appendChild(knopf('wks-link', 'Versand & Zahlung lesen', function (e) { zeigeVersand(e.currentTarget) }))
pflicht.appendChild(links)
var g = gewaehr()
var bildUrl = g ? httpsUrl(g.bild) : ''
var gbox = el('div', 'wks-gewaehr')
if (bildUrl) {
var img = el('img')
img.src = bildUrl
img.alt = g.text
img.loading = 'lazy'
img.decoding = 'async'
gbox.appendChild(img)
} else if (g) {
gbox.appendChild(absaetze(g.text, 'wks-text'))
}
pflicht.appendChild(gbox)
pflicht.appendChild(el('p', '', 'Name, Lieferadresse und Zahlung geben Sie im nächsten Schritt bei unserem Zahlungsdienstleister Stripe ein.'))
senden.disabled = S.sendet
}
+33 -1
View File
@@ -88,7 +88,7 @@ test('Pflichttexte: Knopf der Kasse, Widerrufsfunktion, Gewaehrleistungsbild, St
'Der Shop ist gerade geschlossen.', 'Shop-Technik: WEBklar', 'Lieferung nach: ', 'Abholung möglich', 'Zahlung: ',
"'AGB'", "'Widerrufsbelehrung'", "'Versand & Zahlung'", "'Impressum'", "'Datenschutz'", 'zzgl. Versand',
'Vielen Dank für Ihre Bestellung', 'bei uns eingegangen. Eine Eingangsbestätigung haben wir Ihnen per E-Mail geschickt.',
'rel = \'noopener noreferrer\'', 'img.alt = g.text', "img.loading = 'lazy'", 'gewaehrleistung',
'rel = \'noopener noreferrer\'', 'img.alt = g.text', "img.loading = 'eager'", 'gewaehrleistung',
'wk_bestellung', 'wk_t', 'wk_abbruch', 'replaceState', 'kontakt_url', 'formToken', 'rueckUrl: location.href', 'nurWiderruf',
'data-webklar-shop', 'data-api', 'data-ansicht', "'ansicht'", 'aria-live', 'aria-pressed', 'tabIndex = -1', 'showModal',
]) {
@@ -100,6 +100,38 @@ test('Pflichttexte: Knopf der Kasse, Widerrufsfunktion, Gewaehrleistungsbild, St
assert.ok(OHNE_KOMMENTARE.includes("knopf('wks-btn wks-btn-sek', 'Vertrag widerrufen'"), 'Widerruf im Fuss ist ein Knopf')
})
test('I-2: Gewährleistungsgrafik steht hervorgehoben vor der Zusammenfassung, höchstens 420 px, sofort geladen, mit Vergrößern-Dialog', () => {
assert.ok(OHNE_KOMMENTARE.includes("'Ihre gesetzlichen Gewährleistungsrechte'"), 'Überschrift')
assert.match(OHNE_KOMMENTARE, /\.wks-gewaehr img\{[^']*width:100%;max-width:420px/)
assert.match(OHNE_KOMMENTARE, /\.wks-gewaehr\{[^']*border:2px solid/)
const kastenCode = OHNE_KOMMENTARE.slice(OHNE_KOMMENTARE.indexOf('function gewaehrKasten'), OHNE_KOMMENTARE.indexOf('function honigfeld'))
assert.ok(kastenCode.includes("img.alt = g.text") && !kastenCode.includes('lazy'), 'Pflichtbild nicht verzögert laden, Alt-Text = voller Text')
assert.ok(OHNE_KOMMENTARE.includes("img.loading = 'eager'"))
assert.ok(OHNE_KOMMENTARE.includes("'Vergrößern'"), 'Knopf')
assert.match(OHNE_KOMMENTARE, /dialogOeffnen\('Ihre gesetzlichen Gewährleistungsrechte', \[\{ bild: bildUrl, text: g\.text \}\]/)
assert.match(OHNE_KOMMENTARE, /e\.key === 'Escape'/, 'Esc schließt')
assert.ok(OHNE_KOMMENTARE.includes('knopf(\'wks-schliessen\', \'×\', dialogSchliessen)'), 'Schließen-Knopf')
// Reihenfolge in der Kasse: Kasten -> Zusammenfassung -> AGB-Hinweis -> Knopf
const i = (t) => OHNE_KOMMENTARE.indexOf(t)
const kasten = i('form.appendChild(gkasten)')
const pflicht = i('form.appendChild(pflicht)')
const hinweis = i('form.appendChild(agbHinweis)')
const knopf = i("var senden = el('button', 'wks-btn', 'Zahlungspflichtig bestellen')")
assert.ok(kasten > 0 && kasten < pflicht && pflicht < hinweis && hinweis < knopf, 'Reihenfolge')
// nicht mehr in der Zusammenfassung (die wird bei jeder Änderung neu aufgebaut)
const fuelle = OHNE_KOMMENTARE.slice(i('function fuellePflicht'), i('function landName'))
assert.ok(!fuelle.includes('gewaehr'), 'Gewährleistung nicht in fuellePflicht')
})
test('I-3: ausdrücklicher AGB-Hinweis direkt über dem Bestellknopf, AGB und Widerrufsbelehrung öffnen die Texte', () => {
const stelle = OHNE_KOMMENTARE.slice(OHNE_KOMMENTARE.indexOf("var agbHinweis = el('p'"), OHNE_KOMMENTARE.indexOf("var senden = el('button'"))
assert.ok(stelle.includes("createTextNode('Es gelten unsere ')"))
assert.ok(stelle.includes("knopf('wks-link', 'AGB', function (e) { zeigeAgb(e.currentTarget) })"))
assert.ok(stelle.includes("createTextNode('. Informationen zu Ihrem Widerrufsrecht finden Sie in der ')"))
assert.ok(stelle.includes("knopf('wks-link', 'Widerrufsbelehrung', function (e) { zeigeBelehrung(e.currentTarget) })"))
assert.ok(stelle.includes("createTextNode('.')"))
})
test('Weiterleitung zu Stripe nur zu einer https-Adresse (httpsUrl), Links der Rechtstexte nur als https', () => {
assert.match(OHNE_KOMMENTARE, /var ziel = d \? httpsUrl\(d\.url\) : ''/)
assert.match(OHNE_KOMMENTARE, /location\.href = ziel/)