Terminplaner TP2: Bestell-Gate und Gesundheits-Stichwortpruefung
fragebogen.js ersetzt den Stub aus Block B: bestellpruefung (Kriterien (a) bis (h), je Punkt ein Eintrag, nach Schrittfolge sortiert, Abo-Punkt nur bei mitAbo !== false), SCHRITT_TITEL, gesundheitsWarnungen (Stichworte nur am Wortanfang, hoechstens 10 Meldungen) und bestellungAnsicht fuer die Bestellseite. einstellungen.js exportiert sichtbareLeistungen und MELDUNG_PFLICHT. Testhelfer bestellbarerStand und entwurfDoc; der Stub-Test entfaellt, die zwei B-Tests mit dem Stub laufen gegen das echte Gate. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ab47fabcb2
commit
008ad4fb1e
7 files changed
+869
-47
No files matched your search
@@ -27,6 +27,7 @@ const { config } = await import('../server/config.js')
|
||||
const { startTestApp, post } = await import('./support/testApp.js')
|
||||
const { customerCookie, kundenansichtCookie, seedFixtures, subscriptionDoc, wartungDoc } = await import('./support/fixtures.js')
|
||||
const { default: funktionenRoutes } = await import('../server/routes/funktionen.js')
|
||||
const { bestellbarerStand, entwurfDoc } = await import('./support/fragebogenStand.js')
|
||||
const { deleteDocument } = await import('../server/services/appwriteAdmin.js')
|
||||
const reg = await import('../server/services/featureRegistry.js')
|
||||
const order = await import('../server/services/featureOrder.js')
|
||||
@@ -349,9 +350,10 @@ test('Bestellpruefung: kaputter Haken (keine Liste) lehnt ab, 500 ohne Rohtext (
|
||||
test('Standard-Haken liest den Entwurf nur, wenn es ein Dokument gibt, und ruft die Bestellpruefung ohne Abo', async () => {
|
||||
const haken = reg.featureHaken('termine')
|
||||
const arg = { customerId: 'c1', projectId: 'p1', feature: T }
|
||||
// ohne Dokument: keine Abfrage von termineConfig, der Platzhalter meldet nichts offen
|
||||
// ohne Dokument: keine Abfrage von termineConfig, das echte Gate meldet nur die Branche offen (kein Abo-Punkt)
|
||||
aw.failNext({ collection: 'termineConfig', status: 500 })
|
||||
assert.deepEqual(await haken.bestellpruefung(arg), [])
|
||||
const ohneDoc = await haken.bestellpruefung(arg)
|
||||
assert.deepEqual(ohneDoc.map((p) => p.schritt), ['branche'])
|
||||
// mit Dokument: der Entwurf wird geladen (der eingeplante Lesefehler trifft)
|
||||
aw.seed('portalFeatures', { $id: 'f_p1_termine', customerId: 'c1', projectId: 'p1', featureKey: 'termine', state: 'off', enabled: false, siteKey: 'abcdefghijklmnop' })
|
||||
const log = stumm()
|
||||
@@ -360,10 +362,21 @@ test('Standard-Haken liest den Entwurf nur, wenn es ein Dokument gibt, und ruft
|
||||
} finally {
|
||||
log.mock.restore()
|
||||
}
|
||||
assert.deepEqual(await haken.bestellpruefung(arg), [], 'danach wieder normal')
|
||||
// Dokument ohne gespeicherten Entwurf: wie ohne Dokument
|
||||
assert.deepEqual((await haken.bestellpruefung(arg)).map((p) => p.schritt), ['branche'], 'danach wieder normal')
|
||||
// bestellbarer Entwurf: leer; offener Fragebogen: Punkte der Schritte, nie der Abo-Punkt (mitAbo: false)
|
||||
aw.seed('termineConfig', entwurfDoc('f_p1_termine', { customerId: 'c1', projectId: 'p1' }))
|
||||
assert.deepEqual(await haken.bestellpruefung(arg), [])
|
||||
const offen = bestellbarerStand()
|
||||
offen.fragebogen.bestaetigt = []
|
||||
aw.seed('termineConfig', entwurfDoc('f_p1_termine', { customerId: 'c1', projectId: 'p1', stand: offen }))
|
||||
const punkte = await haken.bestellpruefung(arg)
|
||||
assert.equal(punkte.length, 8)
|
||||
assert.ok(punkte.every((p) => p.schritt !== 'bestellen'))
|
||||
})
|
||||
|
||||
// ------------------------------------------------------------------------------------------ 7 Abo ---
|
||||
const SCHRITTE_OHNE_BRANCHE = ['wer', 'leistungen', 'zeiten', 'regeln', 'gastfelder', 'benachrichtigung', 'website']
|
||||
const ABO_TEXT = {
|
||||
kein_abo: 'Für den Terminplaner brauchst du ein laufendes Wartungs-Abo.',
|
||||
gekuendigt: 'Dein Wartungs-Abo ist gekündigt. Für den Terminplaner brauchst du ein laufendes Abo.',
|
||||
@@ -443,15 +456,67 @@ test('Abo-Lesefehler: 500 ohne Rohtext, fail-closed ohne Spur', async () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('Abo-Stufe mit leerer Pruefung (Stub und Standard-Gate): ohne Abo 409 kein_abo, nie bestellung_offen', async () => {
|
||||
test('Abo-Stufe mit dem echten Gate: ohne Abo und bestellbarem Entwurf 409 kein_abo, mit offenem Fragebogen 409 bestellung_offen (ohne bestellen)', async () => {
|
||||
const c3 = customerCookie('c3')
|
||||
// Standard-Haken (Platzhalter von Block B meldet nichts offen)
|
||||
aboAbgelehnt(await checkout('termine', { projectId: 'p3', zustimmung: zustimmung() }, c3), 'kein_abo')
|
||||
// ueberschriebener Haken mit leerer Liste
|
||||
const entwurf = (stand) => {
|
||||
aw.seed('portalFeatures', { $id: 'f_p3_termine', customerId: 'c3', projectId: 'p3', featureKey: 'termine', state: 'off', enabled: false, siteKey: 'abcdefghijklmnop' })
|
||||
aw.seed('termineConfig', entwurfDoc('f_p3_termine', { customerId: 'c3', projectId: 'p3', stand }))
|
||||
}
|
||||
// Standard-Haken, Kunde ohne Abo, bestellbarer Entwurf: das Gate ist leer, die Abo-Stufe lehnt ab
|
||||
entwurf(bestellbarerStand())
|
||||
const featuresVorher = aw.docs('portalFeatures').size
|
||||
const abgelehnt = await checkout('termine', { projectId: 'p3', zustimmung: zustimmung() }, c3)
|
||||
assert.equal(abgelehnt.status, 409)
|
||||
assert.equal(abgelehnt.body.code, 'kein_abo')
|
||||
assert.notEqual(abgelehnt.body.code, 'bestellung_offen')
|
||||
assert.equal(abgelehnt.body.error, ABO_TEXT.kein_abo)
|
||||
assert.deepEqual(spuren(), { sessions: 0, consents: 0, features: featuresVorher }, 'keine Sitzung, kein Nachweis, kein neues Dokument')
|
||||
// Kunde ohne Abo, Fragebogen offen: bestellung_offen, und die Liste enthaelt keinen Abo-Punkt (mitAbo: false)
|
||||
const offen = bestellbarerStand()
|
||||
offen.fragebogen.bestaetigt = ['branche']
|
||||
entwurf(offen)
|
||||
const res = await checkout('termine', { projectId: 'p3', zustimmung: zustimmung() }, c3)
|
||||
assert.equal(res.status, 409)
|
||||
assert.equal(res.body.code, 'bestellung_offen')
|
||||
assert.equal(res.body.offen.length, 7)
|
||||
assert.ok(res.body.offen.every((p) => p.schritt !== 'bestellen'), 'kein Eintrag bestellen')
|
||||
assert.deepEqual(res.body.offen.map((p) => p.schritt), SCHRITTE_OHNE_BRANCHE)
|
||||
assert.deepEqual(spuren(), { sessions: 0, consents: 0, features: featuresVorher })
|
||||
// ohne Entwurf (gar kein Dokument): ebenfalls bestellung_offen mit der Branche, nie ein Abo-Punkt
|
||||
for (const col of ['portalFeatures', 'termineConfig']) for (const id of aw.docs(col).keys()) await deleteDocument(col, id)
|
||||
const leer = await checkout('termine', { projectId: 'p3', zustimmung: zustimmung() }, c3)
|
||||
assert.equal(leer.status, 409)
|
||||
assert.equal(leer.body.code, 'bestellung_offen')
|
||||
assert.deepEqual(leer.body.offen.map((p) => p.schritt), ['branche'])
|
||||
// ueberschriebener Haken mit leerer Liste: weiter die Abo-Stufe
|
||||
T.bestellpruefung = async () => []
|
||||
aboAbgelehnt(await checkout('termine', { projectId: 'p3', zustimmung: zustimmung() }, c3), 'kein_abo')
|
||||
})
|
||||
|
||||
test('Echtes Gate bis zur Stripe-Sitzung: Kunde mit Wartungs-Abo und bestellbarem Entwurf kommt durch, mit offenem Punkt nicht', async () => {
|
||||
const entwurf = (stand) => {
|
||||
aw.seed('portalFeatures', { $id: 'f_p1_termine', customerId: 'c1', projectId: 'p1', featureKey: 'termine', state: 'off', enabled: false, siteKey: 'abcdefghijklmnop' })
|
||||
aw.seed('termineConfig', entwurfDoc('f_p1_termine', { customerId: 'c1', projectId: 'p1', stand }))
|
||||
}
|
||||
// ein offener Punkt (Impressum fehlt): 409 bestellung_offen, keine Sitzung, kein Nachweis
|
||||
const luecke = bestellbarerStand()
|
||||
luecke.einstellung.betrieb.impressumUrl = null
|
||||
entwurf(luecke)
|
||||
const offen = await checkout('termine', bodyT())
|
||||
assert.equal(offen.status, 409)
|
||||
assert.equal(offen.body.code, 'bestellung_offen')
|
||||
assert.deepEqual(offen.body.offen.map((p) => p.schritt), ['website'])
|
||||
assert.deepEqual({ sessions: sitzungen().length, consents: nachweise().length }, { sessions: 0, consents: 0 })
|
||||
// bestellbarer Entwurf: Gate leer, Abo laeuft, die Stripe-Sitzung entsteht
|
||||
entwurf(bestellbarerStand())
|
||||
const ok = await checkout('termine', bodyT())
|
||||
assert.equal(ok.status, 200, JSON.stringify(ok.body))
|
||||
assert.match(ok.body.url, /^https?:\/\//)
|
||||
assert.equal(sitzungen().length, 1)
|
||||
assert.equal(nachweise().length, 1)
|
||||
assert.equal(termineDoc().state, 'ordered')
|
||||
})
|
||||
|
||||
test('aboMeldung: Wortlaute aus dem Register, Akkusativ aus mails.formen.akk, unbekannter Grund wie unbekannt', () => {
|
||||
for (const grund of ['kein_abo', 'gekuendigt', 'nicht_aktiv']) assert.equal(order.aboMeldung(T, grund), ABO_TEXT[grund], grund)
|
||||
assert.equal(order.aboMeldung(T, 'unbekannt'), 'Das Abo konnte gerade nicht geprüft werden.')
|
||||
@@ -544,7 +609,7 @@ test('Abo-Memo: je Anfrage ein aboMemo(), News fragt das Abo nie', async () => {
|
||||
})
|
||||
|
||||
// ------------------------------------------------------------------------------------------ Sperre, Zustand, Nachweis (B7) ---
|
||||
// Ab hier der Rest der Route: die Vorpruefungen sind bestanden (Fragebogen-Pruefung per Haken uebersprungen, Block C fuellt sie).
|
||||
// Ab hier der Rest der Route: die Vorpruefungen sind bestanden (Fragebogen-Pruefung per Haken uebersprungen; das echte Gate pruefen die Tests der Abschnitte 6 und 7).
|
||||
const bereit = () => {
|
||||
T.bestellpruefung = async () => []
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user