Skip to content

Commit 7ebc6ea

Browse files
Copilothartra344
andcommitted
Add unit tests for hooks.ts
Co-authored-by: hartra344 <13208452+hartra344@users.noreply.github.com>
1 parent 43b37f9 commit 7ebc6ea

File tree

3 files changed

+2466
-1193
lines changed

3 files changed

+2466
-1193
lines changed

libs/logic-apps-shared/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
"main": "src/index.ts",
2929
"module": "src/index.ts",
3030
"peerDependencies": {
31+
"@tanstack/query-sync-storage-persister": "4.36.1",
3132
"@tanstack/react-query": "4.36.1",
3233
"@tanstack/react-query-persist-client": "4.36.1",
33-
"@tanstack/query-sync-storage-persister": "4.36.1",
3434
"react": "^16.4.0 || ^17.0.0 || ^18.0.0",
3535
"react-dom": "^16.4.0 || ^17.0.0 || ^18.0.0"
3636
},
@@ -56,5 +56,8 @@
5656
},
5757
"sideEffects": false,
5858
"type": "module",
59-
"types": "src/index.ts"
59+
"types": "src/index.ts",
60+
"devDependencies": {
61+
"@testing-library/react-hooks": "^8.0.1"
62+
}
6063
}
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
/**
2+
* @vitest-environment jsdom
3+
*/
4+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5+
import { renderHook, act } from '@testing-library/react';
6+
import {
7+
useThrottledEffect,
8+
useWindowDimensions,
9+
useOutsideClick,
10+
useConsoleLog,
11+
useNodeSize,
12+
useNodeIndex,
13+
useEdgeIndex,
14+
useNodeLeafIndex,
15+
} from '../hooks';
16+
import { useNodesData } from '@xyflow/react';
17+
import { useEdgesData } from '../useEdgesData';
18+
19+
// Mock dependencies
20+
vi.mock('@xyflow/react', () => ({
21+
useNodesData: vi.fn(),
22+
}));
23+
24+
vi.mock('../useEdgesData', () => ({
25+
useEdgesData: vi.fn(),
26+
}));
27+
28+
describe('lib/utils/src/lib/helpers/hooks', () => {
29+
describe('useThrottledEffect', () => {
30+
beforeEach(() => {
31+
vi.useFakeTimers();
32+
});
33+
34+
afterEach(() => {
35+
vi.useRealTimers();
36+
});
37+
38+
it('should call the effect function when throttle delay has passed', () => {
39+
const effect = vi.fn();
40+
const delay = 100;
41+
const deps = [1, 2];
42+
43+
renderHook(() => useThrottledEffect(effect, deps, delay));
44+
45+
// Should not be called immediately
46+
expect(effect).not.toHaveBeenCalled();
47+
48+
// Advance timer past delay
49+
act(() => {
50+
vi.advanceTimersByTime(delay + 10);
51+
});
52+
53+
// Should be called after delay
54+
expect(effect).toHaveBeenCalledTimes(1);
55+
});
56+
});
57+
58+
describe('useWindowDimensions', () => {
59+
beforeEach(() => {
60+
// Set initial window dimensions for testing
61+
Object.defineProperty(window, 'innerWidth', { value: 1024, writable: true });
62+
Object.defineProperty(window, 'innerHeight', { value: 768, writable: true });
63+
});
64+
65+
it('should return the current window dimensions', () => {
66+
const { result } = renderHook(() => useWindowDimensions());
67+
68+
expect(result.current).toEqual({
69+
width: 1024,
70+
height: 768,
71+
});
72+
});
73+
74+
it('should update dimensions when window is resized', () => {
75+
const { result } = renderHook(() => useWindowDimensions());
76+
77+
// Change window dimensions
78+
act(() => {
79+
window.innerWidth = 800;
80+
window.innerHeight = 600;
81+
82+
// Trigger resize event
83+
window.dispatchEvent(new Event('resize'));
84+
});
85+
86+
// Check if dimensions are updated
87+
expect(result.current).toEqual({
88+
width: 800,
89+
height: 600,
90+
});
91+
});
92+
});
93+
94+
describe('useOutsideClick', () => {
95+
it('should call callback when clicked outside all refs', () => {
96+
const callback = vi.fn();
97+
const mockRef1 = { current: document.createElement('div') };
98+
const mockRef2 = { current: document.createElement('div') };
99+
100+
document.body.appendChild(mockRef1.current);
101+
document.body.appendChild(mockRef2.current);
102+
103+
renderHook(() => useOutsideClick([mockRef1, mockRef2], callback));
104+
105+
// Create an element outside of the refs
106+
const outsideElement = document.createElement('div');
107+
document.body.appendChild(outsideElement);
108+
109+
// Simulate click on outside element
110+
act(() => {
111+
const clickEvent = new MouseEvent('click', { bubbles: true });
112+
Object.defineProperty(clickEvent, 'target', { value: outsideElement });
113+
document.dispatchEvent(clickEvent);
114+
});
115+
116+
expect(callback).toHaveBeenCalledTimes(1);
117+
118+
// Clean up
119+
document.body.removeChild(mockRef1.current);
120+
document.body.removeChild(mockRef2.current);
121+
document.body.removeChild(outsideElement);
122+
});
123+
124+
it('should not call callback when clicked inside a ref', () => {
125+
const callback = vi.fn();
126+
const mockRef1 = { current: document.createElement('div') };
127+
const mockRef2 = { current: document.createElement('div') };
128+
129+
document.body.appendChild(mockRef1.current);
130+
document.body.appendChild(mockRef2.current);
131+
132+
renderHook(() => useOutsideClick([mockRef1, mockRef2], callback));
133+
134+
// Simulate click on inside element
135+
act(() => {
136+
const clickEvent = new MouseEvent('click', { bubbles: true });
137+
Object.defineProperty(clickEvent, 'target', { value: mockRef1.current });
138+
document.dispatchEvent(clickEvent);
139+
});
140+
141+
expect(callback).not.toHaveBeenCalled();
142+
143+
// Clean up
144+
document.body.removeChild(mockRef1.current);
145+
document.body.removeChild(mockRef2.current);
146+
});
147+
148+
it('should handle ref with null current property', () => {
149+
const callback = vi.fn();
150+
const mockRef1 = { current: null };
151+
const mockRef2 = { current: document.createElement('div') };
152+
153+
document.body.appendChild(mockRef2.current);
154+
155+
renderHook(() => useOutsideClick([mockRef1, mockRef2], callback));
156+
157+
// Simulate click on outside element
158+
act(() => {
159+
const clickEvent = new MouseEvent('click', { bubbles: true });
160+
Object.defineProperty(clickEvent, 'target', { value: document.body });
161+
document.dispatchEvent(clickEvent);
162+
});
163+
164+
expect(callback).toHaveBeenCalledTimes(1);
165+
166+
// Clean up
167+
document.body.removeChild(mockRef2.current);
168+
});
169+
});
170+
171+
describe('useConsoleLog', () => {
172+
it('should call console.log with the provided value', () => {
173+
const originalConsoleLog = console.log;
174+
console.log = vi.fn();
175+
176+
const testValue = { test: 'data' };
177+
renderHook(() => useConsoleLog(testValue));
178+
179+
expect(console.log).toHaveBeenCalledWith('%c UseConsole>', 'color: #3386FF; font-weight: bold;', testValue);
180+
181+
// Restore console.log
182+
console.log = originalConsoleLog;
183+
});
184+
185+
it('should update the log when the value changes', () => {
186+
const originalConsoleLog = console.log;
187+
console.log = vi.fn();
188+
189+
const initialValue = 'initial';
190+
const { rerender } = renderHook(({ value }) => useConsoleLog(value), {
191+
initialProps: { value: initialValue },
192+
});
193+
194+
expect(console.log).toHaveBeenCalledWith('%c UseConsole>', 'color: #3386FF; font-weight: bold;', initialValue);
195+
196+
// Update the value
197+
const newValue = 'updated';
198+
rerender({ value: newValue });
199+
200+
expect(console.log).toHaveBeenCalledWith('%c UseConsole>', 'color: #3386FF; font-weight: bold;', newValue);
201+
202+
// Restore console.log
203+
console.log = originalConsoleLog;
204+
});
205+
});
206+
207+
describe('useNodeSize', () => {
208+
it('should return node size from useNodesData', () => {
209+
const mockSize = { width: 100, height: 50 };
210+
const mockNodeId = 'test-node-id';
211+
212+
// Mock useNodesData to return a node with size data
213+
(useNodesData as vi.Mock).mockReturnValue({
214+
data: {
215+
size: mockSize,
216+
},
217+
});
218+
219+
const { result } = renderHook(() => useNodeSize(mockNodeId));
220+
221+
expect(result.current).toEqual(mockSize);
222+
expect(useNodesData).toHaveBeenCalledWith(mockNodeId);
223+
});
224+
225+
it('should return default size when node data is not available', () => {
226+
const mockNodeId = 'test-node-id';
227+
228+
// Mock useNodesData to return null
229+
(useNodesData as vi.Mock).mockReturnValue(null);
230+
231+
const { result } = renderHook(() => useNodeSize(mockNodeId));
232+
233+
expect(result.current).toEqual({ width: 0, height: 0 });
234+
expect(useNodesData).toHaveBeenCalledWith(mockNodeId);
235+
});
236+
237+
it('should handle undefined nodeId', () => {
238+
// Mock useNodesData
239+
(useNodesData as vi.Mock).mockReturnValue(null);
240+
241+
const { result } = renderHook(() => useNodeSize(undefined));
242+
243+
expect(result.current).toEqual({ width: 0, height: 0 });
244+
expect(useNodesData).toHaveBeenCalledWith('');
245+
});
246+
});
247+
248+
describe('useNodeIndex', () => {
249+
it('should return node index from useNodesData', () => {
250+
const mockNodeIndex = 42;
251+
const mockNodeId = 'test-node-id';
252+
253+
// Mock useNodesData to return a node with nodeIndex data
254+
(useNodesData as vi.Mock).mockReturnValue({
255+
data: {
256+
nodeIndex: mockNodeIndex,
257+
},
258+
});
259+
260+
const { result } = renderHook(() => useNodeIndex(mockNodeId));
261+
262+
expect(result.current).toEqual(mockNodeIndex);
263+
expect(useNodesData).toHaveBeenCalledWith(mockNodeId);
264+
});
265+
266+
it('should return default index when node data is not available', () => {
267+
const mockNodeId = 'test-node-id';
268+
269+
// Mock useNodesData to return null
270+
(useNodesData as vi.Mock).mockReturnValue(null);
271+
272+
const { result } = renderHook(() => useNodeIndex(mockNodeId));
273+
274+
expect(result.current).toEqual(0);
275+
expect(useNodesData).toHaveBeenCalledWith(mockNodeId);
276+
});
277+
278+
it('should handle undefined nodeId', () => {
279+
// Mock useNodesData
280+
(useNodesData as vi.Mock).mockReturnValue(null);
281+
282+
const { result } = renderHook(() => useNodeIndex(undefined));
283+
284+
expect(result.current).toEqual(0);
285+
expect(useNodesData).toHaveBeenCalledWith('');
286+
});
287+
});
288+
289+
describe('useEdgeIndex', () => {
290+
it('should return edge index from useEdgesData', () => {
291+
const mockEdgeIndex = 42;
292+
const mockEdgeId = 'test-edge-id';
293+
294+
// Mock useEdgesData to return an edge with edgeIndex data
295+
(useEdgesData as vi.Mock).mockReturnValue({
296+
data: {
297+
edgeIndex: mockEdgeIndex,
298+
},
299+
});
300+
301+
const { result } = renderHook(() => useEdgeIndex(mockEdgeId));
302+
303+
expect(result.current).toEqual(mockEdgeIndex);
304+
expect(useEdgesData).toHaveBeenCalledWith(mockEdgeId);
305+
});
306+
307+
it('should return default index when edge data is not available', () => {
308+
const mockEdgeId = 'test-edge-id';
309+
310+
// Mock useEdgesData to return null
311+
(useEdgesData as vi.Mock).mockReturnValue(null);
312+
313+
const { result } = renderHook(() => useEdgeIndex(mockEdgeId));
314+
315+
expect(result.current).toEqual(0);
316+
expect(useEdgesData).toHaveBeenCalledWith(mockEdgeId);
317+
});
318+
319+
it('should handle undefined edgeId', () => {
320+
// Mock useEdgesData
321+
(useEdgesData as vi.Mock).mockReturnValue(null);
322+
323+
const { result } = renderHook(() => useEdgeIndex(undefined));
324+
325+
expect(result.current).toEqual(0);
326+
expect(useEdgesData).toHaveBeenCalledWith('');
327+
});
328+
});
329+
330+
describe('useNodeLeafIndex', () => {
331+
it('should return node leaf index from useNodesData', () => {
332+
const mockNodeLeafIndex = 42;
333+
const mockNodeId = 'test-node-id';
334+
335+
// Mock useNodesData to return a node with nodeLeafIndex data
336+
(useNodesData as vi.Mock).mockReturnValue({
337+
data: {
338+
nodeLeafIndex: mockNodeLeafIndex,
339+
},
340+
});
341+
342+
const { result } = renderHook(() => useNodeLeafIndex(mockNodeId));
343+
344+
expect(result.current).toEqual(mockNodeLeafIndex);
345+
expect(useNodesData).toHaveBeenCalledWith(mockNodeId);
346+
});
347+
348+
it('should return default index when node data is not available', () => {
349+
const mockNodeId = 'test-node-id';
350+
351+
// Mock useNodesData to return null
352+
(useNodesData as vi.Mock).mockReturnValue(null);
353+
354+
const { result } = renderHook(() => useNodeLeafIndex(mockNodeId));
355+
356+
expect(result.current).toEqual(0);
357+
expect(useNodesData).toHaveBeenCalledWith(mockNodeId);
358+
});
359+
360+
it('should handle undefined nodeId', () => {
361+
// Mock useNodesData
362+
(useNodesData as vi.Mock).mockReturnValue(null);
363+
364+
const { result } = renderHook(() => useNodeLeafIndex(undefined));
365+
366+
expect(result.current).toEqual(0);
367+
expect(useNodesData).toHaveBeenCalledWith('');
368+
});
369+
});
370+
});

0 commit comments

Comments
 (0)