@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.
- package/dist/lib/viewport/label/getViewportLabelOverlay.d.ts +1 -0
- package/dist/lib/viewport/label/index.d.ts +5 -3
- package/dist/lib/viewport/label/isViewportDragging.d.ts +2 -0
- package/dist/lib/viewport/label/refreshViewportLabel.d.ts +8 -0
- package/dist/lib/viewport/label/removeViewportLabel.d.ts +5 -0
- package/dist/lib/viewport/label/setupViewportDrag.d.ts +1 -0
- package/dist/node-edit-utils.cjs.js +100 -62
- package/dist/node-edit-utils.esm.js +100 -62
- package/dist/node-edit-utils.umd.js +100 -62
- package/dist/node-edit-utils.umd.min.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +7 -2
- package/src/lib/canvas/createCanvasObserver.test.ts +242 -0
- package/src/lib/canvas/disableCanvasKeyboard.test.ts +53 -0
- package/src/lib/canvas/disableCanvasKeyboard.ts +1 -1
- package/src/lib/canvas/disableCanvasTextMode.test.ts +53 -0
- package/src/lib/canvas/disableCanvasTextMode.ts +1 -1
- package/src/lib/canvas/enableCanvasKeyboard.test.ts +53 -0
- package/src/lib/canvas/enableCanvasKeyboard.ts +1 -1
- package/src/lib/canvas/enableCanvasTextMode.test.ts +53 -0
- package/src/lib/canvas/enableCanvasTextMode.ts +1 -1
- package/src/lib/canvas/helpers/applyCanvasState.test.ts +119 -0
- package/src/lib/canvas/helpers/applyCanvasState.ts +1 -1
- package/src/lib/canvas/helpers/getCanvasContainer.test.ts +62 -0
- package/src/lib/canvas/helpers/getCanvasContainerOrBody.test.ts +51 -0
- package/src/lib/canvas/helpers/getCanvasWindowValue.test.ts +116 -0
- package/src/lib/helpers/adjustForZoom.test.ts +65 -0
- package/src/lib/helpers/createDragHandler.test.ts +325 -0
- package/src/lib/helpers/getNodeProvider.test.ts +71 -0
- package/src/lib/helpers/getNodeTools.test.ts +50 -0
- package/src/lib/helpers/getViewportDimensions.test.ts +93 -0
- package/src/lib/helpers/observer/connectMutationObserver.test.ts +127 -0
- package/src/lib/helpers/observer/connectResizeObserver.test.ts +147 -0
- package/src/lib/helpers/parseTransform.test.ts +117 -0
- package/src/lib/helpers/toggleClass.test.ts +71 -0
- package/src/lib/helpers/withRAF.test.ts +439 -0
- package/src/lib/node-tools/createNodeTools.test.ts +373 -0
- package/src/lib/node-tools/events/click/handleNodeClick.test.ts +109 -0
- package/src/lib/node-tools/events/setupEventListener.test.ts +136 -0
- package/src/lib/node-tools/highlight/clearHighlightFrame.test.ts +88 -0
- package/src/lib/node-tools/highlight/createCornerHandles.test.ts +150 -0
- package/src/lib/node-tools/highlight/createHighlightFrame.test.ts +237 -0
- package/src/lib/node-tools/highlight/createTagLabel.test.ts +135 -0
- package/src/lib/node-tools/highlight/createToolsContainer.test.ts +97 -0
- package/src/lib/node-tools/highlight/helpers/getElementBounds.test.ts +158 -0
- package/src/lib/node-tools/highlight/helpers/getHighlightFrameElement.test.ts +78 -0
- package/src/lib/node-tools/highlight/helpers/getScreenBounds.test.ts +133 -0
- package/src/lib/node-tools/highlight/highlightNode.test.ts +213 -0
- package/src/lib/node-tools/highlight/refreshHighlightFrame.test.ts +323 -0
- package/src/lib/node-tools/highlight/updateHighlightFrameVisibility.test.ts +110 -0
- package/src/lib/node-tools/select/helpers/getElementsFromPoint.test.ts +109 -0
- package/src/lib/node-tools/select/helpers/isInsideComponent.test.ts +81 -0
- package/src/lib/node-tools/select/helpers/isInsideViewport.test.ts +82 -0
- package/src/lib/node-tools/select/helpers/targetSameCandidates.test.ts +81 -0
- package/src/lib/node-tools/select/selectNode.test.ts +238 -0
- package/src/lib/node-tools/text/events/setupKeydownHandler.test.ts +91 -0
- package/src/lib/node-tools/text/events/setupMutationObserver.test.ts +213 -0
- package/src/lib/node-tools/text/events/setupNodeListeners.test.ts +133 -0
- package/src/lib/node-tools/text/helpers/enterTextEditMode.test.ts +50 -0
- package/src/lib/node-tools/text/helpers/handleTextChange.test.ts +201 -0
- package/src/lib/node-tools/text/helpers/hasTextContent.test.ts +101 -0
- package/src/lib/node-tools/text/helpers/insertLineBreak.test.ts +96 -0
- package/src/lib/node-tools/text/helpers/makeNodeEditable.test.ts +56 -0
- package/src/lib/node-tools/text/helpers/makeNodeNonEditable.test.ts +57 -0
- package/src/lib/node-tools/text/helpers/shouldEnterTextEditMode.test.ts +61 -0
- package/src/lib/node-tools/text/nodeText.test.ts +233 -0
- package/src/lib/post-message/processPostMessage.test.ts +218 -0
- package/src/lib/post-message/sendPostMessage.test.ts +120 -0
- package/src/lib/styles/styles.css +2 -2
- package/src/lib/viewport/createViewport.test.ts +267 -0
- package/src/lib/viewport/createViewport.ts +7 -4
- package/src/lib/viewport/events/setupEventListener.test.ts +103 -0
- package/src/lib/viewport/label/getViewportLabelOverlay.test.ts +77 -0
- package/src/lib/viewport/label/{getViewportLabelsOverlay.ts → getViewportLabelOverlay.ts} +2 -1
- package/src/lib/viewport/label/helpers/getLabelPosition.test.ts +51 -0
- package/src/lib/viewport/label/helpers/getTransformValues.test.ts +59 -0
- package/src/lib/viewport/label/helpers/getZoomValue.test.ts +53 -0
- package/src/lib/viewport/label/helpers/selectFirstViewportNode.test.ts +105 -0
- package/src/lib/viewport/label/helpers/selectFirstViewportNode.ts +8 -0
- package/src/lib/viewport/label/index.ts +5 -3
- package/src/lib/viewport/label/isViewportDragging.test.ts +35 -0
- package/src/lib/viewport/label/isViewportDragging.ts +9 -0
- package/src/lib/viewport/label/refreshViewportLabel.test.ts +105 -0
- package/src/lib/viewport/label/refreshViewportLabel.ts +50 -0
- package/src/lib/viewport/label/refreshViewportLabels.test.ts +107 -0
- package/src/lib/viewport/label/refreshViewportLabels.ts +17 -50
- package/src/lib/viewport/label/removeViewportLabel.test.ts +67 -0
- package/src/lib/viewport/label/removeViewportLabel.ts +20 -0
- package/src/lib/viewport/label/setupViewportDrag.test.ts +249 -0
- package/src/lib/viewport/label/{setupViewportLabelDrag.ts → setupViewportDrag.ts} +14 -14
- package/src/lib/viewport/resize/createResizeHandle.test.ts +37 -0
- package/src/lib/viewport/resize/createResizePresets.test.ts +75 -0
- package/src/lib/viewport/resize/updateActivePreset.test.ts +92 -0
- package/src/lib/viewport/width/calcConstrainedWidth.test.ts +47 -0
- package/src/lib/viewport/width/calcWidth.test.ts +68 -0
- package/src/lib/viewport/width/updateWidth.test.ts +78 -0
- package/src/lib/window/bindToWindow.test.ts +166 -0
- package/dist/lib/viewport/label/getViewportLabelsOverlay.d.ts +0 -1
- package/dist/lib/viewport/label/isViewportLabelDragging.d.ts +0 -2
- package/dist/lib/viewport/label/setupViewportLabelDrag.d.ts +0 -1
- package/src/lib/viewport/label/isViewportLabelDragging.ts +0 -9
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { getNodeTools } from "./getNodeTools";
|
|
3
|
+
|
|
4
|
+
describe("getNodeTools", () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
delete (window as Window & { nodeTools?: unknown }).nodeTools;
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
delete (window as Window & { nodeTools?: unknown }).nodeTools;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should return nodeTools when it exists on window", () => {
|
|
14
|
+
const mockNodeTools = { test: "value" };
|
|
15
|
+
(window as Window & { nodeTools?: unknown }).nodeTools = mockNodeTools;
|
|
16
|
+
|
|
17
|
+
const result = getNodeTools();
|
|
18
|
+
|
|
19
|
+
expect(result).toBe(mockNodeTools);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should return undefined when nodeTools does not exist", () => {
|
|
23
|
+
const result = getNodeTools();
|
|
24
|
+
|
|
25
|
+
expect(result).toBeUndefined();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should return updated value when nodeTools changes", () => {
|
|
29
|
+
const mockNodeTools1 = { test: "value1" };
|
|
30
|
+
(window as Window & { nodeTools?: unknown }).nodeTools = mockNodeTools1;
|
|
31
|
+
const result1 = getNodeTools();
|
|
32
|
+
expect(result1).toBe(mockNodeTools1);
|
|
33
|
+
|
|
34
|
+
const mockNodeTools2 = { test: "value2" };
|
|
35
|
+
(window as Window & { nodeTools?: unknown }).nodeTools = mockNodeTools2;
|
|
36
|
+
const result2 = getNodeTools();
|
|
37
|
+
expect(result2).toBe(mockNodeTools2);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should return undefined after nodeTools is deleted", () => {
|
|
41
|
+
const mockNodeTools = { test: "value" };
|
|
42
|
+
(window as Window & { nodeTools?: unknown }).nodeTools = mockNodeTools;
|
|
43
|
+
const result1 = getNodeTools();
|
|
44
|
+
expect(result1).toBe(mockNodeTools);
|
|
45
|
+
|
|
46
|
+
delete (window as Window & { nodeTools?: unknown }).nodeTools;
|
|
47
|
+
const result2 = getNodeTools();
|
|
48
|
+
expect(result2).toBeUndefined();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { getViewportDimensions } from "./getViewportDimensions";
|
|
3
|
+
|
|
4
|
+
describe("getViewportDimensions", () => {
|
|
5
|
+
it("should return documentElement clientWidth and clientHeight", () => {
|
|
6
|
+
// Mock documentElement dimensions
|
|
7
|
+
Object.defineProperty(document.documentElement, "clientWidth", {
|
|
8
|
+
writable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
value: 1920,
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(document.documentElement, "clientHeight", {
|
|
13
|
+
writable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
value: 1080,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const result = getViewportDimensions();
|
|
19
|
+
|
|
20
|
+
expect(result.width).toBe(1920);
|
|
21
|
+
expect(result.height).toBe(1080);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should fallback to window.innerWidth and innerHeight when clientWidth/clientHeight are 0", () => {
|
|
25
|
+
// Mock documentElement dimensions as 0
|
|
26
|
+
Object.defineProperty(document.documentElement, "clientWidth", {
|
|
27
|
+
writable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
value: 0,
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(document.documentElement, "clientHeight", {
|
|
32
|
+
writable: true,
|
|
33
|
+
configurable: true,
|
|
34
|
+
value: 0,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Mock window dimensions
|
|
38
|
+
Object.defineProperty(window, "innerWidth", {
|
|
39
|
+
writable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
value: 1024,
|
|
42
|
+
});
|
|
43
|
+
Object.defineProperty(window, "innerHeight", {
|
|
44
|
+
writable: true,
|
|
45
|
+
configurable: true,
|
|
46
|
+
value: 768,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const result = getViewportDimensions();
|
|
50
|
+
|
|
51
|
+
expect(result.width).toBe(1024);
|
|
52
|
+
expect(result.height).toBe(768);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should return object with width and height properties", () => {
|
|
56
|
+
Object.defineProperty(document.documentElement, "clientWidth", {
|
|
57
|
+
writable: true,
|
|
58
|
+
configurable: true,
|
|
59
|
+
value: 800,
|
|
60
|
+
});
|
|
61
|
+
Object.defineProperty(document.documentElement, "clientHeight", {
|
|
62
|
+
writable: true,
|
|
63
|
+
configurable: true,
|
|
64
|
+
value: 600,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const result = getViewportDimensions();
|
|
68
|
+
|
|
69
|
+
expect(result).toHaveProperty("width");
|
|
70
|
+
expect(result).toHaveProperty("height");
|
|
71
|
+
expect(typeof result.width).toBe("number");
|
|
72
|
+
expect(typeof result.height).toBe("number");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should handle different viewport sizes", () => {
|
|
76
|
+
Object.defineProperty(document.documentElement, "clientWidth", {
|
|
77
|
+
writable: true,
|
|
78
|
+
configurable: true,
|
|
79
|
+
value: 375,
|
|
80
|
+
});
|
|
81
|
+
Object.defineProperty(document.documentElement, "clientHeight", {
|
|
82
|
+
writable: true,
|
|
83
|
+
configurable: true,
|
|
84
|
+
value: 667,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const result = getViewportDimensions();
|
|
88
|
+
|
|
89
|
+
expect(result.width).toBe(375);
|
|
90
|
+
expect(result.height).toBe(667);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { connectMutationObserver } from "./connectMutationObserver";
|
|
3
|
+
|
|
4
|
+
describe("connectMutationObserver", () => {
|
|
5
|
+
let element: HTMLElement;
|
|
6
|
+
let observer: MutationObserver;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
element = document.createElement("div");
|
|
10
|
+
document.body.appendChild(element);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
if (observer) {
|
|
15
|
+
observer.disconnect();
|
|
16
|
+
}
|
|
17
|
+
if (document.body.contains(element)) {
|
|
18
|
+
document.body.removeChild(element);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should return MutationObserver instance", () => {
|
|
23
|
+
const handler = () => {};
|
|
24
|
+
observer = connectMutationObserver(element, handler);
|
|
25
|
+
|
|
26
|
+
expect(observer).toBeInstanceOf(MutationObserver);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should call handler on childList changes", async () => {
|
|
30
|
+
const handler = vi.fn();
|
|
31
|
+
observer = connectMutationObserver(element, handler);
|
|
32
|
+
|
|
33
|
+
const child = document.createElement("div");
|
|
34
|
+
element.appendChild(child);
|
|
35
|
+
|
|
36
|
+
// Wait for observer to process
|
|
37
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
38
|
+
|
|
39
|
+
expect(handler).toHaveBeenCalled();
|
|
40
|
+
expect(handler).toHaveBeenCalledWith(expect.arrayContaining([expect.any(MutationRecord)]));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should call handler on childList changes", async () => {
|
|
44
|
+
const handler = vi.fn();
|
|
45
|
+
observer = connectMutationObserver(element, handler);
|
|
46
|
+
|
|
47
|
+
// Add a child element
|
|
48
|
+
const child = document.createElement("div");
|
|
49
|
+
element.appendChild(child);
|
|
50
|
+
|
|
51
|
+
// Wait for observer to process
|
|
52
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
53
|
+
|
|
54
|
+
expect(handler).toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should call handler on characterData changes", async () => {
|
|
58
|
+
const handler = vi.fn();
|
|
59
|
+
observer = connectMutationObserver(element, handler);
|
|
60
|
+
|
|
61
|
+
const textNode = document.createTextNode("initial");
|
|
62
|
+
element.appendChild(textNode);
|
|
63
|
+
|
|
64
|
+
// Wait for first mutation
|
|
65
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
66
|
+
handler.mockClear();
|
|
67
|
+
|
|
68
|
+
textNode.textContent = "changed";
|
|
69
|
+
|
|
70
|
+
// Wait for second mutation
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
72
|
+
|
|
73
|
+
expect(handler).toHaveBeenCalled();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should observe subtree changes", async () => {
|
|
77
|
+
const handler = vi.fn();
|
|
78
|
+
observer = connectMutationObserver(element, handler);
|
|
79
|
+
|
|
80
|
+
const child = document.createElement("div");
|
|
81
|
+
element.appendChild(child);
|
|
82
|
+
|
|
83
|
+
// Wait for first mutation
|
|
84
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
85
|
+
handler.mockClear();
|
|
86
|
+
|
|
87
|
+
// Add a grandchild to trigger subtree change
|
|
88
|
+
const grandchild = document.createElement("span");
|
|
89
|
+
child.appendChild(grandchild);
|
|
90
|
+
|
|
91
|
+
// Wait for second mutation
|
|
92
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
93
|
+
|
|
94
|
+
expect(handler).toHaveBeenCalled();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("should pass mutations array to handler", async () => {
|
|
98
|
+
const handler = vi.fn();
|
|
99
|
+
observer = connectMutationObserver(element, handler);
|
|
100
|
+
|
|
101
|
+
const child = document.createElement("div");
|
|
102
|
+
element.appendChild(child);
|
|
103
|
+
|
|
104
|
+
// Wait for observer to process
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
106
|
+
|
|
107
|
+
expect(handler).toHaveBeenCalledWith(expect.any(Array));
|
|
108
|
+
const mutations = handler.mock.calls[0][0];
|
|
109
|
+
expect(mutations.length).toBeGreaterThan(0);
|
|
110
|
+
expect(mutations[0]).toBeInstanceOf(MutationRecord);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should observe multiple changes", async () => {
|
|
114
|
+
const handler = vi.fn();
|
|
115
|
+
observer = connectMutationObserver(element, handler);
|
|
116
|
+
|
|
117
|
+
const child1 = document.createElement("div");
|
|
118
|
+
element.appendChild(child1);
|
|
119
|
+
const child2 = document.createElement("div");
|
|
120
|
+
element.appendChild(child2);
|
|
121
|
+
|
|
122
|
+
// Wait for observer to process
|
|
123
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
124
|
+
|
|
125
|
+
expect(handler).toHaveBeenCalled();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { connectResizeObserver } from "./connectResizeObserver";
|
|
3
|
+
|
|
4
|
+
// Mock ResizeObserver for jsdom environment
|
|
5
|
+
global.ResizeObserver = class ResizeObserver {
|
|
6
|
+
constructor(public callback: ResizeObserverCallback) {}
|
|
7
|
+
observe() {}
|
|
8
|
+
unobserve() {}
|
|
9
|
+
disconnect() {}
|
|
10
|
+
} as unknown as typeof ResizeObserver;
|
|
11
|
+
|
|
12
|
+
describe("connectResizeObserver", () => {
|
|
13
|
+
let element: HTMLElement;
|
|
14
|
+
let observer: ResizeObserver;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
element = document.createElement("div");
|
|
18
|
+
document.body.appendChild(element);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
if (observer) {
|
|
23
|
+
observer.disconnect();
|
|
24
|
+
}
|
|
25
|
+
if (document.body.contains(element)) {
|
|
26
|
+
document.body.removeChild(element);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should return ResizeObserver instance", () => {
|
|
31
|
+
const handler = () => {};
|
|
32
|
+
observer = connectResizeObserver(element, handler);
|
|
33
|
+
|
|
34
|
+
expect(observer).toBeInstanceOf(ResizeObserver);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should call handler on element resize", () => {
|
|
38
|
+
const handler = vi.fn();
|
|
39
|
+
observer = connectResizeObserver(element, handler);
|
|
40
|
+
|
|
41
|
+
// Trigger resize by changing dimensions
|
|
42
|
+
element.style.width = "200px";
|
|
43
|
+
element.style.height = "200px";
|
|
44
|
+
|
|
45
|
+
// Manually trigger the callback since we're mocking ResizeObserver
|
|
46
|
+
// In a real environment, ResizeObserver would call this automatically
|
|
47
|
+
const mockEntry = {
|
|
48
|
+
target: element,
|
|
49
|
+
contentRect: { width: 200, height: 200 },
|
|
50
|
+
borderBoxSize: [],
|
|
51
|
+
contentBoxSize: [],
|
|
52
|
+
devicePixelContentBoxSize: [],
|
|
53
|
+
} as ResizeObserverEntry;
|
|
54
|
+
(observer as unknown as { callback: ResizeObserverCallback }).callback([mockEntry], observer);
|
|
55
|
+
|
|
56
|
+
expect(handler).toHaveBeenCalled();
|
|
57
|
+
expect(handler).toHaveBeenCalledWith([mockEntry]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should pass entries array to handler", () => {
|
|
61
|
+
const handler = vi.fn();
|
|
62
|
+
observer = connectResizeObserver(element, handler);
|
|
63
|
+
|
|
64
|
+
const mockEntry = {
|
|
65
|
+
target: element,
|
|
66
|
+
contentRect: { width: 300, height: 0 },
|
|
67
|
+
borderBoxSize: [],
|
|
68
|
+
contentBoxSize: [],
|
|
69
|
+
devicePixelContentBoxSize: [],
|
|
70
|
+
} as ResizeObserverEntry;
|
|
71
|
+
(observer as unknown as { callback: ResizeObserverCallback }).callback([mockEntry], observer);
|
|
72
|
+
|
|
73
|
+
expect(handler).toHaveBeenCalledWith(expect.any(Array));
|
|
74
|
+
const entries = handler.mock.calls[0][0];
|
|
75
|
+
expect(entries.length).toBeGreaterThan(0);
|
|
76
|
+
expect(entries[0]).toBeInstanceOf(Object);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("should observe width changes", () => {
|
|
80
|
+
const handler = vi.fn();
|
|
81
|
+
observer = connectResizeObserver(element, handler);
|
|
82
|
+
|
|
83
|
+
const mockEntry = {
|
|
84
|
+
target: element,
|
|
85
|
+
contentRect: { width: 100, height: 0 },
|
|
86
|
+
borderBoxSize: [],
|
|
87
|
+
contentBoxSize: [],
|
|
88
|
+
devicePixelContentBoxSize: [],
|
|
89
|
+
} as ResizeObserverEntry;
|
|
90
|
+
(observer as unknown as { callback: ResizeObserverCallback }).callback([mockEntry], observer);
|
|
91
|
+
|
|
92
|
+
expect(handler).toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("should observe height changes", () => {
|
|
96
|
+
const handler = vi.fn();
|
|
97
|
+
observer = connectResizeObserver(element, handler);
|
|
98
|
+
|
|
99
|
+
const mockEntry = {
|
|
100
|
+
target: element,
|
|
101
|
+
contentRect: { width: 0, height: 150 },
|
|
102
|
+
borderBoxSize: [],
|
|
103
|
+
contentBoxSize: [],
|
|
104
|
+
devicePixelContentBoxSize: [],
|
|
105
|
+
} as ResizeObserverEntry;
|
|
106
|
+
(observer as unknown as { callback: ResizeObserverCallback }).callback([mockEntry], observer);
|
|
107
|
+
|
|
108
|
+
expect(handler).toHaveBeenCalled();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should observe both width and height changes", () => {
|
|
112
|
+
const handler = vi.fn();
|
|
113
|
+
observer = connectResizeObserver(element, handler);
|
|
114
|
+
|
|
115
|
+
const mockEntry = {
|
|
116
|
+
target: element,
|
|
117
|
+
contentRect: { width: 200, height: 200 },
|
|
118
|
+
borderBoxSize: [],
|
|
119
|
+
contentBoxSize: [],
|
|
120
|
+
devicePixelContentBoxSize: [],
|
|
121
|
+
} as ResizeObserverEntry;
|
|
122
|
+
(observer as unknown as { callback: ResizeObserverCallback }).callback([mockEntry], observer);
|
|
123
|
+
|
|
124
|
+
expect(handler).toHaveBeenCalled();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should stop observing when disconnected", () => {
|
|
128
|
+
const handler = vi.fn();
|
|
129
|
+
observer = connectResizeObserver(element, handler);
|
|
130
|
+
|
|
131
|
+
observer.disconnect();
|
|
132
|
+
handler.mockClear();
|
|
133
|
+
|
|
134
|
+
// Try to trigger callback after disconnect - should not be called
|
|
135
|
+
const mockEntry = {
|
|
136
|
+
target: element,
|
|
137
|
+
contentRect: { width: 500, height: 0 },
|
|
138
|
+
borderBoxSize: [],
|
|
139
|
+
contentBoxSize: [],
|
|
140
|
+
devicePixelContentBoxSize: [],
|
|
141
|
+
} as ResizeObserverEntry;
|
|
142
|
+
// Note: In real scenario, ResizeObserver wouldn't call callback after disconnect
|
|
143
|
+
// This test verifies disconnect exists and works
|
|
144
|
+
expect(typeof observer.disconnect).toBe("function");
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { parseTransform2d, parseTransform3d } from "./parseTransform";
|
|
3
|
+
|
|
4
|
+
describe("parseTransform3d", () => {
|
|
5
|
+
it("should parse valid translate3d transform", () => {
|
|
6
|
+
const result = parseTransform3d("translate3d(100px, 200px, 0px)");
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual({ x: 100, y: 200 });
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should parse negative values", () => {
|
|
12
|
+
const result = parseTransform3d("translate3d(-100px, -200px, 0px)");
|
|
13
|
+
|
|
14
|
+
expect(result).toEqual({ x: -100, y: -200 });
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should parse decimal values", () => {
|
|
18
|
+
const result = parseTransform3d("translate3d(123.45px, 678.90px, 0px)");
|
|
19
|
+
|
|
20
|
+
expect(result).toEqual({ x: 123.45, y: 678.9 });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return zero values for invalid transform", () => {
|
|
24
|
+
const result = parseTransform3d("invalid-transform");
|
|
25
|
+
|
|
26
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should return zero values for empty string", () => {
|
|
30
|
+
const result = parseTransform3d("");
|
|
31
|
+
|
|
32
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should parse transform with extra spaces", () => {
|
|
36
|
+
// Note: The regex doesn't handle extra spaces, so this will return zeros
|
|
37
|
+
const result = parseTransform3d("translate3d( 100px , 200px , 0px )");
|
|
38
|
+
|
|
39
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should parse transform with no spaces", () => {
|
|
43
|
+
const result = parseTransform3d("translate3d(100px,200px,0px)");
|
|
44
|
+
|
|
45
|
+
expect(result).toEqual({ x: 100, y: 200 });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should parse zero values", () => {
|
|
49
|
+
const result = parseTransform3d("translate3d(0px, 0px, 0px)");
|
|
50
|
+
|
|
51
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("parseTransform2d", () => {
|
|
56
|
+
it("should parse valid translate transform", () => {
|
|
57
|
+
const result = parseTransform2d("translate(100, 200)");
|
|
58
|
+
|
|
59
|
+
expect(result).toEqual({ x: 100, y: 200 });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should parse negative values", () => {
|
|
63
|
+
const result = parseTransform2d("translate(-100, -200)");
|
|
64
|
+
|
|
65
|
+
expect(result).toEqual({ x: -100, y: -200 });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should parse decimal values", () => {
|
|
69
|
+
const result = parseTransform2d("translate(123.45, 678.90)");
|
|
70
|
+
|
|
71
|
+
expect(result).toEqual({ x: 123.45, y: 678.9 });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should return zero values for null", () => {
|
|
75
|
+
const result = parseTransform2d(null);
|
|
76
|
+
|
|
77
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should return zero values for invalid transform", () => {
|
|
81
|
+
const result = parseTransform2d("invalid-transform");
|
|
82
|
+
|
|
83
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("should return zero values for empty string", () => {
|
|
87
|
+
const result = parseTransform2d("");
|
|
88
|
+
|
|
89
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should parse transform with extra spaces", () => {
|
|
93
|
+
// Note: The regex doesn't handle extra spaces, so this will return zeros
|
|
94
|
+
const result = parseTransform2d("translate( 100 , 200 )");
|
|
95
|
+
|
|
96
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should parse transform with no spaces", () => {
|
|
100
|
+
const result = parseTransform2d("translate(100,200)");
|
|
101
|
+
|
|
102
|
+
expect(result).toEqual({ x: 100, y: 200 });
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("should parse zero values", () => {
|
|
106
|
+
const result = parseTransform2d("translate(0, 0)");
|
|
107
|
+
|
|
108
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should handle undefined", () => {
|
|
112
|
+
const result = parseTransform2d(undefined as unknown as string | null);
|
|
113
|
+
|
|
114
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { toggleClass } from "./toggleClass";
|
|
3
|
+
|
|
4
|
+
describe("toggleClass", () => {
|
|
5
|
+
let element: HTMLElement;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
element = document.createElement("div");
|
|
9
|
+
document.body.appendChild(element);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
if (document.body.contains(element)) {
|
|
14
|
+
document.body.removeChild(element);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should add class when condition is true", () => {
|
|
19
|
+
toggleClass(element, "test-class", true);
|
|
20
|
+
|
|
21
|
+
expect(element.classList.contains("test-class")).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should remove class when condition is false", () => {
|
|
25
|
+
element.classList.add("test-class");
|
|
26
|
+
toggleClass(element, "test-class", false);
|
|
27
|
+
|
|
28
|
+
expect(element.classList.contains("test-class")).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should not add class when condition is false", () => {
|
|
32
|
+
toggleClass(element, "test-class", false);
|
|
33
|
+
|
|
34
|
+
expect(element.classList.contains("test-class")).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should not remove class when condition is true and class already exists", () => {
|
|
38
|
+
element.classList.add("test-class");
|
|
39
|
+
toggleClass(element, "test-class", true);
|
|
40
|
+
|
|
41
|
+
expect(element.classList.contains("test-class")).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should handle multiple classes", () => {
|
|
45
|
+
toggleClass(element, "class1", true);
|
|
46
|
+
toggleClass(element, "class2", true);
|
|
47
|
+
toggleClass(element, "class3", false);
|
|
48
|
+
|
|
49
|
+
expect(element.classList.contains("class1")).toBe(true);
|
|
50
|
+
expect(element.classList.contains("class2")).toBe(true);
|
|
51
|
+
expect(element.classList.contains("class3")).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should do nothing when element is null", () => {
|
|
55
|
+
expect(() => {
|
|
56
|
+
toggleClass(null, "test-class", true);
|
|
57
|
+
}).not.toThrow();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should toggle class multiple times", () => {
|
|
61
|
+
toggleClass(element, "test-class", true);
|
|
62
|
+
expect(element.classList.contains("test-class")).toBe(true);
|
|
63
|
+
|
|
64
|
+
toggleClass(element, "test-class", false);
|
|
65
|
+
expect(element.classList.contains("test-class")).toBe(false);
|
|
66
|
+
|
|
67
|
+
toggleClass(element, "test-class", true);
|
|
68
|
+
expect(element.classList.contains("test-class")).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|