Files
Webklar-Kundenbereich/test/auftraegeKundenansicht.test.js
T

90 lines
5.1 KiB
JavaScript

import { test, after, beforeEach } from 'node:test'
import assert from 'node:assert/strict'
import os from 'node:os'
import path from 'node:path'
import { mkdtempSync } from 'node:fs'
import { startAppwriteMock } from './support/appwriteMock.js'
import { useTestEnv } from './support/testEnv.js'
import { mailSink } from './support/mailSink.js'
import { AUFTRAEGE_DATETIMES, AUFTRAEGE_SCHEMA, TOKEN, abDokument } from './auftraegeBestaetigungHilfe.js'
// Kundenansicht (Mitarbeiter im Portal eines Kunden): Bestätigen ist eine Erklärung im Namen des Kunden und bleibt gesperrt
process.env.AUFTRAEGE_UPLOAD_DIR = mkdtempSync(path.join(os.tmpdir(), 'auftraege-kundenansicht-'))
process.env.AUFTRAEGE_ENABLED = 'on'
const aw = await startAppwriteMock({ schema: AUFTRAEGE_SCHEMA, datetimes: AUFTRAEGE_DATETIMES, defaultLimit: 25 })
useTestEnv({ appwriteUrl: aw.url, stripeUrl: 'http://127.0.0.1:1' })
const { startTestApp, send } = await import('./support/testApp.js')
const { seedFixtures, customerCookie, kundenansichtCookie } = await import('./support/fixtures.js')
const { auftragToDoc, getAuftrag } = await import('../server/services/auftraege/auftragStore.js')
const { speicherePdf } = await import('../server/services/auftraege/ablage.js')
const { kundenansichtGuard, KUNDENANSICHT_ALLOWED } = await import('../server/middleware/kundenansichtGuard.js')
const { setMailTransportForTests } = await import('../server/services/mailer.js')
const { default: kundeRoutes } = await import('../server/routes/auftraegeKunde.js')
const { default: tokenRoutes } = await import('../server/routes/auftrag.js')
// Mount-Pfade und Reihenfolge wie in server/index.js: der Wächter steht vor den Routen
const app = await startTestApp({ '/': kundenansichtGuard, '/api/auftraege': kundeRoutes, '/api/auftrag': tokenRoutes })
after(() => {
setMailTransportForTests(null)
return Promise.all([app.close(), aw.close()])
})
seedFixtures(aw)
await speicherePdf('c1', 'ab1', Buffer.from('%PDF-1.4 Test'))
const VIEW = 'a'.repeat(32)
const kv = () => ({ cookie: kundenansichtCookie({ customerId: 'c1', viewId: VIEW }), headers: { 'x-kundenansicht': VIEW } })
let sink
beforeEach(() => {
sink = mailSink()
setMailTransportForTests(sink)
aw.seed('auftraege', { $id: 'ab1', ...auftragToDoc(abDokument()) })
})
const unveraendert = async () => {
const doc = await getAuftrag('ab1')
assert.deepEqual([doc.status, doc.bestaetigtAm, sink.sent.length], ['versendet', null, 0])
}
test('kein Eintrag der Erlaubnisliste gilt für Aufträge', () => {
for (const pfad of ['/api/auftraege', '/api/auftraege/ab1/bestaetigen', '/api/auftraege/ab1/pdf', `/api/auftrag/${TOKEN}`, `/api/auftrag/${TOKEN}/bestaetigen`]) {
assert.ok(!KUNDENANSICHT_ALLOWED.some(([, muster]) => muster.test(pfad)), pfad)
}
})
test('POST /api/auftraege/:id/bestaetigen in der Kundenansicht: 403 view_blocked, die AB bleibt unverändert', async () => {
const res = await send('POST', '/api/auftraege/ab1/bestaetigen', { ...kv(), body: { bestaetigt: true, fruehbeginn: true } })
assert.equal(res.status, 403)
assert.equal(res.body.code, 'view_blocked')
await unveraendert()
})
test('alle Schreib-Routen des Kunden-Routers sind in der Kundenansicht gesperrt (nur Bestätigen ist eine)', async () => {
const schreibRouten = kundeRoutes.stack
.filter((schicht) => schicht.route)
.flatMap((schicht) => Object.keys(schicht.route.methods).filter((m) => !['get', 'head', 'options', '_all'].includes(m)).map((m) => [m.toUpperCase(), `/api/auftraege${String(schicht.route.path).replace(/:[A-Za-z]+/g, 'ab1')}`]))
assert.deepEqual(schreibRouten, [['POST', '/api/auftraege/ab1/bestaetigen']])
for (const [methode, pfad] of schreibRouten) {
const res = await send(methode, pfad, { ...kv(), body: { bestaetigt: true } })
assert.equal(res.status, 403, `${methode} ${pfad}`)
}
await unveraendert()
})
test('auch der öffentliche Link bestätigt nichts, wenn der Browser eine Kundenansicht-Sitzung trägt', async () => {
const mitKennung = await send('POST', `/api/auftrag/${TOKEN}/bestaetigen`, { ...kv(), body: { bestaetigt: true } })
assert.deepEqual([mitKennung.status, mitKennung.body.code], [403, 'view_blocked'])
const ohneKennung = await send('POST', `/api/auftrag/${TOKEN}/bestaetigen`, { cookie: kv().cookie, body: { bestaetigt: true } })
assert.deepEqual([ohneKennung.status, ohneKennung.body.code], [409, 'view_replaced'])
await unveraendert()
})
test('Lesen bleibt erlaubt, kannBestaetigen ist in der Kundenansicht false; der Kunde selbst darf bestätigen', async () => {
const liste = await send('GET', '/api/auftraege', kv())
assert.equal(liste.status, 200)
assert.deepEqual(liste.body.auftraege.map((a) => [a.id, a.kannBestaetigen]), [['ab1', false]])
assert.equal((await send('GET', '/api/auftraege/ab1/pdf', kv())).status, 200)
const selbst = await send('GET', '/api/auftraege', { cookie: customerCookie('c1') })
assert.deepEqual(selbst.body.auftraege.map((a) => [a.id, a.kannBestaetigen]), [['ab1', true]])
const res = await send('POST', '/api/auftraege/ab1/bestaetigen', { cookie: customerCookie('c1'), body: { bestaetigt: true } })
assert.equal(res.status, 200)
assert.equal((await getAuftrag('ab1')).status, 'bestaetigt')
})