import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
defaultSvgLimits,
utf8ByteLength,
type SvgResourceLimits,
} from "../../src/app/limits";
import { parseSvgSource } from "../../src/document/source-parser";
const mutableLimits = defaultSvgLimits as SvgResourceLimits;
let original: SvgResourceLimits;
beforeEach(() => {
original = { ...defaultSvgLimits };
Object.assign(mutableLimits, {
maximumAttributeLength: 30,
maximumPathCommandsPerPath: 2,
maximumPathCommandsTotal: 3,
maximumCssRules: 1,
maximumReferences: 1,
maximumAnimations: 1,
maximumFilterPrimitives: 1,
maximumTextLength: 3,
maximumEmbeddedResourceBytes: 10,
});
});
afterEach(() => {
Object.assign(mutableLimits, original);
});
describe("configured SVG resource limits", () => {
it("counts UTF-8 bytes without allocating an encoded copy", () => {
expect(utf8ByteLength("Aé🙂\ud800")).toBe(10);
});
it("rejects a hard-limit document before XML or semantic processing", () => {
const result = parseSvgSource(
'',
0,
{ ...original, sourceHardBytes: 8, sourceSoftBytes: 4 },
);
expect(result.valid).toBe(false);
expect(result.semantic).toBeNull();
expect(result.diagnostics).toEqual([
expect.objectContaining({ code: "source-hard-limit" }),
]);
});
it("reports every bounded resource class with source-preserving diagnostics", () => {
const result = parseSvgSource(
``,
1,
);
const codes = result.diagnostics.map((diagnostic) => diagnostic.code);
expect(result.valid).toBe(false);
expect(result.semantic).not.toBeNull();
expect(codes).toEqual(
expect.arrayContaining([
"attribute-length-limit",
"path-command-per-element-limit",
"path-command-limit",
"css-rule-limit",
"reference-limit",
"animation-limit",
"filter-primitive-limit",
"text-length-limit",
"total-text-limit",
"embedded-resource-limit",
]),
);
});
it("does not count exponent markers as path commands", () => {
Object.assign(mutableLimits, {
maximumPathCommandsPerPath: 10,
maximumPathCommandsTotal: 10,
maximumTextLength: original.maximumTextLength,
maximumAttributeLength: original.maximumAttributeLength,
});
const result = parseSvgSource(
'',
1,
);
expect(result.semantic?.metrics.pathCommandCount).toBe(2);
});
it("bounds aggregate embedded data even when each resource is below the limit", () => {
const perResource = "data:image/png;base64,aaaaaaaaaaaaaaaaaaaaaaaa";
const result = parseSvgSource(
``,
2,
{
...original,
maximumEmbeddedResourceBytes: 60,
},
);
const codes = result.diagnostics.map((diagnostic) => diagnostic.code);
expect(codes).not.toContain("embedded-resource-limit");
expect(codes).toContain("embedded-resource-total-limit");
expect(result.valid).toBe(false);
});
});