import { strict as assert } from 'node:assert'; import { readFile, rm } from 'node:fs/promises'; import path from 'node:path'; import { afterEach, beforeEach, describe, it } from 'node:test'; import type { FastifyInstance } from 'fastify'; import { SESSION_COOKIE, createSessionToken, csrfToken } from '../src/auth.ts'; import { parseSiteConfig } from '../src/config.ts'; import { ICON_URL, IdentityError, IdentityStore, sanitiseIcon } from '../src/storage/identity.ts'; import { buildApp } from '../src/server.ts'; import { FakePipeline, tempDir } from './support/harness.ts'; const BRAND = { name: 'Hops n Grains', tagline: 'Handcrafted Microbrewery', logo: '/assets/favicon.svg' }; const SECRET = 'identity-test-secret'; const SVG = ''; let dataDir: string; beforeEach(async () => { dataDir = await tempDir('identity'); }); afterEach(async () => { await rm(dataDir, { recursive: true, force: true }); }); function config() { return parseSiteConfig({ site: 'menu.example.test', brand: BRAND, sections: [{ slug: 'bar', label: 'Bar', order: 1 }], }); } async function loaded() { const store = new IdentityStore({ dataDir, seed: { ...BRAND } }); await store.load(); return store; } describe('sanitiseIcon', () => { it('strips script, event handlers and remote references but keeps the drawing', () => { const dirty = ` hi `; const clean = sanitiseIcon(dirty); assert.doesNotMatch(clean, /script/i); assert.doesNotMatch(clean, /onload|onclick/i); assert.doesNotMatch(clean, /foreignObject/i); assert.doesNotMatch(clean, /javascript:/i); assert.doesNotMatch(clean, /