110 lines
7.2 KiB
JavaScript
110 lines
7.2 KiB
JavaScript
import { test, after } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { startAppwriteMock } from './support/appwriteMock.js'
|
|
import { startFakeStripe } from './support/fakeStripe.js'
|
|
import { useTestEnv } from './support/testEnv.js'
|
|
import { schemaKeys } from './support/schema.js'
|
|
|
|
// Fassungsweiche (V12) und Vertragsnachweis: eine Zeile in featureConsents ohne Projekt, mit Kundenart, Hash und Konto
|
|
const aw = await startAppwriteMock({ schema: { featureConsents: schemaKeys('featureConsents') } })
|
|
const st = await startFakeStripe()
|
|
after(() => Promise.all([aw.close(), st.close()]))
|
|
useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url })
|
|
Object.assign(process.env, { KUNDENANSICHT_NEU: 'pilot', KUNDENANSICHT_NEU_PILOT_EMAILS: 'k3@example.invalid' })
|
|
const { config } = await import('../server/config.js')
|
|
const { fassungDerAnfrage, istNeueFassung, speichereVertragsNachweis, speichereNachweisFuerRoute } = await import('../server/services/vertragsNachweis.js')
|
|
const { nachweisTexte, FEHLER_NACHWEIS } = await import('../server/services/bestelltexte.js')
|
|
const { texteHash } = await import('../server/services/featureConsents.js')
|
|
|
|
const req = (email = 'k3@example.invalid') => ({
|
|
ip: '203.0.113.9',
|
|
get: (h) => (h === 'user-agent' ? 'UA/1' : ''),
|
|
session: { customerId: 'c3', appwriteUserId: 'u3', name: 'Kunde Drei', email },
|
|
})
|
|
|
|
test('fassungDerAnfrage: alt, neu, null; fehlende Neu-Fassung ist nie neu', () => {
|
|
const NEU = config.abo.termsVersionNeu
|
|
const modus = config.kundenansichtNeu.mode // P8 setzt die Neu-Fassung, der Test liest sie nur
|
|
try {
|
|
assert.equal(fassungDerAnfrage(req('fremd@example.invalid'), config.abo.termsVersion), 'alt')
|
|
assert.equal(fassungDerAnfrage(req('k3@example.invalid'), NEU), 'neu')
|
|
assert.equal(fassungDerAnfrage(req('fremd@example.invalid'), NEU), null) // nicht Pilot
|
|
assert.equal(fassungDerAnfrage(req('k3@example.invalid'), '2026-09-25-v3'), null)
|
|
for (const v of [undefined, null, '', 6, {}]) assert.equal(fassungDerAnfrage(req('k3@example.invalid'), v), null)
|
|
config.abo.termsVersionNeu = undefined
|
|
assert.equal(fassungDerAnfrage(req('k3@example.invalid'), undefined), null)
|
|
config.abo.termsVersionNeu = NEU
|
|
config.kundenansichtNeu.mode = 'off'
|
|
assert.equal(fassungDerAnfrage(req('k3@example.invalid'), NEU), null) // off schlägt die Liste
|
|
assert.deepEqual([istNeueFassung(NEU), istNeueFassung(''), istNeueFassung(undefined), istNeueFassung(config.abo.termsVersion)], [true, false, false, false])
|
|
// gleiche Werte (nach P10): nur noch mit neuer Ansicht 'neu', sonst null
|
|
config.kundenansichtNeu.mode = 'pilot'
|
|
config.abo.termsVersionNeu = config.abo.termsVersion
|
|
assert.equal(fassungDerAnfrage(req('k3@example.invalid'), config.abo.termsVersion), 'neu')
|
|
assert.equal(fassungDerAnfrage(req('fremd@example.invalid'), config.abo.termsVersion), null)
|
|
// eine Sitzung ohne Konto-Kennung ist keine Kunden-Sitzung (P0)
|
|
config.abo.termsVersionNeu = NEU
|
|
const ohneKonto = req(); delete ohneKonto.session.appwriteUserId
|
|
assert.equal(fassungDerAnfrage(ohneKonto, NEU), null)
|
|
} finally {
|
|
config.abo.termsVersionNeu = NEU
|
|
config.kundenansichtNeu.mode = modus
|
|
}
|
|
})
|
|
|
|
test('speichereVertragsNachweis schreibt eine Zeile ohne Projekt, mit Kundenart, Hash und Konto', async () => {
|
|
const FASSUNG = config.abo.termsVersionNeu
|
|
const texte = nachweisTexte('abo', { kundenart: 'privat', fassung: FASSUNG, bestellung: 'Zeile', beginnGehakt: true })
|
|
const d = await speichereVertragsNachweis({ customerId: 'c3', art: 'abo', bezug: 'wartung', texte, fassungen: { zustimmung: FASSUNG }, kundenart: 'privat', req: req('k3@example.invalid'), at: '2026-10-17T08:00:00.000Z' })
|
|
assert.deepEqual([d.featureKey, d.projectId, d.stripeSessionId, d.kundenart, d.konto, d.ip, d.userAgent], ['abo', '', '', 'privat', 'Kunde Drei <k3@example.invalid>', '203.0.113.9', 'UA/1'])
|
|
assert.deepEqual(JSON.parse(d.fassungen), { zustimmung: FASSUNG, bezug: 'wartung', wortlaut: 'entwurf' })
|
|
assert.deepEqual(JSON.parse(d.texte), texte)
|
|
assert.equal(d.textHash, texteHash(texte))
|
|
assert.equal(d.acceptedAt, '2026-10-17T08:00:00.000Z')
|
|
assert.equal(aw.docs('featureConsents').get(d.$id).customerId, 'c3')
|
|
})
|
|
|
|
test('Mitarbeiter-Kundenansicht: das Konto ist die handelnde Person, nicht der Kunde', async () => {
|
|
const r = req()
|
|
r.session.adminName = 'Team Mitglied'
|
|
r.session.adminEmail = 'team@example.invalid'
|
|
const d = await speichereVertragsNachweis({ customerId: 'c3', art: 'wechsel', texte: nachweisTexte('gutschrift', {}), fassungen: {}, kundenart: 'unternehmen', req: r, at: '2026-10-17T08:00:00.000Z' })
|
|
assert.equal(d.konto, 'Team Mitglied <team@example.invalid>')
|
|
assert.deepEqual([d.kundenart, JSON.parse(d.fassungen).bezug], ['unternehmen', ''])
|
|
})
|
|
|
|
test('Ungültiges wird vor dem Schreiben mit 400 abgelehnt, nie als privat ergänzt', async () => {
|
|
const vorher = aw.docs('featureConsents').size
|
|
const gut = { customerId: 'c3', art: 'abo', texte: [{ id: 'knopf', text: 'Zahlungspflichtig bestellen', haken: false }], fassungen: {}, kundenart: 'privat', req: req(), at: '2026-10-17T08:00:00.000Z' }
|
|
for (const schlecht of [
|
|
{ art: 'feature' }, { art: undefined }, { kundenart: '' }, { kundenart: 'firma' }, { kundenart: undefined },
|
|
{ texte: [] }, { texte: undefined }, { texte: [{ id: 'x', text: '' }] }, { texte: [{ id: '', text: 'a' }] }, { texte: [{ id: 'x', text: 'a', haken: 'ja' }] },
|
|
{ texte: [{ id: 'x', text: 'a'.repeat(20001) }] }, { fassungen: { zustimmung: 'a'.repeat(1001) } }, { fassungen: null },
|
|
{ customerId: '' }, { customerId: undefined }, { at: 'gestern' }, { at: undefined },
|
|
]) {
|
|
await assert.rejects(speichereVertragsNachweis({ ...gut, ...schlecht }), (e) => e.status === 400, JSON.stringify(Object.keys(schlecht)))
|
|
}
|
|
assert.equal(aw.docs('featureConsents').size, vorher)
|
|
for (const art of ['abo', 'wechsel', 'speicher', 'gutschrift']) await speichereVertragsNachweis({ ...gut, art })
|
|
assert.equal(aw.docs('featureConsents').size, vorher + 4)
|
|
})
|
|
|
|
test('Appwrite-Fehler: 500 mit dem festen Text, keine Ursache nach außen', async () => {
|
|
const vorher = aw.docs('featureConsents').size
|
|
aw.failNext({ collection: config.collections.featureConsents, method: 'POST', status: 500, message: 'geheimer Appwrite-Text' })
|
|
await assert.rejects(
|
|
speichereVertragsNachweis({ customerId: 'c3', art: 'gutschrift', texte: nachweisTexte('gutschrift', {}), fassungen: {}, kundenart: 'unternehmen', req: req(), at: '2026-10-17T08:00:00.000Z' }),
|
|
(e) => e.status === 500 && e.message === FEHLER_NACHWEIS && !JSON.stringify(e).includes('geheimer'),
|
|
)
|
|
assert.equal(aw.docs('featureConsents').size, vorher)
|
|
})
|
|
|
|
test('speichereNachweisFuerRoute: auch eine abgelehnte Eingabe ist ein 500 mit dem festen Text, nichts geschrieben', async () => {
|
|
const vorher = aw.docs('featureConsents').size
|
|
const gut = { customerId: 'c3', art: 'abo', texte: nachweisTexte('gutschrift', {}), fassungen: {}, kundenart: 'privat', req: req(), at: '2026-10-17T08:00:00.000Z' }
|
|
await assert.rejects(speichereNachweisFuerRoute({ ...gut, kundenart: '' }), (e) => e.status === 500 && e.message === FEHLER_NACHWEIS)
|
|
assert.equal(aw.docs('featureConsents').size, vorher)
|
|
assert.equal((await speichereNachweisFuerRoute(gut)).featureKey, 'abo')
|
|
assert.equal(aw.docs('featureConsents').size, vorher + 1)
|
|
})
|