import assert from 'node:assert/strict'; import path from 'node:path'; import { test } from 'node:test'; import { handleApi } from '../server/api.js'; import { resolveSafe } from '../server/static.js'; import { PUBLIC_DIR } from './helpers.js'; test('resolveSafe stays inside the public directory', () => { const root = path.resolve(PUBLIC_DIR); assert.equal(resolveSafe(root, '/js/main.js'), path.join(root, 'js', 'main.js')); for (const evil of ['/../package.json', '/..%2F..%2Fetc/passwd', '/a/../../x', '/%00', '/%E0%A4%A']) { const result = resolveSafe(root, evil); assert.ok(result === null || result.startsWith(root + path.sep), evil); } assert.equal(resolveSafe(root, '/%00'), null); assert.equal(resolveSafe(root, '/%E0%A4%A'), null); }); test('/api/themes lists installed themes with their languages', async () => { const themes = await handleApi(PUBLIC_DIR, '/api/themes'); const ids = themes.map((t) => t.id); for (const id of ['paperclip', 'witch', 'alien', 'insects', 'computers']) assert.ok(ids.includes(id), id); assert.deepEqual(themes.find((t) => t.id === 'paperclip').locales, ['en', 'fr']); }); test('/api/locales lists languages with their own names', async () => { const locales = await handleApi(PUBLIC_DIR, '/api/locales'); assert.deepEqual(locales.find((l) => l.code === 'fr'), { code: 'fr', name: 'Français' }); }); test('unknown API routes are not handled', async () => { assert.equal(await handleApi(PUBLIC_DIR, '/api/nope'), undefined); });