71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { AnimationDefinition } from "../../src/animation/animation.types";
|
|
import {
|
|
animationStyle,
|
|
withAnimationPreview,
|
|
} from "../../src/animation/preview";
|
|
|
|
const fade: AnimationDefinition = {
|
|
id: "fade",
|
|
name: "Fade",
|
|
targetNodeKey: "id:shape",
|
|
property: "opacity",
|
|
kind: "style",
|
|
enabled: true,
|
|
keyframes: [
|
|
{ offset: 0, value: "0" },
|
|
{ offset: 1, value: "1" },
|
|
],
|
|
timing: {
|
|
durationMs: 500,
|
|
delayMs: 20,
|
|
iterations: "infinite",
|
|
direction: "alternate",
|
|
fillMode: "both",
|
|
easing: "ease-in-out",
|
|
},
|
|
};
|
|
|
|
describe("isolated animation preview", () => {
|
|
it("creates project-side CSS targeting only projection metadata", () => {
|
|
const css = animationStyle([fade]);
|
|
expect(css).toContain("@keyframes svg-tools-animation-0");
|
|
expect(css).toContain('[data-svg-tools-node="id:shape"]');
|
|
expect(css).toContain("500ms ease-in-out 20ms infinite alternate both");
|
|
});
|
|
|
|
it("injects preview metadata without mutating the input projection", () => {
|
|
const source =
|
|
'<svg xmlns="http://www.w3.org/2000/svg"><circle data-svg-tools-node="id:shape"/></svg>';
|
|
const result = withAnimationPreview(source, [fade]);
|
|
expect(source).not.toContain("data-svg-tools-preview");
|
|
expect(result).toContain('data-svg-tools-preview="animation"');
|
|
});
|
|
|
|
it("rejects unsafe properties and CSS rule or URL injection", () => {
|
|
expect(() =>
|
|
animationStyle([{ ...fade, property: "background-image" }]),
|
|
).toThrow(/not application-safe/u);
|
|
expect(() =>
|
|
animationStyle([
|
|
{
|
|
...fade,
|
|
keyframes: [{ offset: 0, value: "url(https://evil.test)" }],
|
|
},
|
|
]),
|
|
).toThrow(/URLs or external resources/u);
|
|
expect(() =>
|
|
animationStyle([
|
|
{
|
|
...fade,
|
|
timing: { ...fade.timing, easing: "linear; color:red" },
|
|
},
|
|
]),
|
|
).toThrow(/unsafe animation easing/u);
|
|
});
|
|
|
|
it("omits disabled animations", () => {
|
|
expect(animationStyle([{ ...fade, enabled: false }])).toBe("");
|
|
});
|
|
});
|