import { test, after } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import vm from 'node:vm' import { useTestEnv } from './support/testEnv.js' import { installFakeDom } from './support/fakeDom.js' // Task 17: Standalone-Seiten /unterkunft/:siteKey und /unterkunft/:siteKey/buchung/:id plus Skript public/unterkunft-buchung.js useTestEnv({ appwriteUrl: 'http://127.0.0.1:1', stripeUrl: 'http://127.0.0.1:1' }) const { startTestApp } = await import('./support/testApp.js') const { unterkunftSeiteRouter, resetUnterkunftSeiteForTests } = await import('../server/routes/unterkunftSeite.js') resetUnterkunftSeiteForTests() const app = await startTestApp({ '/': unterkunftSeiteRouter() }) after(() => app.close()) const KEY = 'abcdefghijklmnop' const get = async (path) => { const r = await fetch(app.url + path) return { status: r.status, headers: r.headers, text: await r.text() } } const lies = (pfad) => readFileSync(new URL(`../${pfad}`, import.meta.url), 'utf8') /* ----------------------------------------------------------------- Routen --- */ test('Widget-Seite und Buchungsseite: 200, Schluessel escaped, Schutz-Header', async () => { for (const [pfad, ansicht] of [[`/unterkunft/${KEY}`, 'widget'], [`/unterkunft/${KEY}/buchung/Ab_c-123?t=geheim`, 'buchung']]) { const r = await get(pfad) assert.equal(r.status, 200, pfad) assert.match(r.headers.get('content-type'), /^text\/html; charset=utf-8/) assert.match(r.text, new RegExp(`
<\/script>/) assert.equal(r.headers.get('cache-control'), 'no-store') assert.equal(r.headers.get('x-robots-tag'), 'noindex') assert.equal(r.headers.get('referrer-policy'), 'no-referrer') assert.match(r.text, //) assert.equal(r.headers.get('x-content-type-options'), 'nosniff') const csp = r.headers.get('content-security-policy') for (const d of ["default-src 'self'", "script-src 'self'", "connect-src 'self'", "frame-ancestors 'none'", "base-uri 'none'", "form-action 'self'"]) assert.ok(csp.includes(d), d) assert.ok(!/script-src[^;]*unsafe/.test(csp)) } }) test('ungueltige Schluessel, ical und fremde Pfade: 404 ohne Container', async () => { for (const p of ['/unterkunft/xyz', '/unterkunft/ical', `/unterkunft/${KEY.toUpperCase()}`, `/unterkunft/${KEY}a`, '/unterkunft/%3Cscript%3E', '/unterkunft/ical/buchung/abc', `/unterkunft/${KEY}/buchung`, `/unterkunft/${KEY}/buchung/a%20b`, `/unterkunft/${KEY}/buchung/${'a'.repeat(37)}`, `/unterkunft/${KEY}/agb`, '/unterkunft', '/unterkunft/']) { const r = await get(p) assert.equal(r.status, 404, p) assert.doesNotMatch(r.text, /uk-app/, p) } }) test('Seitenvorlage: kein Inline-Skript, Stylesheet und Skripte vom eigenen Ursprung', () => { const html = lies('public/unterkunft-seite.html') assert.doesNotMatch(html, /]*\bsrc=)/) assert.match(html, /name="robots" content="noindex"/) assert.match(html, /