84 lines
3.2 KiB
TypeScript
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>");
|
|
});
|
|
});
|