1import { describe, expect, it } from "vite-plus/test";
2
3import { isPickedElementPayload, isPreviewAnnotationPayload } from "./PickedElementPayload.ts";
4
5function validPayload(overrides?: Record<string, unknown>): Record<string, unknown> {
6 return {
7 pageUrl: "https://example.com/",
8 pageTitle: "Example",
9 tagName: "button",
10 selector: "button.submit",
11 htmlPreview: "<button>Save</button>",
12 componentName: "SubmitButton",
13 source: {
14 functionName: "SubmitButton",
15 fileName: "/repo/src/Button.tsx",
16 lineNumber: 12,
17 columnNumber: 5,
18 },
19 stack: [
20 {
21 functionName: "SubmitButton",
22 fileName: "/repo/src/Button.tsx",
23 lineNumber: 12,
24 columnNumber: 5,
25 },
26 ],
27 styles: ".submit { color: white; }",
28 pickedAt: "2026-05-03T18:00:00.000Z",
29 ...overrides,
30 };
31}
32
33describe("isPickedElementPayload", () => {
34 it("rejects non-finite numeric line/column numbers", () => {
35 expect(
36 isPickedElementPayload(
37 validPayload({
38 source: {
39 functionName: null,
40 fileName: null,
41 lineNumber: Number.POSITIVE_INFINITY,
42 columnNumber: null,
43 },
44 }),
45 ),
46 ).toBe(false);
47 expect(
48 isPickedElementPayload(
49 validPayload({
50 source: {
51 functionName: null,
52 fileName: null,
53 lineNumber: Number.NaN,
54 columnNumber: null,
55 },
56 }),
57 ),
58 ).toBe(false);
59 });
60});
61
62function validAnnotation(overrides?: Record<string, unknown>): Record<string, unknown> {
63 return {
64 id: "annotation_1",
65 pageUrl: "https://example.com/",
66 pageTitle: "Example",
67 comment: "Make this clearer",
68 elements: [
69 {
70 id: "element_1",
71 element: validPayload(),
72 rect: { x: 10, y: 20, width: 100, height: 40 },
73 },
74 ],
75 regions: [{ id: "region_1", rect: { x: 5, y: 6, width: 20, height: 30 } }],
76 strokes: [
77 {
78 id: "stroke_1",
79 color: "#7c3aed",
80 width: 4,
81 points: [
82 { x: 10, y: 10 },
83 { x: 20, y: 20 },
84 ],
85 bounds: { x: 6, y: 6, width: 18, height: 18 },
86 },
87 ],
88 styleChanges: [
89 {
90 targetId: "element_1",
91 selector: "button.submit",
92 property: "opacity",
93 previousValue: "1",
94 value: "0.5",
95 },
96 ],
97 screenshot: null,
98 createdAt: "2026-06-11T00:00:00.000Z",
99 ...overrides,
100 };
101}
102
103describe("isPreviewAnnotationPayload", () => {
104 it("rejects screenshots supplied by the guest preload", () => {
105 expect(isPreviewAnnotationPayload(validAnnotation({ screenshot: { dataUrl: "bad" } }))).toBe(
106 false,
107 );
108 });
109});