Shop Review B I-5: Bestaetigen nur ohne Platzhalter, Musterkopf und mit Adresse der Widerrufsfunktion
pruefeBestaetigbar listet die Probleme in Du-Form; POST /api/shop/rechtstexte/bestaetigen antwortet 400 nicht_bestaetigbar mit der Liste, GET und PUT liefern sie als probleme mit. Der Reiter Rechtliches zeigt die Punkte im Bestaetigungsblock und sperrt den Knopf. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1f56b86791
commit
2f4f360a21
6 files changed
+169
-15
No files matched your search
+37
-11
@@ -61,6 +61,9 @@ const TEXTE = {
|
||||
datenschutzUrl: 'https://toepferei.example/datenschutz',
|
||||
}
|
||||
const ARTIKEL = { name: 'Tasse', preisCent: 1800 }
|
||||
/** Bestaetigungsfaehige Texte: die Belehrung nennt die Adresse der Widerrufsfunktion dieses Shops (I-5). */
|
||||
const WIDERRUF = (feature) => `${config.publicBaseUrl}/shop/${feature.siteKey}/widerruf`
|
||||
const texteFuer = (feature) => ({ ...TEXTE, widerrufsbelehrung: `Unsere Widerrufsbelehrung. Widerruf online: ${WIDERRUF(feature)}` })
|
||||
|
||||
const q = (projectId = 'pt1') => `projectId=${projectId}`
|
||||
const lesen = (pfad, projectId = 'pt1', opts = { cookie }) => send('GET', `/api/shop/${pfad}${pfad.includes('?') ? '&' : '?'}${q(projectId)}`, opts)
|
||||
@@ -98,7 +101,7 @@ async function machBereit({ mitArtikel = true } = {}) {
|
||||
const feature = await aktiviere()
|
||||
assert.equal((await schreiben('PUT', 'einstellungen', { einstellungen: EINSTELLUNGEN })).status, 200)
|
||||
if (mitArtikel) assert.equal((await schreiben('POST', 'produkte', { produkt: ARTIKEL })).status, 201)
|
||||
assert.equal((await schreiben('PUT', 'rechtstexte', { rechtstexte: TEXTE })).status, 200)
|
||||
assert.equal((await schreiben('PUT', 'rechtstexte', { rechtstexte: texteFuer(feature) })).status, 200)
|
||||
const hash = (await lesen('rechtstexte')).body.hash
|
||||
assert.equal((await schreiben('POST', 'rechtstexte/bestaetigen', { hash })).status, 200)
|
||||
await updateDocument(config.collections.shopConfig, feature.$id, {
|
||||
@@ -447,10 +450,11 @@ test('Rechtstexte GET: Entwurf leer, nichts bestaetigt, Muster, erzeugte Texte,
|
||||
const res = await lesen('rechtstexte')
|
||||
assert.equal(res.status, 200)
|
||||
const b = res.body
|
||||
assert.deepEqual(Object.keys(b).sort(), ['bestaetigt', 'bestaetigungText', 'entwurf', 'gewaehrleistung', 'hash', 'muster', 'versandUndZahlung', 'vollstaendig'])
|
||||
assert.deepEqual(Object.keys(b).sort(), ['bestaetigt', 'bestaetigungText', 'entwurf', 'gewaehrleistung', 'hash', 'muster', 'probleme', 'versandUndZahlung', 'vollstaendig'])
|
||||
assert.deepEqual(b.entwurf, { agb: '', widerrufsbelehrung: '', widerrufsformular: '', impressumUrl: '', datenschutzUrl: '' })
|
||||
assert.equal(b.bestaetigt, null)
|
||||
assert.equal(b.vollstaendig, false)
|
||||
assert.deepEqual(b.probleme, [], 'leerer Entwurf: nur vollstaendig meldet etwas')
|
||||
assert.match(b.hash, /^[0-9a-f]{64}$/)
|
||||
assert.equal(b.hash, rechtstexteHash(b.entwurf, (await lesen('einstellungen')).body.einstellungen))
|
||||
for (const k of ['agb', 'widerrufsbelehrung', 'widerrufsformular']) assert.ok(b.muster[k].length > 100, k)
|
||||
@@ -485,13 +489,13 @@ test('Rechtstexte PUT: speichert den Entwurf, normalisiert, Fehler 400; Hash aen
|
||||
test('Rechtstexte bestaetigen: falscher oder alter Hash 409, unvollstaendig 400, sonst Kopie mit Zeit, Person und Hash', async () => {
|
||||
const feature = await aktiviere()
|
||||
await schreiben('PUT', 'einstellungen', { einstellungen: EINSTELLUNGEN })
|
||||
const unvollstaendig = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...TEXTE, datenschutzUrl: '' } })
|
||||
const unvollstaendig = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...texteFuer(feature), datenschutzUrl: '' } })
|
||||
const hashUnvollstaendig = unvollstaendig.body.hash
|
||||
const leer = await schreiben('POST', 'rechtstexte/bestaetigen', { hash: hashUnvollstaendig })
|
||||
assert.equal(leer.status, 400)
|
||||
assert.equal(shopConfigDoc(feature).rechtstexteHash || '', '')
|
||||
|
||||
const voll = await schreiben('PUT', 'rechtstexte', { rechtstexte: TEXTE })
|
||||
const voll = await schreiben('PUT', 'rechtstexte', { rechtstexte: texteFuer(feature) })
|
||||
const falsch = await schreiben('POST', 'rechtstexte/bestaetigen', { hash: 'abc' })
|
||||
assert.deepEqual([falsch.status, falsch.body.code], [409, 'texte_geaendert'])
|
||||
assert.match(falsch.body.error, /^Die Texte wurden inzwischen geändert/)
|
||||
@@ -500,7 +504,7 @@ test('Rechtstexte bestaetigen: falscher oder alter Hash 409, unvollstaendig 400,
|
||||
|
||||
const ok = await schreiben('POST', 'rechtstexte/bestaetigen', { hash: voll.body.hash })
|
||||
assert.equal(ok.status, 200)
|
||||
assert.deepEqual(ok.body.bestaetigt.texte, TEXTE)
|
||||
assert.deepEqual(ok.body.bestaetigt.texte, texteFuer(feature))
|
||||
assert.equal(ok.body.bestaetigt.von, `${customers.c1.name} <${customers.c1.email}>`)
|
||||
assert.equal(ok.body.bestaetigt.aktuell, true)
|
||||
assert.ok(Math.abs(Date.now() - Date.parse(ok.body.bestaetigt.at)) < 10_000)
|
||||
@@ -509,13 +513,13 @@ test('Rechtstexte bestaetigen: falscher oder alter Hash 409, unvollstaendig 400,
|
||||
assert.equal(doc.rechtstexteBestaetigtVon, `${customers.c1.name} <${customers.c1.email}>`)
|
||||
assert.equal(new Date(doc.rechtstexteBestaetigtAt).toISOString(), new Date(ok.body.bestaetigt.at).toISOString())
|
||||
const gespeichert = JSON.parse(doc.rechtstexte)
|
||||
assert.deepEqual(gespeichert.entwurf, TEXTE)
|
||||
assert.deepEqual([gespeichert.bestaetigt.texte, gespeichert.bestaetigt.hash], [TEXTE, voll.body.hash])
|
||||
assert.deepEqual(gespeichert.entwurf, texteFuer(feature))
|
||||
assert.deepEqual([gespeichert.bestaetigt.texte, gespeichert.bestaetigt.hash], [texteFuer(feature), voll.body.hash])
|
||||
assert.equal((await shopPerSiteKey(feature.siteKey)).shop.rechtstexte.bestaetigt.hash, voll.body.hash, 'Speicher wurde geleert')
|
||||
|
||||
// Entwurf aendern: die bestaetigte Fassung bleibt, ist aber nicht mehr aktuell; Bereitschaft verlangt neue Bestaetigung
|
||||
const geaendert = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...TEXTE, agb: 'Geaenderte AGB' } })
|
||||
assert.deepEqual(geaendert.body.bestaetigt.texte, TEXTE)
|
||||
const geaendert = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...texteFuer(feature), agb: 'Geaenderte AGB' } })
|
||||
assert.deepEqual(geaendert.body.bestaetigt.texte, texteFuer(feature))
|
||||
assert.equal(geaendert.body.bestaetigt.aktuell, false)
|
||||
assert.equal(geaendert.body.entwurf.agb, 'Geaenderte AGB')
|
||||
const stand = (await lesen('status')).body.bereitschaft.punkte.find((p) => p.id === 'rechtstexte')
|
||||
@@ -524,9 +528,9 @@ test('Rechtstexte bestaetigen: falscher oder alter Hash 409, unvollstaendig 400,
|
||||
})
|
||||
|
||||
test('Rechtstexte: Hash haengt auch an den Einstellungen (Versand und Zahlung), eine Aenderung dort verlangt neue Bestaetigung', async () => {
|
||||
await aktiviere()
|
||||
const feature = await aktiviere()
|
||||
await schreiben('PUT', 'einstellungen', { einstellungen: EINSTELLUNGEN })
|
||||
await schreiben('PUT', 'rechtstexte', { rechtstexte: TEXTE })
|
||||
await schreiben('PUT', 'rechtstexte', { rechtstexte: texteFuer(feature) })
|
||||
const alt = (await lesen('rechtstexte')).body.hash
|
||||
await schreiben('PUT', 'einstellungen', { einstellungen: { ...EINSTELLUNGEN, versand: { ...EINSTELLUNGEN.versand, kostenCent: { DE: 690 } } } })
|
||||
const neu = (await lesen('rechtstexte')).body.hash
|
||||
@@ -535,6 +539,28 @@ test('Rechtstexte: Hash haengt auch an den Einstellungen (Versand und Zahlung),
|
||||
assert.equal((await schreiben('POST', 'rechtstexte/bestaetigen', { hash: neu })).status, 200)
|
||||
})
|
||||
|
||||
test('Rechtstexte bestaetigen I-5: Platzhalter, Musterkopf und fehlende Adresse der Widerrufsfunktion ⇒ 400 nicht_bestaetigbar mit Liste; GET zeigt dieselben Probleme', async () => {
|
||||
const feature = await aktiviere()
|
||||
await schreiben('PUT', 'einstellungen', { einstellungen: EINSTELLUNGEN })
|
||||
const schlecht = { ...texteFuer(feature), agb: 'Muster – bitte prüfen und anpassen\n\nAGB von [Name], [Anschrift]', widerrufsbelehrung: 'Unsere Widerrufsbelehrung ohne Adresse.' }
|
||||
const put = await schreiben('PUT', 'rechtstexte', { rechtstexte: schlecht })
|
||||
assert.equal(put.status, 200)
|
||||
assert.equal(put.body.probleme.length, 3)
|
||||
assert.deepEqual((await lesen('rechtstexte')).body.probleme, put.body.probleme)
|
||||
const res = await schreiben('POST', 'rechtstexte/bestaetigen', { hash: put.body.hash })
|
||||
assert.equal(res.status, 400)
|
||||
assert.equal(res.body.code, 'nicht_bestaetigbar')
|
||||
assert.deepEqual(res.body.probleme, put.body.probleme)
|
||||
assert.match(res.body.probleme.join('\n'), /„\[Name\]“, „\[Anschrift\]“/)
|
||||
assert.match(res.body.probleme.join('\n'), /Muster – bitte prüfen und anpassen/)
|
||||
assert.ok(res.body.probleme.join('\n').includes(WIDERRUF(feature)))
|
||||
assert.equal(shopConfigDoc(feature).rechtstexteHash || '', '', 'nichts bestaetigt')
|
||||
// behoben ⇒ ohne Probleme und bestaetigbar
|
||||
const gut = await schreiben('PUT', 'rechtstexte', { rechtstexte: texteFuer(feature) })
|
||||
assert.deepEqual(gut.body.probleme, [])
|
||||
assert.equal((await schreiben('POST', 'rechtstexte/bestaetigen', { hash: gut.body.hash })).status, 200)
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------- Oeffnen
|
||||
|
||||
test('Oeffnen: nur wenn bereit (sonst 409 mit Punkten), Schliessen immer, Speicher geleert, Eingabe geprueft', async () => {
|
||||
|
||||
Reference in new issue
Block a user