/**
* Security Tests (Section 4 of TESTS.md)
*
* Tests XSS escaping in published HTML output.
*/
import { describe, it, expect } from "vitest";
import { renderArticleHTML, type PublishMeta } from "../src/publisher/html-renderer.js";
const EMPTY_CSS = {
variables: ":root { --text-color: #000; }",
reset: "",
base: "",
layout: "",
print: "",
editorTokens: "",
article: "",
components: "",
publisher: "",
};
const BASE_META: PublishMeta = {
title: "Test",
description: "Test description",
authors: [],
affiliations: [],
date: "2025-01-01",
};
const MINIMAL_JSON = {
type: "doc",
content: [{ type: "paragraph", content: [{ type: "text", text: "Hello" }] }],
};
describe("4.4 XSS prevention", () => {
it("4.4.1 licence field is escaped in published HTML", async () => {
const meta: PublishMeta = {
...BASE_META,
licence: '',
};
const html = await renderArticleHTML(MINIMAL_JSON, meta, EMPTY_CSS);
expect(html).not.toContain('');
expect(html).toContain("<script>");
});
it("4.4.2 title is escaped in published HTML", async () => {
const meta: PublishMeta = {
...BASE_META,
title: '
',
};
const html = await renderArticleHTML(MINIMAL_JSON, meta, EMPTY_CSS);
expect(html).not.toContain('
');
expect(html).toContain("<img");
});
it("4.4.3 description is escaped in meta tags", async () => {
const meta: PublishMeta = {
...BASE_META,
description: '">',
};
const html = await renderArticleHTML(MINIMAL_JSON, meta, EMPTY_CSS);
expect(html).not.toContain('">',
affiliationIndices: [],
affiliationNames: [],
},
],
};
const html = await renderArticleHTML(MINIMAL_JSON, meta, EMPTY_CSS);
expect(html).not.toContain('');
expect(html).toContain("<script>");
});
it("4.4.5 DOI is escaped in links", async () => {
const meta: PublishMeta = {
...BASE_META,
doi: '">',
};
const html = await renderArticleHTML(MINIMAL_JSON, meta, EMPTY_CSS);
expect(html).not.toContain('">