Kundenansicht neu E-Fix M6: Zahlungsknöpfe sind nach der Rückkehr von Stripe wieder bedienbar

Nach "Zahlungspflichtig bestellen" setzt die Seite den Knopf auf "Weiter zur Zahlung…" (gesperrt) und leitet zu Stripe. Bricht der Kunde per
Zurück-Wischgeste ab, stellt Safari die Seite aus dem Bfcache her: der Knopf blieb gesperrt, ein neuer Versuch ging nur nach Neuladen. Nur
ansicht-wechsel.js hatte einen pageshow-Handler. Neuer Helfer beiRueckkehr(el, fn) in ansicht-hilfen.js (pageshow mit persisted, entfernt sich,
sobald das Element nicht mehr im Dokument steht); genutzt von der Bestellseite und von "Zahlungsart aktualisieren" (Verträge).
Speicher und Gutschrift leiten nicht zu Stripe, dort ist nichts zu tun.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 21:45:15 +00:00
1 parent 8bb02f3949
commit 140275022d
5 files changed
+38 -2

No files matched your search

+2
View File
@@ -26,6 +26,8 @@ test('Zahlungsproblem: Knopf öffnet das Stripe-Portal; Widerruf nur in der Fris
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 portal = fx.finde(b, (e) => e.textContent === 'Zahlungsart aktualisieren'); assert.equal(portal.hasAttribute('disabled'), true, 'während der Weiterleitung gesperrt')
fx.window.dispatchEvent({ type: 'pageshow', persisted: true }); assert.equal(portal.hasAttribute('disabled'), false, 'M6: zurück von Stripe wieder bedienbar')
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)
}))
+15
View File
@@ -99,6 +99,21 @@ test('Privat und leer: ein Häkchen aus dem Wortlaut, ungehakt nach der Frist, g
}
}))
test('M6: zurück von der Zahlungsseite (Wischgeste, Bfcache) ist der Knopf wieder bedienbar; ein später entfernter Knopf bekommt nichts mehr', mit({ 'POST /api/abo/checkout': { url: 'https://checkout.stripe.test/x' } }, async (fx) => {
const w = await zeige(fx, aboNeu(), meMit('privat'))
const knopf = fx.finde(w, '#abo-buy')
await fx.klick(knopf); await fx.ruhe()
assert.deepEqual([knopf.hasAttribute('disabled'), knopf.textContent], [true, 'Weiter zur Zahlung…'])
fx.window.dispatchEvent({ type: 'pageshow', persisted: false }); assert.equal(knopf.hasAttribute('disabled'), true, 'ein normales Laden (nicht persisted) ändert nichts')
fx.window.dispatchEvent({ type: 'pageshow', persisted: true })
assert.deepEqual([knopf.hasAttribute('disabled'), knopf.textContent], [false, 'Zahlungspflichtig bestellen'])
// der Knopf kann wieder bestellen
await fx.klick(knopf); await fx.ruhe(); assert.equal(fx.fetchLog.filter((a) => a.url === '/api/abo/checkout').length, 2)
// die Seite wurde ersetzt: der Hörer entfernt sich und fasst den alten Knopf nicht mehr an
w.replaceChildren(); knopf.disabled = true
fx.window.dispatchEvent({ type: 'pageshow', persisted: true }); assert.equal(knopf.hasAttribute('disabled'), true)
}))
test('Der Body enthält nie kundenart oder startChoice', mit({ 'POST /api/abo/checkout': { url: 'https://checkout.stripe.test/x' } }, async (fx) => {
for (const m of [meMit('unternehmen'), meMit('privat'), meMit('')]) {
const w = await zeige(fx, aboNeu(), m)