@node-edit-utils/core 2.3.3 → 2.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/lib/viewport/label/getViewportLabelOverlay.d.ts +1 -0
  2. package/dist/lib/viewport/label/index.d.ts +5 -3
  3. package/dist/lib/viewport/label/isViewportDragging.d.ts +2 -0
  4. package/dist/lib/viewport/label/refreshViewportLabel.d.ts +8 -0
  5. package/dist/lib/viewport/label/removeViewportLabel.d.ts +5 -0
  6. package/dist/lib/viewport/label/setupViewportDrag.d.ts +1 -0
  7. package/dist/node-edit-utils.cjs.js +100 -62
  8. package/dist/node-edit-utils.esm.js +100 -62
  9. package/dist/node-edit-utils.umd.js +100 -62
  10. package/dist/node-edit-utils.umd.min.js +1 -1
  11. package/dist/styles.css +1 -1
  12. package/package.json +7 -2
  13. package/src/lib/canvas/createCanvasObserver.test.ts +242 -0
  14. package/src/lib/canvas/disableCanvasKeyboard.test.ts +53 -0
  15. package/src/lib/canvas/disableCanvasKeyboard.ts +1 -1
  16. package/src/lib/canvas/disableCanvasTextMode.test.ts +53 -0
  17. package/src/lib/canvas/disableCanvasTextMode.ts +1 -1
  18. package/src/lib/canvas/enableCanvasKeyboard.test.ts +53 -0
  19. package/src/lib/canvas/enableCanvasKeyboard.ts +1 -1
  20. package/src/lib/canvas/enableCanvasTextMode.test.ts +53 -0
  21. package/src/lib/canvas/enableCanvasTextMode.ts +1 -1
  22. package/src/lib/canvas/helpers/applyCanvasState.test.ts +119 -0
  23. package/src/lib/canvas/helpers/applyCanvasState.ts +1 -1
  24. package/src/lib/canvas/helpers/getCanvasContainer.test.ts +62 -0
  25. package/src/lib/canvas/helpers/getCanvasContainerOrBody.test.ts +51 -0
  26. package/src/lib/canvas/helpers/getCanvasWindowValue.test.ts +116 -0
  27. package/src/lib/helpers/adjustForZoom.test.ts +65 -0
  28. package/src/lib/helpers/createDragHandler.test.ts +325 -0
  29. package/src/lib/helpers/getNodeProvider.test.ts +71 -0
  30. package/src/lib/helpers/getNodeTools.test.ts +50 -0
  31. package/src/lib/helpers/getViewportDimensions.test.ts +93 -0
  32. package/src/lib/helpers/observer/connectMutationObserver.test.ts +127 -0
  33. package/src/lib/helpers/observer/connectResizeObserver.test.ts +147 -0
  34. package/src/lib/helpers/parseTransform.test.ts +117 -0
  35. package/src/lib/helpers/toggleClass.test.ts +71 -0
  36. package/src/lib/helpers/withRAF.test.ts +439 -0
  37. package/src/lib/node-tools/createNodeTools.test.ts +373 -0
  38. package/src/lib/node-tools/events/click/handleNodeClick.test.ts +109 -0
  39. package/src/lib/node-tools/events/setupEventListener.test.ts +136 -0
  40. package/src/lib/node-tools/highlight/clearHighlightFrame.test.ts +88 -0
  41. package/src/lib/node-tools/highlight/createCornerHandles.test.ts +150 -0
  42. package/src/lib/node-tools/highlight/createHighlightFrame.test.ts +237 -0
  43. package/src/lib/node-tools/highlight/createTagLabel.test.ts +135 -0
  44. package/src/lib/node-tools/highlight/createToolsContainer.test.ts +97 -0
  45. package/src/lib/node-tools/highlight/helpers/getElementBounds.test.ts +158 -0
  46. package/src/lib/node-tools/highlight/helpers/getHighlightFrameElement.test.ts +78 -0
  47. package/src/lib/node-tools/highlight/helpers/getScreenBounds.test.ts +133 -0
  48. package/src/lib/node-tools/highlight/highlightNode.test.ts +213 -0
  49. package/src/lib/node-tools/highlight/refreshHighlightFrame.test.ts +323 -0
  50. package/src/lib/node-tools/highlight/updateHighlightFrameVisibility.test.ts +110 -0
  51. package/src/lib/node-tools/select/helpers/getElementsFromPoint.test.ts +109 -0
  52. package/src/lib/node-tools/select/helpers/isInsideComponent.test.ts +81 -0
  53. package/src/lib/node-tools/select/helpers/isInsideViewport.test.ts +82 -0
  54. package/src/lib/node-tools/select/helpers/targetSameCandidates.test.ts +81 -0
  55. package/src/lib/node-tools/select/selectNode.test.ts +238 -0
  56. package/src/lib/node-tools/text/events/setupKeydownHandler.test.ts +91 -0
  57. package/src/lib/node-tools/text/events/setupMutationObserver.test.ts +213 -0
  58. package/src/lib/node-tools/text/events/setupNodeListeners.test.ts +133 -0
  59. package/src/lib/node-tools/text/helpers/enterTextEditMode.test.ts +50 -0
  60. package/src/lib/node-tools/text/helpers/handleTextChange.test.ts +201 -0
  61. package/src/lib/node-tools/text/helpers/hasTextContent.test.ts +101 -0
  62. package/src/lib/node-tools/text/helpers/insertLineBreak.test.ts +96 -0
  63. package/src/lib/node-tools/text/helpers/makeNodeEditable.test.ts +56 -0
  64. package/src/lib/node-tools/text/helpers/makeNodeNonEditable.test.ts +57 -0
  65. package/src/lib/node-tools/text/helpers/shouldEnterTextEditMode.test.ts +61 -0
  66. package/src/lib/node-tools/text/nodeText.test.ts +233 -0
  67. package/src/lib/post-message/processPostMessage.test.ts +218 -0
  68. package/src/lib/post-message/sendPostMessage.test.ts +120 -0
  69. package/src/lib/styles/styles.css +2 -2
  70. package/src/lib/viewport/createViewport.test.ts +267 -0
  71. package/src/lib/viewport/createViewport.ts +7 -4
  72. package/src/lib/viewport/events/setupEventListener.test.ts +103 -0
  73. package/src/lib/viewport/label/getViewportLabelOverlay.test.ts +77 -0
  74. package/src/lib/viewport/label/{getViewportLabelsOverlay.ts → getViewportLabelOverlay.ts} +2 -1
  75. package/src/lib/viewport/label/helpers/getLabelPosition.test.ts +51 -0
  76. package/src/lib/viewport/label/helpers/getTransformValues.test.ts +59 -0
  77. package/src/lib/viewport/label/helpers/getZoomValue.test.ts +53 -0
  78. package/src/lib/viewport/label/helpers/selectFirstViewportNode.test.ts +105 -0
  79. package/src/lib/viewport/label/helpers/selectFirstViewportNode.ts +8 -0
  80. package/src/lib/viewport/label/index.ts +5 -3
  81. package/src/lib/viewport/label/isViewportDragging.test.ts +35 -0
  82. package/src/lib/viewport/label/isViewportDragging.ts +9 -0
  83. package/src/lib/viewport/label/refreshViewportLabel.test.ts +105 -0
  84. package/src/lib/viewport/label/refreshViewportLabel.ts +50 -0
  85. package/src/lib/viewport/label/refreshViewportLabels.test.ts +107 -0
  86. package/src/lib/viewport/label/refreshViewportLabels.ts +17 -50
  87. package/src/lib/viewport/label/removeViewportLabel.test.ts +67 -0
  88. package/src/lib/viewport/label/removeViewportLabel.ts +20 -0
  89. package/src/lib/viewport/label/setupViewportDrag.test.ts +249 -0
  90. package/src/lib/viewport/label/{setupViewportLabelDrag.ts → setupViewportDrag.ts} +14 -14
  91. package/src/lib/viewport/resize/createResizeHandle.test.ts +37 -0
  92. package/src/lib/viewport/resize/createResizePresets.test.ts +75 -0
  93. package/src/lib/viewport/resize/updateActivePreset.test.ts +92 -0
  94. package/src/lib/viewport/width/calcConstrainedWidth.test.ts +47 -0
  95. package/src/lib/viewport/width/calcWidth.test.ts +68 -0
  96. package/src/lib/viewport/width/updateWidth.test.ts +78 -0
  97. package/src/lib/window/bindToWindow.test.ts +166 -0
  98. package/dist/lib/viewport/label/getViewportLabelsOverlay.d.ts +0 -1
  99. package/dist/lib/viewport/label/isViewportLabelDragging.d.ts +0 -2
  100. package/dist/lib/viewport/label/setupViewportLabelDrag.d.ts +0 -1
  101. package/src/lib/viewport/label/isViewportLabelDragging.ts +0 -9
@@ -0,0 +1,323 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import * as getCanvasContainerOrBodyModule from "@/lib/canvas/helpers/getCanvasContainerOrBody";
3
+ import * as getCanvasWindowValueModule from "@/lib/canvas/helpers/getCanvasWindowValue";
4
+ import * as getViewportDimensionsModule from "@/lib/helpers/getViewportDimensions";
5
+ import * as toggleClassModule from "@/lib/helpers/toggleClass";
6
+ import * as isComponentInstanceModule from "../select/helpers/isComponentInstance";
7
+ import * as getHighlightFrameElementModule from "./helpers/getHighlightFrameElement";
8
+ import * as getScreenBoundsModule from "./helpers/getScreenBounds";
9
+ import { refreshHighlightFrame } from "./refreshHighlightFrame";
10
+
11
+ vi.mock("@/lib/canvas/helpers/getCanvasContainerOrBody");
12
+ vi.mock("@/lib/canvas/helpers/getCanvasWindowValue");
13
+ vi.mock("@/lib/helpers/getViewportDimensions");
14
+ vi.mock("@/lib/helpers/toggleClass");
15
+ vi.mock("../select/helpers/isComponentInstance");
16
+ vi.mock("./helpers/getHighlightFrameElement");
17
+ vi.mock("./helpers/getScreenBounds");
18
+
19
+ describe("refreshHighlightFrame", () => {
20
+ let node: HTMLElement;
21
+ let nodeProvider: HTMLElement;
22
+ let container: HTMLElement;
23
+ let frame: SVGSVGElement;
24
+ let group: SVGGElement;
25
+ let rect: SVGRectElement;
26
+ let toolsWrapper: HTMLElement;
27
+ let nodeTools: HTMLElement;
28
+
29
+ beforeEach(() => {
30
+ node = document.createElement("div");
31
+ node.setAttribute("data-node-id", "test-node");
32
+ document.body.appendChild(node);
33
+
34
+ nodeProvider = document.createElement("div");
35
+ document.body.appendChild(nodeProvider);
36
+
37
+ container = document.createElement("div");
38
+ document.body.appendChild(container);
39
+
40
+ frame = document.createElementNS("http://www.w3.org/2000/svg", "svg");
41
+ frame.classList.add("highlight-frame-overlay");
42
+ container.appendChild(frame);
43
+
44
+ group = document.createElementNS("http://www.w3.org/2000/svg", "g");
45
+ group.classList.add("highlight-frame-group");
46
+ frame.appendChild(group);
47
+
48
+ rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
49
+ group.appendChild(rect);
50
+
51
+ toolsWrapper = document.createElement("div");
52
+ toolsWrapper.classList.add("highlight-frame-tools-wrapper");
53
+ container.appendChild(toolsWrapper);
54
+
55
+ nodeTools = document.createElement("div");
56
+ nodeTools.classList.add("node-tools");
57
+ toolsWrapper.appendChild(nodeTools);
58
+
59
+ vi.mocked(getCanvasContainerOrBodyModule.getCanvasContainerOrBody).mockReturnValue(container);
60
+ vi.mocked(getHighlightFrameElementModule.getHighlightFrameElement).mockReturnValue(frame);
61
+ vi.mocked(getViewportDimensionsModule.getViewportDimensions).mockReturnValue({
62
+ width: 1920,
63
+ height: 1080,
64
+ });
65
+ vi.mocked(getScreenBoundsModule.getScreenBounds).mockReturnValue({
66
+ top: 100,
67
+ left: 200,
68
+ width: 300,
69
+ height: 400,
70
+ });
71
+ vi.mocked(getCanvasWindowValueModule.getCanvasWindowValue).mockReturnValue(1);
72
+ vi.mocked(isComponentInstanceModule.isComponentInstance).mockReturnValue(false);
73
+ vi.mocked(toggleClassModule.toggleClass).mockImplementation(() => {});
74
+ });
75
+
76
+ afterEach(() => {
77
+ if (document.body.contains(node)) {
78
+ document.body.removeChild(node);
79
+ }
80
+ if (document.body.contains(nodeProvider)) {
81
+ document.body.removeChild(nodeProvider);
82
+ }
83
+ if (document.body.contains(container)) {
84
+ document.body.removeChild(container);
85
+ }
86
+ vi.clearAllMocks();
87
+ });
88
+
89
+ it("should do nothing when frame does not exist", () => {
90
+ vi.mocked(getHighlightFrameElementModule.getHighlightFrameElement).mockReturnValue(null);
91
+
92
+ expect(() => {
93
+ refreshHighlightFrame(node, nodeProvider);
94
+ }).not.toThrow();
95
+ });
96
+
97
+ it("should update SVG dimensions", () => {
98
+ refreshHighlightFrame(node, nodeProvider);
99
+
100
+ expect(frame.getAttribute("width")).toBe("1920");
101
+ expect(frame.getAttribute("height")).toBe("1080");
102
+ });
103
+
104
+ it("should toggle is-instance class", () => {
105
+ vi.mocked(isComponentInstanceModule.isComponentInstance).mockReturnValue(true);
106
+
107
+ refreshHighlightFrame(node, nodeProvider);
108
+
109
+ expect(toggleClassModule.toggleClass).toHaveBeenCalledWith(frame, "is-instance", true);
110
+ });
111
+
112
+ it("should toggle is-text-edit class", () => {
113
+ node.contentEditable = "true";
114
+
115
+ refreshHighlightFrame(node, nodeProvider);
116
+
117
+ expect(toggleClassModule.toggleClass).toHaveBeenCalledWith(frame, "is-text-edit", true);
118
+ });
119
+
120
+ it("should update group transform", () => {
121
+ refreshHighlightFrame(node, nodeProvider);
122
+
123
+ expect(group.getAttribute("transform")).toBe("translate(200, 100)");
124
+ });
125
+
126
+ it("should update rect dimensions", () => {
127
+ refreshHighlightFrame(node, nodeProvider);
128
+
129
+ expect(rect.getAttribute("width")).toBe("300");
130
+ expect(rect.getAttribute("height")).toBe("400");
131
+ });
132
+
133
+ it("should ensure minimum width of 3", () => {
134
+ vi.mocked(getScreenBoundsModule.getScreenBounds).mockReturnValue({
135
+ top: 100,
136
+ left: 200,
137
+ width: 1,
138
+ height: 400,
139
+ });
140
+
141
+ refreshHighlightFrame(node, nodeProvider);
142
+
143
+ expect(rect.getAttribute("width")).toBe("3");
144
+ });
145
+
146
+ it("should apply instance color when isInstance is true", () => {
147
+ const originalGetComputedStyle = window.getComputedStyle;
148
+ window.getComputedStyle = vi.fn().mockReturnValue({
149
+ getPropertyValue: vi.fn((prop: string) => {
150
+ if (prop === "--component-color") return "rgb(255, 0, 0)";
151
+ return "";
152
+ }),
153
+ } as unknown as CSSStyleDeclaration);
154
+
155
+ vi.mocked(isComponentInstanceModule.isComponentInstance).mockReturnValue(true);
156
+
157
+ refreshHighlightFrame(node, nodeProvider);
158
+
159
+ expect(rect.getAttribute("stroke")).toBe("rgb(255, 0, 0)");
160
+
161
+ window.getComputedStyle = originalGetComputedStyle;
162
+ });
163
+
164
+ it("should apply text edit color when isTextEdit is true", () => {
165
+ const originalGetComputedStyle = window.getComputedStyle;
166
+ window.getComputedStyle = vi.fn().mockReturnValue({
167
+ getPropertyValue: vi.fn((prop: string) => {
168
+ if (prop === "--text-edit-color") return "rgb(0, 255, 0)";
169
+ return "";
170
+ }),
171
+ } as unknown as CSSStyleDeclaration);
172
+
173
+ node.contentEditable = "true";
174
+
175
+ refreshHighlightFrame(node, nodeProvider);
176
+
177
+ expect(rect.getAttribute("stroke")).toBe("rgb(0, 255, 0)");
178
+
179
+ window.getComputedStyle = originalGetComputedStyle;
180
+ });
181
+
182
+ it("should remove stroke when neither flag is true", () => {
183
+ rect.setAttribute("stroke", "rgb(255, 0, 0)");
184
+
185
+ refreshHighlightFrame(node, nodeProvider);
186
+
187
+ expect(rect.getAttribute("stroke")).toBeNull();
188
+ });
189
+
190
+ it("should update tools wrapper transform", () => {
191
+ refreshHighlightFrame(node, nodeProvider);
192
+
193
+ expect(toolsWrapper.style.transform).toBe("translate(200px, 500px)");
194
+ });
195
+
196
+ it("should toggle classes on tools wrapper", () => {
197
+ refreshHighlightFrame(node, nodeProvider);
198
+
199
+ expect(toggleClassModule.toggleClass).toHaveBeenCalledWith(toolsWrapper, "is-instance", false);
200
+ expect(toggleClassModule.toggleClass).toHaveBeenCalledWith(toolsWrapper, "is-text-edit", false);
201
+ });
202
+
203
+ it("should toggle classes on node tools", () => {
204
+ refreshHighlightFrame(node, nodeProvider);
205
+
206
+ expect(toggleClassModule.toggleClass).toHaveBeenCalledWith(nodeTools, "is-instance", false);
207
+ expect(toggleClassModule.toggleClass).toHaveBeenCalledWith(nodeTools, "is-text-edit", false);
208
+ });
209
+
210
+ it("should update tool opacity when zoom <= 10", () => {
211
+ vi.mocked(getCanvasWindowValueModule.getCanvasWindowValue).mockReturnValue(5);
212
+
213
+ refreshHighlightFrame(node, nodeProvider);
214
+
215
+ expect(nodeProvider.style.getPropertyValue("--tool-opacity")).toBe("1");
216
+ });
217
+
218
+ it("should set tool opacity to 0 when zoom > 10", () => {
219
+ vi.mocked(getCanvasWindowValueModule.getCanvasWindowValue).mockReturnValue(15);
220
+
221
+ refreshHighlightFrame(node, nodeProvider);
222
+
223
+ expect(nodeProvider.style.getPropertyValue("--tool-opacity")).toBe("0");
224
+ });
225
+
226
+ it("should use default zoom of 1 when zoom is undefined", () => {
227
+ vi.mocked(getCanvasWindowValueModule.getCanvasWindowValue).mockReturnValue(undefined);
228
+
229
+ refreshHighlightFrame(node, nodeProvider);
230
+
231
+ expect(nodeProvider.style.getPropertyValue("--tool-opacity")).toBe("1");
232
+ });
233
+
234
+ it("should use custom canvas name", () => {
235
+ refreshHighlightFrame(node, nodeProvider, "custom-canvas");
236
+
237
+ expect(getCanvasWindowValueModule.getCanvasWindowValue).toHaveBeenCalledWith(["zoom", "current"], "custom-canvas");
238
+ });
239
+
240
+ it("should update corner handle positions", () => {
241
+ const topLeft = document.createElementNS("http://www.w3.org/2000/svg", "rect");
242
+ topLeft.classList.add("handle-top-left");
243
+ group.appendChild(topLeft);
244
+
245
+ refreshHighlightFrame(node, nodeProvider);
246
+
247
+ expect(topLeft.getAttribute("x")).toBe("-3");
248
+ expect(topLeft.getAttribute("y")).toBe("-3");
249
+ });
250
+
251
+ it("should update all corner handles", () => {
252
+ const topLeft = document.createElementNS("http://www.w3.org/2000/svg", "rect");
253
+ topLeft.classList.add("handle-top-left");
254
+ const topRight = document.createElementNS("http://www.w3.org/2000/svg", "rect");
255
+ topRight.classList.add("handle-top-right");
256
+ const bottomRight = document.createElementNS("http://www.w3.org/2000/svg", "rect");
257
+ bottomRight.classList.add("handle-bottom-right");
258
+ const bottomLeft = document.createElementNS("http://www.w3.org/2000/svg", "rect");
259
+ bottomLeft.classList.add("handle-bottom-left");
260
+ group.appendChild(topLeft);
261
+ group.appendChild(topRight);
262
+ group.appendChild(bottomRight);
263
+ group.appendChild(bottomLeft);
264
+
265
+ refreshHighlightFrame(node, nodeProvider);
266
+
267
+ expect(topLeft.getAttribute("x")).toBe("-3");
268
+ expect(topLeft.getAttribute("y")).toBe("-3");
269
+ expect(topRight.getAttribute("x")).toBe("297");
270
+ expect(topRight.getAttribute("y")).toBe("-3");
271
+ expect(bottomRight.getAttribute("x")).toBe("297");
272
+ expect(bottomRight.getAttribute("y")).toBe("397");
273
+ expect(bottomLeft.getAttribute("x")).toBe("-3");
274
+ expect(bottomLeft.getAttribute("y")).toBe("397");
275
+ });
276
+
277
+ it("should update handle colors for instance", () => {
278
+ const originalGetComputedStyle = window.getComputedStyle;
279
+ window.getComputedStyle = vi.fn().mockReturnValue({
280
+ getPropertyValue: vi.fn((prop: string) => {
281
+ if (prop === "--component-color") return "rgb(255, 0, 0)";
282
+ return "";
283
+ }),
284
+ } as unknown as CSSStyleDeclaration);
285
+
286
+ const handle = document.createElementNS("http://www.w3.org/2000/svg", "rect");
287
+ handle.classList.add("handle-top-left");
288
+ group.appendChild(handle);
289
+
290
+ vi.mocked(isComponentInstanceModule.isComponentInstance).mockReturnValue(true);
291
+
292
+ refreshHighlightFrame(node, nodeProvider);
293
+
294
+ expect(handle.getAttribute("stroke")).toBe("rgb(255, 0, 0)");
295
+
296
+ window.getComputedStyle = originalGetComputedStyle;
297
+ });
298
+
299
+ it("should not update when group does not exist", () => {
300
+ group.remove();
301
+
302
+ expect(() => {
303
+ refreshHighlightFrame(node, nodeProvider);
304
+ }).not.toThrow();
305
+ });
306
+
307
+ it("should not update when rect does not exist", () => {
308
+ rect.remove();
309
+
310
+ expect(() => {
311
+ refreshHighlightFrame(node, nodeProvider);
312
+ }).not.toThrow();
313
+ });
314
+
315
+ it("should not update tools wrapper when it does not exist", () => {
316
+ container.removeChild(toolsWrapper);
317
+
318
+ expect(() => {
319
+ refreshHighlightFrame(node, nodeProvider);
320
+ }).not.toThrow();
321
+ });
322
+ });
323
+
@@ -0,0 +1,110 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import * as getCanvasContainerOrBodyModule from "@/lib/canvas/helpers/getCanvasContainerOrBody";
3
+ import * as getHighlightFrameElementModule from "./helpers/getHighlightFrameElement";
4
+ import { updateHighlightFrameVisibility } from "./updateHighlightFrameVisibility";
5
+
6
+ vi.mock("@/lib/canvas/helpers/getCanvasContainerOrBody");
7
+ vi.mock("./helpers/getHighlightFrameElement");
8
+
9
+ describe("updateHighlightFrameVisibility", () => {
10
+ let container: HTMLElement;
11
+ let frame: SVGSVGElement;
12
+ let toolsWrapper: HTMLElement;
13
+ let node: HTMLElement;
14
+
15
+ beforeEach(() => {
16
+ container = document.createElement("div");
17
+ document.body.appendChild(container);
18
+
19
+ frame = document.createElementNS("http://www.w3.org/2000/svg", "svg");
20
+ frame.classList.add("highlight-frame-overlay");
21
+ container.appendChild(frame);
22
+
23
+ toolsWrapper = document.createElement("div");
24
+ toolsWrapper.classList.add("highlight-frame-tools-wrapper");
25
+ container.appendChild(toolsWrapper);
26
+
27
+ node = document.createElement("div");
28
+ document.body.appendChild(node);
29
+
30
+ vi.mocked(getCanvasContainerOrBodyModule.getCanvasContainerOrBody).mockReturnValue(container);
31
+ vi.mocked(getHighlightFrameElementModule.getHighlightFrameElement).mockReturnValue(frame);
32
+ });
33
+
34
+ afterEach(() => {
35
+ if (document.body.contains(container)) {
36
+ document.body.removeChild(container);
37
+ }
38
+ if (document.body.contains(node)) {
39
+ document.body.removeChild(node);
40
+ }
41
+ vi.clearAllMocks();
42
+ });
43
+
44
+ it("should set display to empty string when node is visible", () => {
45
+ updateHighlightFrameVisibility(node);
46
+
47
+ expect(frame.style.display).toBe("");
48
+ expect(toolsWrapper.style.display).toBe("");
49
+ });
50
+
51
+ it("should set display to none when node has hidden class", () => {
52
+ node.classList.add("hidden");
53
+
54
+ updateHighlightFrameVisibility(node);
55
+
56
+ expect(frame.style.display).toBe("none");
57
+ expect(toolsWrapper.style.display).toBe("none");
58
+ });
59
+
60
+ it("should set display to none when node has select-none class", () => {
61
+ node.classList.add("select-none");
62
+
63
+ updateHighlightFrameVisibility(node);
64
+
65
+ expect(frame.style.display).toBe("none");
66
+ expect(toolsWrapper.style.display).toBe("none");
67
+ });
68
+
69
+ it("should set display to none when node has both hidden and select-none classes", () => {
70
+ node.classList.add("hidden");
71
+ node.classList.add("select-none");
72
+
73
+ updateHighlightFrameVisibility(node);
74
+
75
+ expect(frame.style.display).toBe("none");
76
+ expect(toolsWrapper.style.display).toBe("none");
77
+ });
78
+
79
+ it("should not update when frame does not exist", () => {
80
+ vi.mocked(getHighlightFrameElementModule.getHighlightFrameElement).mockReturnValue(null);
81
+
82
+ expect(() => {
83
+ updateHighlightFrameVisibility(node);
84
+ }).not.toThrow();
85
+
86
+ expect(toolsWrapper.style.display).toBe("");
87
+ });
88
+
89
+ it("should not update tools wrapper when it does not exist", () => {
90
+ container.removeChild(toolsWrapper);
91
+
92
+ updateHighlightFrameVisibility(node);
93
+
94
+ expect(frame.style.display).toBe("");
95
+ });
96
+
97
+ it("should toggle visibility when classes change", () => {
98
+ updateHighlightFrameVisibility(node);
99
+ expect(frame.style.display).toBe("");
100
+
101
+ node.classList.add("hidden");
102
+ updateHighlightFrameVisibility(node);
103
+ expect(frame.style.display).toBe("none");
104
+
105
+ node.classList.remove("hidden");
106
+ updateHighlightFrameVisibility(node);
107
+ expect(frame.style.display).toBe("");
108
+ });
109
+ });
110
+
@@ -0,0 +1,109 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { getElementsFromPoint } from "./getElementsFromPoint";
3
+
4
+ describe("getElementsFromPoint", () => {
5
+ let nodeProvider: HTMLElement;
6
+ let element1: HTMLElement;
7
+ let element2: HTMLElement;
8
+
9
+ beforeEach(() => {
10
+ nodeProvider = document.createElement("div");
11
+ nodeProvider.setAttribute("data-role", "node-provider");
12
+ document.body.appendChild(nodeProvider);
13
+
14
+ element1 = document.createElement("div");
15
+ element1.setAttribute("data-node-id", "node-1");
16
+ nodeProvider.appendChild(element1);
17
+
18
+ element2 = document.createElement("div");
19
+ element2.setAttribute("data-node-id", "node-2");
20
+ element1.appendChild(element2);
21
+ });
22
+
23
+ afterEach(() => {
24
+ if (document.body.contains(nodeProvider)) {
25
+ document.body.removeChild(nodeProvider);
26
+ }
27
+ vi.clearAllMocks();
28
+ });
29
+
30
+ it("should return elements up to node-provider", () => {
31
+ const mockElements = [element2, element1, nodeProvider];
32
+ Object.defineProperty(document, "elementsFromPoint", {
33
+ value: vi.fn().mockReturnValue(mockElements),
34
+ writable: true,
35
+ configurable: true,
36
+ });
37
+
38
+ const result = getElementsFromPoint(100, 200);
39
+
40
+ expect(result).toEqual([element2, element1]);
41
+ });
42
+
43
+ it("should return empty array when node-provider is first element", () => {
44
+ const mockElements = [nodeProvider, element1, element2];
45
+ Object.defineProperty(document, "elementsFromPoint", {
46
+ value: vi.fn().mockReturnValue(mockElements),
47
+ writable: true,
48
+ configurable: true,
49
+ });
50
+
51
+ const result = getElementsFromPoint(100, 200);
52
+
53
+ expect(result).toEqual([]);
54
+ });
55
+
56
+ it("should return all elements before node-provider", () => {
57
+ const element3 = document.createElement("div");
58
+ const mockElements = [element3, element2, element1, nodeProvider];
59
+ Object.defineProperty(document, "elementsFromPoint", {
60
+ value: vi.fn().mockReturnValue(mockElements),
61
+ writable: true,
62
+ configurable: true,
63
+ });
64
+
65
+ const result = getElementsFromPoint(100, 200);
66
+
67
+ expect(result).toEqual([element3, element2, element1]);
68
+ });
69
+
70
+ it("should return empty array when no elements", () => {
71
+ Object.defineProperty(document, "elementsFromPoint", {
72
+ value: vi.fn().mockReturnValue([]),
73
+ writable: true,
74
+ configurable: true,
75
+ });
76
+
77
+ const result = getElementsFromPoint(100, 200);
78
+
79
+ expect(result).toEqual([]);
80
+ });
81
+
82
+ it("should return all elements when node-provider is not present", () => {
83
+ const mockElements = [element2, element1];
84
+ Object.defineProperty(document, "elementsFromPoint", {
85
+ value: vi.fn().mockReturnValue(mockElements),
86
+ writable: true,
87
+ configurable: true,
88
+ });
89
+
90
+ const result = getElementsFromPoint(100, 200);
91
+
92
+ expect(result).toEqual([element2, element1]);
93
+ });
94
+
95
+ it("should handle node-provider in middle of elements", () => {
96
+ const element3 = document.createElement("div");
97
+ const mockElements = [element3, nodeProvider, element2, element1];
98
+ Object.defineProperty(document, "elementsFromPoint", {
99
+ value: vi.fn().mockReturnValue(mockElements),
100
+ writable: true,
101
+ configurable: true,
102
+ });
103
+
104
+ const result = getElementsFromPoint(100, 200);
105
+
106
+ expect(result).toEqual([element3]);
107
+ });
108
+ });
109
+
@@ -0,0 +1,81 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
+ import { isInsideComponent } from "./isInsideComponent";
3
+
4
+ describe("isInsideComponent", () => {
5
+ let nodeProvider: HTMLElement;
6
+ let component: HTMLElement;
7
+ let element: HTMLElement;
8
+
9
+ beforeEach(() => {
10
+ nodeProvider = document.createElement("div");
11
+ nodeProvider.setAttribute("data-role", "node-provider");
12
+ document.body.appendChild(nodeProvider);
13
+
14
+ component = document.createElement("div");
15
+ component.setAttribute("data-instance", "true");
16
+ nodeProvider.appendChild(component);
17
+
18
+ element = document.createElement("div");
19
+ component.appendChild(element);
20
+ });
21
+
22
+ afterEach(() => {
23
+ if (document.body.contains(nodeProvider)) {
24
+ document.body.removeChild(nodeProvider);
25
+ }
26
+ });
27
+
28
+ it("should return true when element is inside component", () => {
29
+ const result = isInsideComponent(element);
30
+
31
+ expect(result).toBe(true);
32
+ });
33
+
34
+ it("should return true when element is nested inside component", () => {
35
+ const nested = document.createElement("div");
36
+ element.appendChild(nested);
37
+
38
+ const result = isInsideComponent(nested);
39
+
40
+ expect(result).toBe(true);
41
+ });
42
+
43
+ it("should return false when element is not inside component", () => {
44
+ const outsideElement = document.createElement("div");
45
+ nodeProvider.appendChild(outsideElement);
46
+
47
+ const result = isInsideComponent(outsideElement);
48
+
49
+ expect(result).toBe(false);
50
+ });
51
+
52
+ it("should stop at node-provider", () => {
53
+ const elementOutsideComponent = document.createElement("div");
54
+ nodeProvider.appendChild(elementOutsideComponent);
55
+
56
+ const result = isInsideComponent(elementOutsideComponent);
57
+
58
+ expect(result).toBe(false);
59
+ });
60
+
61
+ it("should return false when element is direct child of node-provider", () => {
62
+ const directChild = document.createElement("div");
63
+ nodeProvider.appendChild(directChild);
64
+
65
+ const result = isInsideComponent(directChild);
66
+
67
+ expect(result).toBe(false);
68
+ });
69
+
70
+ it("should handle component without data-instance attribute", () => {
71
+ const nonComponent = document.createElement("div");
72
+ nodeProvider.appendChild(nonComponent);
73
+ const child = document.createElement("div");
74
+ nonComponent.appendChild(child);
75
+
76
+ const result = isInsideComponent(child);
77
+
78
+ expect(result).toBe(false);
79
+ });
80
+ });
81
+