Files
svg-tools/tests/structure/reference-accessibility.test.ts

84 lines
3.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
accessibilityFixPatch,
auditAccessibility,
} from "../../src/accessibility/audit";
import { parseSvgSource } from "../../src/document/source-parser";
import { applySourcePatches } from "../../src/document/source-patcher";
import {
buildReferenceIndex,
previewIdRename,
} from "../../src/structure/reference-index";
function semantic(source: string) {
return parseSvgSource(source, 1).semantic!;
}
describe("references and accessibility", () => {
it("indexes resolved, missing and cyclic local references", () => {
const document = semantic(
`<svg xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="paint" href="#paint"/></defs><rect id="shape" fill="url(#paint)" aria-labelledby="missing"/></svg>`,
);
const index = buildReferenceIndex(document);
expect(index.edges).toEqual(
expect.arrayContaining([
expect.objectContaining({ targetId: "paint", status: "cyclic" }),
expect.objectContaining({ targetId: "missing", status: "missing" }),
]),
);
});
it("marks cycle members without mislabelling an upstream reference", () => {
const document = semantic(
'<svg xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="upstream" href="#left"/><linearGradient id="left" href="#right"/><linearGradient id="right" href="#left"/></defs></svg>',
);
const edges = buildReferenceIndex(document).edges;
expect(
edges.find(
(edge) =>
edge.sourceKey === "id:upstream" &&
edge.targetId === "left" &&
edge.status === "resolved",
),
).toBeDefined();
expect(
edges
.filter((edge) => edge.status === "cyclic")
.map((edge) => edge.targetId),
).toEqual(expect.arrayContaining(["left", "right"]));
});
it("renames an ID and its typed references without unsafe global replacement", () => {
const source =
'<svg xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="old"/><linearGradient id="oldish"/></defs><rect fill="url( #old )" stroke="url(#oldish)" aria-describedby="old oldish old"/></svg>';
const document = semantic(source);
const target = [...document.nodes.values()].find(
(node) => node.id === "old",
)!;
const preview = previewIdRename(document, target.key, "newPaint");
const result = applySourcePatches(source, preview.patches);
expect(result).toContain('id="newPaint"');
expect(result).toContain("url( #newPaint )");
expect(result).toContain("url(#oldish)");
expect(result).toContain('aria-describedby="newPaint oldish newPaint"');
});
it("reports missing root naming and provides an exact title patch", () => {
const source =
'<svg xmlns="http://www.w3.org/2000/svg"><rect width="4" height="4"/></svg>';
const document = semantic(source);
const findings = auditAccessibility(document);
expect(findings).toContainEqual(
expect.objectContaining({
rule: "svg-accessible-name",
automaticFix: "add-title",
}),
);
const fixed = applySourcePatches(source, [
accessibilityFixPatch(document, "add-title", "Small square"),
]);
expect(fixed).toContain("<title>Small square</title>");
});
});