Skip to content

Commit 3ec612c

Browse files
author
babin
committed
main 🧊 add use element size test
1 parent 143c9c2 commit 3ec612c

File tree

23 files changed

+221
-65
lines changed

23 files changed

+221
-65
lines changed

‎src/hooks/useAsync/useAsync.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ export interface UseAsyncReturn<Data> {
2020
* @category Utilities
2121
*
2222
* @param {() => Promise<Data>} callback - The async callback
23-
* @param {DependencyList} [deps] - The dependencies of the callback
23+
* @param {DependencyList} deps - The dependencies of the callback
2424
* @returns {UseAsyncReturn<Data>} - The state of the async callback
2525
*
2626
* @example
2727
* const { data, isLoading, isError, error } = useAsync(() => fetch('url'), [deps]);
2828
*/
2929
export const useAsync = <Data>(
3030
callback: () => Promise<Data>,
31-
deps?: DependencyList
31+
deps: DependencyList
3232
): UseAsyncReturn<Data> => {
3333
const [isLoading, setIsLoading] = useState(false);
3434
const [isError, setIsError] = useState(false);

‎src/hooks/useBoolean/useBoolean.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ it('Should use counter', () => {
77
const [on, toggle] = result.current;
88

99
expect(on).toBeFalsy();
10-
expect(typeof toggle).toBe('function');
10+
expect(toggle).toBeTypeOf('function');
1111
});
1212

1313
it('Should set initial value', () => {

‎src/hooks/useClickOutside/useClickOutside.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useClickOutside } from './useClickOutside';
55
it('Should use click outside', () => {
66
const { result } = renderHook(() => useClickOutside(vi.fn()));
77

8-
expect(typeof result.current).toBe('function');
8+
expect(result.current).toBeTypeOf('function');
99
});
1010

1111
it('Should call callback when ref connected to the document', () => {

‎src/hooks/useClipboard/useClipboard.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ it('Should use copy to clipboard', () => {
2424

2525
expect(result.current.value).toBeNull();
2626
expect(result.current.supported).toBeTruthy();
27-
expect(typeof result.current.copy).toBe('function');
27+
expect(result.current.copy).toBeTypeOf('function');
2828
});
2929

3030
it('Should copy value to clipboard', async () => {

‎src/hooks/useCounter/useCounter.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ it('Should use counter', () => {
66
const { result } = renderHook(useCounter);
77

88
expect(result.current.value).toBe(0);
9-
expect(typeof result.current.inc).toBe('function');
10-
expect(typeof result.current.dec).toBe('function');
11-
expect(typeof result.current.reset).toBe('function');
12-
expect(typeof result.current.set).toBe('function');
9+
expect(result.current.inc).toBeTypeOf('function');
10+
expect(result.current.dec).toBeTypeOf('function');
11+
expect(result.current.reset).toBeTypeOf('function');
12+
expect(result.current.set).toBeTypeOf('function');
1313
});
1414

1515
it('Should set initial value', () => {

‎src/hooks/useDefault/useDefault.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ it('Should use default', () => {
77
const [state, setState] = result.current;
88

99
expect(state).toBe(5);
10-
expect(typeof setState).toBe('function');
10+
expect(setState).toBeTypeOf('function');
1111
});
1212

1313
it('Should return initial value', () => {

‎src/hooks/useDisclosure/useDisclosure.test.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ it('Should use counter', () => {
66
const { result } = renderHook(useDisclosure);
77

88
expect(result.current.opened).toBeFalsy();
9-
expect(typeof result.current.open).toBe('function');
10-
expect(typeof result.current.close).toBe('function');
11-
expect(typeof result.current.toggle).toBe('function');
9+
expect(result.current.open).toBeTypeOf('function');
10+
expect(result.current.close).toBeTypeOf('function');
11+
expect(result.current.toggle).toBeTypeOf('function');
1212
});
1313

1414
it('Should set initial value', () => {

‎src/hooks/useDocumentTitle/useDocumentTitle.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ it('Should use document title', () => {
1111
const [title, setTitle] = result.current;
1212

1313
expect(title).toBe('default title');
14-
expect(typeof setTitle).toBe('function');
14+
expect(setTitle).toBeTypeOf('function');
1515
});
1616

1717
it('Should be set initial title', () => {

‎src/hooks/useElementSize/useElementSize.demo.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const Demo = () => {
88
<p>Resize the box to see changes</p>
99
<textarea
1010
ref={elementSize.ref}
11+
className='h-[200px] w-[200px]'
1112
style={{ resize: 'both' }}
1213
value={`width: ${elementSize.value.width}\nheight: ${elementSize.value.height}`}
1314
/>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { act, renderHook } from '@testing-library/react';
2+
3+
import type { HookRef } from '@/utils/helpers';
4+
5+
import { getElement } from '@/utils/helpers';
6+
7+
import type { UseElementSizeReturn } from './useElementSize';
8+
9+
import { useElementSize } from './useElementSize';
10+
11+
export function createTrigger<Callback extends (...args: any[]) => void>() {
12+
const observers = new Map();
13+
return {
14+
callback(target: Element, ...args: Partial<Parameters<Callback>>) {
15+
const observe = observers.get(target);
16+
observe(...args);
17+
},
18+
add(element: Element, callback: Callback) {
19+
observers.set(element, callback);
20+
},
21+
delete(element: Element) {
22+
observers.delete(element);
23+
}
24+
};
25+
}
26+
27+
const trigger = createTrigger<ResizeObserverCallback>();
28+
const mockResizeObserverDisconnect = vi.fn();
29+
const mockResizeObserverObserve = vi.fn();
30+
const mockResizeObserver = class ResizeObserver {
31+
callback: ResizeObserverCallback;
32+
element: Element | undefined;
33+
34+
constructor(callback: ResizeObserverCallback) {
35+
this.callback = callback;
36+
}
37+
38+
observe = (element: Element) => {
39+
trigger.add(element, this.callback);
40+
mockResizeObserverObserve();
41+
};
42+
disconnect = () => {
43+
if (this.element) trigger.delete(this.element);
44+
mockResizeObserverDisconnect();
45+
};
46+
unobserve = vi.fn();
47+
};
48+
globalThis.ResizeObserver = mockResizeObserver;
49+
50+
const targets = [
51+
undefined,
52+
'#target',
53+
document.getElementById('target'),
54+
{ current: document.getElementById('target') }
55+
];
56+
57+
targets.forEach((target) => {
58+
beforeEach(() => {
59+
mockResizeObserverObserve.mockClear();
60+
mockResizeObserverDisconnect.mockClear();
61+
});
62+
63+
describe(`${target}`, () => {
64+
it('Should use element size', () => {
65+
const { result } = renderHook(() => {
66+
if (target)
67+
return useElementSize(target) as {
68+
ref: HookRef<HTMLDivElement>;
69+
} & UseElementSizeReturn;
70+
return useElementSize<HTMLDivElement>();
71+
});
72+
expect(result.current.value).toStrictEqual({ width: 0, height: 0 });
73+
if (!target) expect(result.current.ref).toBeTypeOf('function');
74+
});
75+
76+
it('Should set intitial value', () => {
77+
const { result } = renderHook(() => {
78+
if (target) return useElementSize(target, { width: 200, height: 200 });
79+
return useElementSize<HTMLDivElement>({ width: 200, height: 200 });
80+
});
81+
82+
expect(result.current.value).toStrictEqual({ width: 200, height: 200 });
83+
});
84+
85+
it('Should change value after resize', () => {
86+
const { result } = renderHook(() => {
87+
if (target)
88+
return useElementSize(target) as {
89+
ref: HookRef<HTMLDivElement>;
90+
} & UseElementSizeReturn;
91+
return useElementSize<HTMLDivElement>();
92+
});
93+
94+
expect(result.current.value).toStrictEqual({ width: 0, height: 0 });
95+
96+
if (!target)
97+
act(() => result.current.ref(document.getElementById('target')! as HTMLDivElement));
98+
99+
act(() => {
100+
const element = (target ? getElement(target) : result.current.ref.current) as Element;
101+
if (!element) return;
102+
103+
trigger.callback(element, [
104+
{ contentRect: { width: 200, height: 200 } }
105+
] as unknown as ResizeObserverEntry[]);
106+
});
107+
108+
expect(mockResizeObserverObserve).toHaveBeenCalledTimes(1);
109+
expect(result.current.value).toStrictEqual({ width: 200, height: 200 });
110+
});
111+
112+
it('Should disconnect on onmount', () => {
113+
const { result, unmount } = renderHook(() => {
114+
if (target)
115+
return useElementSize(target) as {
116+
ref: HookRef<HTMLDivElement>;
117+
} & UseElementSizeReturn;
118+
return useElementSize<HTMLDivElement>();
119+
});
120+
121+
if (!target)
122+
act(() => result.current.ref(document.getElementById('target')! as HTMLDivElement));
123+
124+
unmount();
125+
126+
expect(mockResizeObserverDisconnect).toHaveBeenCalledTimes(1);
127+
});
128+
});
129+
});

0 commit comments

Comments
 (0)