Shop Review B I-6, I-7: Archiv der bestaetigten Rechtstexte, G09 ohne Link-Ersatz

I-6: Neue Collection shopRechtstexteArchiv (ID r + 35 Hex aus sha256(shopId + hash)); das
Bestaetigen legt die Fassung samt Versand-/Zahlungstext und Gewaehrleistungstext ab, G09 zeigt
die Fassung zum rechtstexteHash der Bestellung (Rueckfall mit Warnung auf die aktuell
bestaetigte), loescheShopDaten loescht das Archiv mit.

I-7: Grenzen AGB 20000, Belehrung 12000, Formular 3000 plus Pruefung der maskierten Laenge beim
Speichern; G09 ersetzt die AGB nie mehr durch einen Link, sondern scheitert (Marker bleibt
offen, wird wiederholt). Test mit Texten in Hoechstlaenge gegen die Grenzen der Warteschlange.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 09:58:31 +00:00
1 parent 2f4f360a21
commit 08d837d690
17 files changed
+288 -65

No files matched your search

+14 -2
View File
@@ -18,6 +18,7 @@ const aw = await startAppwriteMock({
portalFeatures: schemaKeys('portalFeatures'),
shopConfig: schemaKeys('shopConfig'),
shopProducts: schemaKeys('shopProducts'),
shopRechtstexteArchiv: schemaKeys('shopRechtstexteArchiv'),
customerViewLog: schemaKeys('customerViewLog'),
},
datetimes: SHOP_DATETIMES,
@@ -32,6 +33,7 @@ const { kundenansichtGuard } = await import('../server/middleware/kundenansichtG
const sf = await import('../server/services/siteFeatures.js')
const { deleteDocument, updateDocument } = await import('../server/services/appwriteAdmin.js')
const { shopPerSiteKey } = await import('../server/services/shop/kontext.js')
const { archivId } = await import('../server/services/shop/archiv.js')
const { rechtstexteHash } = await import('../server/services/shop/rechtstexte.js')
const { STANDARD_EINSTELLUNGEN } = await import('../server/services/shop/einstellungen.js')
@@ -117,7 +119,7 @@ beforeEach(async () => {
config.shop.mode = 'pilot'
config.shop.pilotEmails = [customers.c1.email]
resetShopRoutesForTests()
for (const col of ['portalFeatures', 'shopConfig', 'shopProducts', 'customerViewLog']) {
for (const col of ['portalFeatures', 'shopConfig', 'shopProducts', 'shopRechtstexteArchiv', 'customerViewLog']) {
for (const id of [...aw.docs(col).keys()]) await deleteDocument(config.collections[col], id)
}
await rm(process.env.SHOP_UPLOAD_DIR, { recursive: true, force: true })
@@ -481,7 +483,7 @@ test('Rechtstexte PUT: speichert den Entwurf, normalisiert, Fehler 400; Hash aen
assert.ok(schlecht.body.fehler.impressumUrl && schlecht.body.fehler.datenschutzUrl)
assert.equal((await schreiben('PUT', 'rechtstexte', { rechtstexte: 'text' })).status, 400)
assert.equal((await schreiben('PUT', 'rechtstexte', {})).status, 400)
const zuLang = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...TEXTE, agb: 'x'.repeat(30001) } })
const zuLang = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...TEXTE, agb: 'x'.repeat(20001) } })
assert.equal(zuLang.status, 400)
assert.equal((await lesen('rechtstexte')).body.entwurf.agb, 'Neue AGB\n\nZeile', 'Fehler aendert nichts')
})
@@ -516,6 +518,16 @@ test('Rechtstexte bestaetigen: falscher oder alter Hash 409, unvollstaendig 400,
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')
// I-6: die bestaetigte Fassung liegt im Archiv (eigene ID, Texte samt Versand/Zahlung und Gewaehrleistung, Person und Zeit)
const archiv = [...aw.docs('shopRechtstexteArchiv').values()]
assert.equal(archiv.length, 1)
assert.equal(archiv[0].$id, archivId(feature.$id, voll.body.hash))
assert.deepEqual([archiv[0].shopId, archiv[0].customerId, archiv[0].hash, archiv[0].bestaetigtVon], [feature.$id, 'c1', voll.body.hash, `${customers.c1.name} <${customers.c1.email}>`])
assert.equal(new Date(archiv[0].bestaetigtAt).toISOString(), new Date(ok.body.bestaetigt.at).toISOString())
const archTexte = JSON.parse(archiv[0].texte)
assert.deepEqual({ ...archTexte, versandUndZahlung: undefined, gewaehrleistung: undefined }, { ...texteFuer(feature), versandUndZahlung: undefined, gewaehrleistung: undefined })
assert.equal(archTexte.versandUndZahlung, voll.body.versandUndZahlung)
assert.equal(archTexte.gewaehrleistung, voll.body.gewaehrleistung.text)
// Entwurf aendern: die bestaetigte Fassung bleibt, ist aber nicht mehr aktuell; Bereitschaft verlangt neue Bestaetigung
const geaendert = await schreiben('PUT', 'rechtstexte', { rechtstexte: { ...texteFuer(feature), agb: 'Geaenderte AGB' } })