Kundenansicht neu P10: Korrekturen aus der Pruefung (Task 5 Kaeufe lesen)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1b79210a7c
commit
e8ede69188
2 files changed
+81
No files matched your search
@@ -1,5 +1,7 @@
|
||||
import { test, after } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { execFile } from 'node:child_process'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { startAppwriteMock } from './support/appwriteMock.js'
|
||||
import { useTestEnv } from './support/testEnv.js'
|
||||
import { schemaKeys } from './support/schema.js'
|
||||
@@ -13,11 +15,15 @@ const { pruefeKaeufe } = await import('../scripts/kauf-bestand-pruefen.mjs')
|
||||
const { deleteDocument } = await import('../server/services/appwriteAdmin.js')
|
||||
|
||||
const jetzt = new Date('2026-11-10T10:00:00Z')
|
||||
const SKRIPT = new URL('../scripts/kauf-bestand-pruefen.mjs', import.meta.url).pathname
|
||||
|
||||
const feature = (id, over = {}) =>
|
||||
aw.seed('portalFeatures', {
|
||||
$id: id, customerId: 'c1', projectId: `p_${id}`, featureKey: 'termine', state: 'active', enabled: true, siteKey: `k_${id}`, ...over,
|
||||
})
|
||||
const leereFeatures = async () => {
|
||||
for (const id of aw.docs('portalFeatures').keys()) await deleteDocument('portalFeatures', id)
|
||||
}
|
||||
const sammler = () => {
|
||||
const zeilen = []
|
||||
return { log: (z) => zeilen.push(z), text: () => zeilen.join('\n') }
|
||||
@@ -72,6 +78,7 @@ test('ohne Käufe: alles leer', async () => {
|
||||
assert.deepEqual(await pruefeKaeufe({ log: out.log, jetzt }), { offeneBestellungen: [], fristLaeuft: [], gekauftGesamt: 0 })
|
||||
assert.match(out.text(), /Offene Bestellungen: 0/)
|
||||
assert.match(out.text(), /Fristen laufen: 0/)
|
||||
assert.match(out.text(), /Behalten-Sitzung eingetragen: 0/)
|
||||
})
|
||||
|
||||
test('Lesefehler: der Fehler geht nach oben, es wird nichts als leer gemeldet', async () => {
|
||||
@@ -79,3 +86,64 @@ test('Lesefehler: der Fehler geht nach oben, es wird nichts als leer gemeldet',
|
||||
aw.failNext({ collection: 'portalFeatures', method: 'GET', status: 500 })
|
||||
await assert.rejects(() => pruefeKaeufe({ log: () => {}, jetzt }))
|
||||
})
|
||||
|
||||
test('Öffnungszeiten "Behalten": eingetragene Sitzung wird als eigene Zeile gemeldet, ohne Sitzungs-ID, ohne Einfluss auf offene Bestellungen', async () => {
|
||||
await leereFeatures() // f_x aus dem Lesefehler-Test steht noch da
|
||||
// starteBehalten ändert den Zustand nicht, es schreibt nur behaltenSessionId ans Dokument (disabled/abo_ende oder active)
|
||||
feature('f_behalten', { state: 'disabled', unlockedBy: 'abo', disabledReason: 'abo_ende', behaltenSessionId: 'cs_offen_1' })
|
||||
feature('f_behalten_aktiv', { state: 'active', unlockedBy: 'abo', behaltenSessionId: 'cs_offen_2' })
|
||||
// schon gebucht (bucheBehalten setzt behaltenSessionId zurück; steht sie doch noch, zählt die gebuchte Sitzung nicht) und ohne Sitzung
|
||||
feature('f_behalten_gebucht', {
|
||||
state: 'active', unlockedBy: 'kauf', unlockedByPurchase: true, stripeSessionId: 'cs_fertig', behaltenSessionId: 'cs_fertig', orderedAt: '2026-09-20T09:00:00.000Z',
|
||||
})
|
||||
feature('f_ohne_sitzung', { state: 'active', unlockedBy: 'abo', behaltenSessionId: '' })
|
||||
const out = sammler()
|
||||
const e = await pruefeKaeufe({ log: out.log, jetzt })
|
||||
assert.deepEqual(e.offeneBestellungen, [], 'eine abgelaufene Sitzungs-ID bleibt stehen: kein Grund für Exit 1')
|
||||
assert.match(out.text(), /Behalten-Sitzung eingetragen: 2 \(f_behalten, f_behalten_aktiv\)/)
|
||||
assert.doesNotMatch(out.text(), /cs_/, 'keine Stripe-Sitzungen in der Ausgabe')
|
||||
for (const id of ['f_behalten', 'f_behalten_aktiv', 'f_behalten_gebucht', 'f_ohne_sitzung']) await deleteDocument('portalFeatures', id)
|
||||
})
|
||||
|
||||
// ---------- Einstieg: Exit-Code ist das Tor vor dem Umschalten ----------
|
||||
|
||||
/** Das Skript als eigener Prozess gegen den Nachbau (sauberes env, cwd ausserhalb des Repos: keine .env) -> { code, stdout, stderr }. */
|
||||
function lauf() {
|
||||
const env = { PATH: process.env.PATH, APPWRITE_ENDPOINT: aw.url, APPWRITE_API_KEY: 'test-key' }
|
||||
assert.equal(new URL(env.APPWRITE_ENDPOINT).hostname, '127.0.0.1', 'nur der Nachbau')
|
||||
return new Promise((resolve) => {
|
||||
execFile(
|
||||
process.execPath,
|
||||
['--max-old-space-size=512', SKRIPT],
|
||||
{ env, cwd: tmpdir(), timeout: 30_000 },
|
||||
(error, stdout, stderr) => resolve({ code: error ? error.code : 0, stdout, stderr })
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
test('Einstieg: Exit 1 bei offener Bestellung, Exit 0 ohne (laufende Fristen sind kein Hindernis), Exit 1 bei Lesefehler', async () => {
|
||||
await leereFeatures()
|
||||
feature('f_offen', { state: 'ordered', purchaseStatus: 'ordered' })
|
||||
const offen = await lauf()
|
||||
assert.equal(offen.code, 1, offen.stderr)
|
||||
assert.match(offen.stdout, /Offene Bestellungen: 1 \(f_offen\)/)
|
||||
assert.match(offen.stdout, /erst die Zahlung abwarten/)
|
||||
|
||||
// keine offene Bestellung, aber eine laufende Frist (gerade gekauft) und eine Behalten-Sitzung: nur Information
|
||||
await deleteDocument('portalFeatures', 'f_offen')
|
||||
feature('f_frist_jetzt', { state: 'setup', purchaseStatus: 'paid', unlockedByPurchase: true, orderedAt: new Date().toISOString() })
|
||||
feature('f_behalten', { state: 'disabled', unlockedBy: 'abo', behaltenSessionId: 'cs_offen' })
|
||||
const frei = await lauf()
|
||||
assert.equal(frei.code, 0, frei.stderr)
|
||||
assert.match(frei.stdout, /Offene Bestellungen: 0/)
|
||||
assert.match(frei.stdout, /Fristen laufen: 1 \(f_frist_jetzt\)/)
|
||||
assert.match(frei.stdout, /Behalten-Sitzung eingetragen: 1 \(f_behalten\)/)
|
||||
|
||||
// Lesefehler: Exit 1, Fehler auf stderr, nie ein leeres "alles gut" auf stdout
|
||||
aw.failNext({ collection: 'portalFeatures', method: 'GET', status: 500 })
|
||||
const kaputt = await lauf()
|
||||
assert.equal(kaputt.code, 1)
|
||||
assert.match(kaputt.stderr, /^Fehler: /)
|
||||
assert.doesNotMatch(kaputt.stdout, /Offene Bestellungen/)
|
||||
await leereFeatures()
|
||||
})
|
||||
Reference in new issue
Block a user