@musecat/functionkit 1.0.2 → 1.2.0
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/index.ts +1 -1
- package/package.json +37 -2
- package/packages/components/ScrolltoTop.tsx +1 -1
- package/packages/components/ViewportPortal.tsx +1 -2
- package/packages/cookie/cookie.shared.ts +17 -35
- package/packages/cookie/cookieNames.shared.ts +9 -0
- package/packages/datetime/dateTime.client.ts +1 -3
- package/packages/datetime/dateTime.server.ts +1 -3
- package/packages/datetime/dateTime.shared.ts +9 -47
- package/packages/hooks/useCheckInvisible.ts +1 -1
- package/packages/hooks/useClientDateTime.ts +3 -16
- package/packages/hooks/useDebounce.ts +2 -7
- package/packages/hooks/useGeolocation.ts +1 -5
- package/packages/hooks/useInterval.ts +1 -2
- package/packages/hooks/useKeyboardListNavigation.ts +10 -38
- package/packages/hooks/useLongPress.ts +13 -24
- package/packages/hooks/useRelativeDateTime.ts +1 -4
- package/packages/hooks/useViewportHeight.ts +1 -2
- package/packages/hooks/useViewportMatch.ts +0 -4
- package/packages/utils/buildContext.tsx +2 -3
- package/packages/utils/floatingMotion.ts +15 -23
- package/packages/utils/subscribeKeyboardHeight.ts +3 -0
- package/.agents/references/components/ScrolltoTop.md +0 -36
- package/.agents/references/components/SwitchCase.md +0 -47
- package/.agents/references/components/ViewportPortal.md +0 -34
- package/.agents/references/cookie/cookie.md +0 -47
- package/.agents/references/datetime/dateTime.client.md +0 -42
- package/.agents/references/datetime/dateTime.server.md +0 -42
- package/.agents/references/datetime/dateTime.shared.md +0 -86
- package/.agents/references/hooks/useAvoidKeyboard.md +0 -29
- package/.agents/references/hooks/useCheckInvisible.md +0 -36
- package/.agents/references/hooks/useCheckScroll.md +0 -36
- package/.agents/references/hooks/useClientDateTime.md +0 -39
- package/.agents/references/hooks/useDebounce.md +0 -46
- package/.agents/references/hooks/useDebouncedCallback.md +0 -34
- package/.agents/references/hooks/useDoubleClick.md +0 -40
- package/.agents/references/hooks/useGeolocation.md +0 -37
- package/.agents/references/hooks/useHasMounted.md +0 -27
- package/.agents/references/hooks/useIntersectionObserver.md +0 -37
- package/.agents/references/hooks/useInterval.md +0 -40
- package/.agents/references/hooks/useKeyboardHeight.md +0 -33
- package/.agents/references/hooks/useKeyboardListNavigation.md +0 -58
- package/.agents/references/hooks/useLongPress.md +0 -48
- package/.agents/references/hooks/usePreservedCallback.md +0 -33
- package/.agents/references/hooks/usePreservedReference.md +0 -34
- package/.agents/references/hooks/useRefEffect.md +0 -35
- package/.agents/references/hooks/useRelativeDateTime.md +0 -35
- package/.agents/references/hooks/useTimeout.md +0 -42
- package/.agents/references/hooks/useToggleState.md +0 -39
- package/.agents/references/hooks/useViewportHeight.md +0 -26
- package/.agents/references/hooks/useViewportMatch.md +0 -32
- package/.agents/references/utils/browserStorage.md +0 -41
- package/.agents/references/utils/buildContext.md +0 -47
- package/.agents/references/utils/clipboardShare.md +0 -59
- package/.agents/references/utils/floatingMotion.md +0 -67
- package/.agents/references/utils/getDeviceInfo.md +0 -43
- package/.agents/references/utils/isEditableKeyboardTarget.md +0 -35
- package/.agents/references/utils/mergeRefs.md +0 -29
- package/.agents/references/utils/seen.md +0 -37
- package/.agents/references/utils/subscribeKeyboardHeight.md +0 -35
- package/.gitattributes +0 -2
- package/AGENTS.md +0 -105
- package/tests/components/ScrolltoTop.test.tsx +0 -15
- package/tests/components/SwitchCase.test.tsx +0 -34
- package/tests/components/ViewportPortal.test.tsx +0 -42
- package/tests/cookie/cookie.test.ts +0 -156
- package/tests/datetime/datetime.test.ts +0 -250
- package/tests/hooks/useAvoidKeyboard.test.ts +0 -12
- package/tests/hooks/useCheckInvisible.test.ts +0 -28
- package/tests/hooks/useCheckScroll.test.ts +0 -23
- package/tests/hooks/useClientDateTime.test.ts +0 -14
- package/tests/hooks/useDebounce.test.ts +0 -71
- package/tests/hooks/useDebouncedCallback.test.ts +0 -34
- package/tests/hooks/useDoubleClick.test.ts +0 -31
- package/tests/hooks/useGeolocation.test.ts +0 -50
- package/tests/hooks/useHasMounted.test.ts +0 -10
- package/tests/hooks/useIntersectionObserver.test.ts +0 -13
- package/tests/hooks/useInterval.test.ts +0 -31
- package/tests/hooks/useKeyboardHeight.test.ts +0 -10
- package/tests/hooks/useKeyboardListNavigation.test.ts +0 -82
- package/tests/hooks/useLongPress.test.ts +0 -52
- package/tests/hooks/usePreservedCallback.test.ts +0 -35
- package/tests/hooks/usePreservedReference.test.ts +0 -35
- package/tests/hooks/useRefEffect.test.ts +0 -30
- package/tests/hooks/useRelativeDateTime.test.ts +0 -19
- package/tests/hooks/useTimeout.test.ts +0 -34
- package/tests/hooks/useToggleState.test.ts +0 -35
- package/tests/hooks/useViewportHeight.test.ts +0 -10
- package/tests/hooks/useViewportMatch.test.ts +0 -35
- package/tests/setup.ts +0 -9
- package/tests/utils/browserStorage.test.ts +0 -54
- package/tests/utils/buildContext.test.tsx +0 -27
- package/tests/utils/checkDevice.test.ts +0 -84
- package/tests/utils/clipboardShare.test.ts +0 -78
- package/tests/utils/floatingMotion.test.ts +0 -84
- package/tests/utils/keyboardTarget.test.ts +0 -44
- package/tests/utils/mergeRefs.test.ts +0 -18
- package/tests/utils/seen.test.ts +0 -31
- package/tests/utils/subscribeKeyboardHeight.test.ts +0 -50
- package/tsconfig.json +0 -18
- package/vitest.config.ts +0 -16
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { useIntersectionObserver } from "@/packages/hooks/useIntersectionObserver";
|
|
4
|
-
|
|
5
|
-
describe("useIntersectionObserver", () => {
|
|
6
|
-
test("returns a ref callback", () => {
|
|
7
|
-
const callback = vi.fn();
|
|
8
|
-
const { result } = renderHook(() =>
|
|
9
|
-
useIntersectionObserver(callback, { threshold: 0 }),
|
|
10
|
-
);
|
|
11
|
-
expect(typeof result.current).toBe("function");
|
|
12
|
-
});
|
|
13
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { useInterval } from "@/packages/hooks/useInterval";
|
|
4
|
-
|
|
5
|
-
describe("useInterval", () => {
|
|
6
|
-
beforeEach(() => { vi.useFakeTimers(); });
|
|
7
|
-
afterEach(() => { vi.useRealTimers(); });
|
|
8
|
-
|
|
9
|
-
test("calls callback repeatedly at interval", () => {
|
|
10
|
-
const fn = vi.fn();
|
|
11
|
-
renderHook(() => useInterval(fn, 100));
|
|
12
|
-
expect(fn).not.toHaveBeenCalled();
|
|
13
|
-
vi.advanceTimersByTime(100);
|
|
14
|
-
expect(fn).toHaveBeenCalledTimes(1);
|
|
15
|
-
vi.advanceTimersByTime(100);
|
|
16
|
-
expect(fn).toHaveBeenCalledTimes(2);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("calls immediately with immediate option", () => {
|
|
20
|
-
const fn = vi.fn();
|
|
21
|
-
renderHook(() => useInterval(fn, { delay: 100, immediate: true }));
|
|
22
|
-
expect(fn).toHaveBeenCalledOnce();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("does not call when disabled", () => {
|
|
26
|
-
const fn = vi.fn();
|
|
27
|
-
renderHook(() => useInterval(fn, { delay: 100, enabled: false }));
|
|
28
|
-
vi.advanceTimersByTime(200);
|
|
29
|
-
expect(fn).not.toHaveBeenCalled();
|
|
30
|
-
});
|
|
31
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { useKeyboardHeight } from "@/packages/hooks/useKeyboardHeight";
|
|
4
|
-
|
|
5
|
-
describe("useKeyboardHeight", () => {
|
|
6
|
-
test("returns default keyboard height of 0", () => {
|
|
7
|
-
const { result } = renderHook(() => useKeyboardHeight());
|
|
8
|
-
expect(result.current.keyboardHeight).toBe(0);
|
|
9
|
-
});
|
|
10
|
-
});
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi } from "vitest";
|
|
2
|
-
import { renderHook, act } from "@testing-library/react";
|
|
3
|
-
import { useKeyboardListNavigation } from "@/packages/hooks/useKeyboardListNavigation";
|
|
4
|
-
|
|
5
|
-
describe("useKeyboardListNavigation", () => {
|
|
6
|
-
test("initializes with activeIndex -1", () => {
|
|
7
|
-
const { result } = renderHook(() =>
|
|
8
|
-
useKeyboardListNavigation({ itemCount: 3 }),
|
|
9
|
-
);
|
|
10
|
-
expect(result.current.activeIndex).toBe(-1);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("handleListKeyDown with ArrowDown moves to first item when none active", () => {
|
|
14
|
-
const { result } = renderHook(() =>
|
|
15
|
-
useKeyboardListNavigation({ itemCount: 3 }),
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
const container = document.createElement("div");
|
|
19
|
-
const items = [0, 1, 2].map(() => {
|
|
20
|
-
const el = document.createElement("div");
|
|
21
|
-
el.setAttribute("tabindex", "-1");
|
|
22
|
-
el.scrollIntoView = vi.fn();
|
|
23
|
-
container.appendChild(el);
|
|
24
|
-
return el;
|
|
25
|
-
});
|
|
26
|
-
items.forEach((el, i) => result.current.setItemRef(i, el));
|
|
27
|
-
|
|
28
|
-
const event = {
|
|
29
|
-
key: "ArrowDown",
|
|
30
|
-
defaultPrevented: false,
|
|
31
|
-
preventDefault: vi.fn(),
|
|
32
|
-
target: container,
|
|
33
|
-
} as unknown as React.KeyboardEvent<HTMLElement>;
|
|
34
|
-
|
|
35
|
-
act(() => { result.current.handleListKeyDown(event); });
|
|
36
|
-
expect(result.current.activeIndex).toBe(0);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("handleListKeyDown with ArrowUp moves to previous item", () => {
|
|
40
|
-
const { result } = renderHook(() =>
|
|
41
|
-
useKeyboardListNavigation({ itemCount: 3 }),
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const container = document.createElement("div");
|
|
45
|
-
const items = [0, 1, 2].map(() => {
|
|
46
|
-
const el = document.createElement("div");
|
|
47
|
-
el.setAttribute("tabindex", "-1");
|
|
48
|
-
el.scrollIntoView = vi.fn();
|
|
49
|
-
container.appendChild(el);
|
|
50
|
-
return el;
|
|
51
|
-
});
|
|
52
|
-
items.forEach((el, i) => result.current.setItemRef(i, el));
|
|
53
|
-
act(() => { result.current.setActiveIndex(1); });
|
|
54
|
-
|
|
55
|
-
const event = {
|
|
56
|
-
key: "ArrowUp",
|
|
57
|
-
defaultPrevented: false,
|
|
58
|
-
preventDefault: vi.fn(),
|
|
59
|
-
target: container,
|
|
60
|
-
} as unknown as React.KeyboardEvent<HTMLElement>;
|
|
61
|
-
|
|
62
|
-
act(() => { result.current.handleListKeyDown(event); });
|
|
63
|
-
expect(result.current.activeIndex).toBe(0);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("Escape resets activeIndex to -1", () => {
|
|
67
|
-
const { result } = renderHook(() =>
|
|
68
|
-
useKeyboardListNavigation({ itemCount: 3 }),
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const event = {
|
|
72
|
-
key: "Escape",
|
|
73
|
-
defaultPrevented: false,
|
|
74
|
-
preventDefault: vi.fn(),
|
|
75
|
-
target: document.createElement("div"),
|
|
76
|
-
} as unknown as React.KeyboardEvent<HTMLElement>;
|
|
77
|
-
|
|
78
|
-
result.current.setActiveIndex(1);
|
|
79
|
-
act(() => { result.current.handleListKeyDown(event); });
|
|
80
|
-
expect(result.current.activeIndex).toBe(-1);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { renderHook, act } from "@testing-library/react";
|
|
3
|
-
import type React from "react";
|
|
4
|
-
import { useLongPress } from "@/packages/hooks/useLongPress";
|
|
5
|
-
|
|
6
|
-
function createMouseEvent(type: string): React.MouseEvent<HTMLElement> {
|
|
7
|
-
return {
|
|
8
|
-
type,
|
|
9
|
-
nativeEvent: new MouseEvent(type, { clientX: 0, clientY: 0 }),
|
|
10
|
-
clientX: 0,
|
|
11
|
-
clientY: 0,
|
|
12
|
-
} as unknown as React.MouseEvent<HTMLElement>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe("useLongPress", () => {
|
|
16
|
-
beforeEach(() => { vi.useFakeTimers(); });
|
|
17
|
-
afterEach(() => { vi.useRealTimers(); });
|
|
18
|
-
|
|
19
|
-
test("fires onLongPress after delay", () => {
|
|
20
|
-
const onLongPress = vi.fn();
|
|
21
|
-
const { result } = renderHook(() => useLongPress(onLongPress, { delay: 200 }));
|
|
22
|
-
|
|
23
|
-
act(() => { result.current.onMouseDown(createMouseEvent("mousedown")); });
|
|
24
|
-
expect(onLongPress).not.toHaveBeenCalled();
|
|
25
|
-
vi.advanceTimersByTime(200);
|
|
26
|
-
expect(onLongPress).toHaveBeenCalledOnce();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("fires onClick when released before delay", () => {
|
|
30
|
-
const onLongPress = vi.fn();
|
|
31
|
-
const onClick = vi.fn();
|
|
32
|
-
const { result } = renderHook(() =>
|
|
33
|
-
useLongPress(onLongPress, { delay: 200, onClick }),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
act(() => { result.current.onMouseDown(createMouseEvent("mousedown")); });
|
|
37
|
-
act(() => { result.current.onMouseUp(createMouseEvent("mouseup")); });
|
|
38
|
-
vi.advanceTimersByTime(200);
|
|
39
|
-
expect(onLongPress).not.toHaveBeenCalled();
|
|
40
|
-
expect(onClick).toHaveBeenCalledOnce();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test("cancels on mouse leave", () => {
|
|
44
|
-
const onLongPress = vi.fn();
|
|
45
|
-
const { result } = renderHook(() => useLongPress(onLongPress, { delay: 200 }));
|
|
46
|
-
|
|
47
|
-
act(() => { result.current.onMouseDown(createMouseEvent("mousedown")); });
|
|
48
|
-
act(() => { result.current.onMouseLeave(createMouseEvent("mouseleave")); });
|
|
49
|
-
vi.advanceTimersByTime(200);
|
|
50
|
-
expect(onLongPress).not.toHaveBeenCalled();
|
|
51
|
-
});
|
|
52
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { usePreservedCallback } from "@/packages/hooks/usePreservedCallback";
|
|
4
|
-
|
|
5
|
-
describe("usePreservedCallback", () => {
|
|
6
|
-
test("returns a stable function reference across renders", () => {
|
|
7
|
-
const { result, rerender } = renderHook(
|
|
8
|
-
({ cb }) => usePreservedCallback(cb),
|
|
9
|
-
{ initialProps: { cb: vi.fn() } },
|
|
10
|
-
);
|
|
11
|
-
const firstRef = result.current;
|
|
12
|
-
rerender({ cb: vi.fn() });
|
|
13
|
-
expect(result.current).toBe(firstRef);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test("invokes the latest callback", () => {
|
|
17
|
-
const fn1 = vi.fn();
|
|
18
|
-
const fn2 = vi.fn();
|
|
19
|
-
const { result, rerender } = renderHook(
|
|
20
|
-
({ cb }) => usePreservedCallback(cb),
|
|
21
|
-
{ initialProps: { cb: fn1 } },
|
|
22
|
-
);
|
|
23
|
-
rerender({ cb: fn2 });
|
|
24
|
-
result.current();
|
|
25
|
-
expect(fn2).toHaveBeenCalledOnce();
|
|
26
|
-
expect(fn1).not.toHaveBeenCalled();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("passes arguments through", () => {
|
|
30
|
-
const fn = vi.fn();
|
|
31
|
-
const { result } = renderHook(() => usePreservedCallback(fn));
|
|
32
|
-
result.current("a", 1);
|
|
33
|
-
expect(fn).toHaveBeenCalledWith("a", 1);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { usePreservedReference } from "@/packages/hooks/usePreservedReference";
|
|
4
|
-
|
|
5
|
-
describe("usePreservedReference", () => {
|
|
6
|
-
test("returns same reference for deeply equal values", () => {
|
|
7
|
-
const { result, rerender } = renderHook(
|
|
8
|
-
({ val }) => usePreservedReference(val),
|
|
9
|
-
{ initialProps: { val: { a: 1, b: { c: [2, 3] } } } },
|
|
10
|
-
);
|
|
11
|
-
const first = result.current;
|
|
12
|
-
rerender({ val: { a: 1, b: { c: [2, 3] } } });
|
|
13
|
-
expect(result.current).toBe(first);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test("returns new reference for different values", () => {
|
|
17
|
-
const { result, rerender } = renderHook(
|
|
18
|
-
({ val }) => usePreservedReference(val),
|
|
19
|
-
{ initialProps: { val: { a: 1 } } },
|
|
20
|
-
);
|
|
21
|
-
const first = result.current;
|
|
22
|
-
rerender({ val: { a: 2 } });
|
|
23
|
-
expect(result.current).not.toBe(first);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("accepts custom comparator", () => {
|
|
27
|
-
const { result, rerender } = renderHook(
|
|
28
|
-
({ val }) => usePreservedReference(val, () => true),
|
|
29
|
-
{ initialProps: { val: { a: 1 } } },
|
|
30
|
-
);
|
|
31
|
-
const first = result.current;
|
|
32
|
-
rerender({ val: { a: 999 } });
|
|
33
|
-
expect(result.current).toBe(first);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi } from "vitest";
|
|
2
|
-
import { renderHook, act } from "@testing-library/react";
|
|
3
|
-
import { useRefEffect } from "@/packages/hooks/useRefEffect";
|
|
4
|
-
|
|
5
|
-
describe("useRefEffect", () => {
|
|
6
|
-
test("calls callback with element and cleanup on unmount", () => {
|
|
7
|
-
const cleanup = vi.fn();
|
|
8
|
-
const callback = vi.fn(() => cleanup);
|
|
9
|
-
const { result } = renderHook(() => useRefEffect(callback, []));
|
|
10
|
-
|
|
11
|
-
const element = document.createElement("div");
|
|
12
|
-
act(() => { (result.current as (el: HTMLElement | null) => void)(element); });
|
|
13
|
-
expect(callback).toHaveBeenCalledWith(element);
|
|
14
|
-
|
|
15
|
-
act(() => { (result.current as (el: HTMLElement | null) => void)(null); });
|
|
16
|
-
expect(cleanup).toHaveBeenCalledOnce();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("calls cleanup before setting new element", () => {
|
|
20
|
-
const cleanup = vi.fn();
|
|
21
|
-
const callback = vi.fn(() => cleanup);
|
|
22
|
-
const { result } = renderHook(() => useRefEffect(callback, []));
|
|
23
|
-
|
|
24
|
-
const el1 = document.createElement("div");
|
|
25
|
-
const el2 = document.createElement("span");
|
|
26
|
-
act(() => { (result.current as (el: HTMLElement | null) => void)(el1); });
|
|
27
|
-
act(() => { (result.current as (el: HTMLElement | null) => void)(el2); });
|
|
28
|
-
expect(cleanup).toHaveBeenCalledOnce();
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { useRelativeDateTime } from "@/packages/hooks/useRelativeDateTime";
|
|
4
|
-
|
|
5
|
-
describe("useRelativeDateTime", () => {
|
|
6
|
-
beforeEach(() => { vi.useFakeTimers(); });
|
|
7
|
-
afterEach(() => { vi.useRealTimers(); });
|
|
8
|
-
|
|
9
|
-
test("returns relative time text", () => {
|
|
10
|
-
const now = Date.now();
|
|
11
|
-
const fiveMinAgo = new Date(now - 5 * 60 * 1000).toISOString();
|
|
12
|
-
const { result } = renderHook(() =>
|
|
13
|
-
useRelativeDateTime(fiveMinAgo, { locale: "ko" }),
|
|
14
|
-
);
|
|
15
|
-
expect(result.current.ready).toBe(true);
|
|
16
|
-
expect(result.current.isRelative).toBe(true);
|
|
17
|
-
expect(result.current.text).toBeTruthy();
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { renderHook, act } from "@testing-library/react";
|
|
3
|
-
import { useTimeout } from "@/packages/hooks/useTimeout";
|
|
4
|
-
|
|
5
|
-
describe("useTimeout", () => {
|
|
6
|
-
beforeEach(() => { vi.useFakeTimers(); });
|
|
7
|
-
afterEach(() => { vi.useRealTimers(); });
|
|
8
|
-
|
|
9
|
-
test("calls callback after delay", () => {
|
|
10
|
-
const fn = vi.fn();
|
|
11
|
-
renderHook(() => useTimeout(fn, 100));
|
|
12
|
-
expect(fn).not.toHaveBeenCalled();
|
|
13
|
-
vi.advanceTimersByTime(100);
|
|
14
|
-
expect(fn).toHaveBeenCalledOnce();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test("does not call when disabled", () => {
|
|
18
|
-
const fn = vi.fn();
|
|
19
|
-
renderHook(() => useTimeout(fn, 100, { enabled: false }));
|
|
20
|
-
vi.advanceTimersByTime(200);
|
|
21
|
-
expect(fn).not.toHaveBeenCalled();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("start and clear controls", () => {
|
|
25
|
-
const fn = vi.fn();
|
|
26
|
-
const { result } = renderHook(() => useTimeout(fn, 1000, { enabled: false }));
|
|
27
|
-
expect(result.current.isPending()).toBe(false);
|
|
28
|
-
act(() => { result.current.start(50); });
|
|
29
|
-
expect(result.current.isPending()).toBe(true);
|
|
30
|
-
vi.advanceTimersByTime(50);
|
|
31
|
-
expect(fn).toHaveBeenCalledOnce();
|
|
32
|
-
expect(result.current.isPending()).toBe(false);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { renderHook, act } from "@testing-library/react";
|
|
3
|
-
import { useToggleState } from "@/packages/hooks/useToggleState";
|
|
4
|
-
|
|
5
|
-
describe("useToggleState", () => {
|
|
6
|
-
test("initializes with false by default", () => {
|
|
7
|
-
const { result } = renderHook(() => useToggleState());
|
|
8
|
-
expect(result.current.value).toBe(false);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
test("initializes with provided value", () => {
|
|
12
|
-
const { result } = renderHook(() => useToggleState(true));
|
|
13
|
-
expect(result.current.value).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test("setTrue sets value to true", () => {
|
|
17
|
-
const { result } = renderHook(() => useToggleState(false));
|
|
18
|
-
act(() => { result.current.setTrue(); });
|
|
19
|
-
expect(result.current.value).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test("setFalse sets value to false", () => {
|
|
23
|
-
const { result } = renderHook(() => useToggleState(true));
|
|
24
|
-
act(() => { result.current.setFalse(); });
|
|
25
|
-
expect(result.current.value).toBe(false);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("toggle switches value", () => {
|
|
29
|
-
const { result } = renderHook(() => useToggleState(false));
|
|
30
|
-
act(() => { result.current.toggle(); });
|
|
31
|
-
expect(result.current.value).toBe(true);
|
|
32
|
-
act(() => { result.current.toggle(); });
|
|
33
|
-
expect(result.current.value).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { useViewportHeight } from "@/packages/hooks/useViewportHeight";
|
|
4
|
-
|
|
5
|
-
describe("useViewportHeight", () => {
|
|
6
|
-
test("returns a height value", () => {
|
|
7
|
-
const { result } = renderHook(() => useViewportHeight());
|
|
8
|
-
expect(result.current.height).toBeGreaterThanOrEqual(0);
|
|
9
|
-
});
|
|
10
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
import { renderHook } from "@testing-library/react";
|
|
3
|
-
import { useViewportMatch } from "@/packages/hooks/useViewportMatch";
|
|
4
|
-
|
|
5
|
-
describe("useViewportMatch", () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
vi.stubGlobal(
|
|
8
|
-
"matchMedia",
|
|
9
|
-
vi.fn().mockImplementation((query: string) => ({
|
|
10
|
-
matches: false,
|
|
11
|
-
media: query,
|
|
12
|
-
addEventListener: vi.fn(),
|
|
13
|
-
removeEventListener: vi.fn(),
|
|
14
|
-
})),
|
|
15
|
-
);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test("returns false initially", () => {
|
|
19
|
-
const { result } = renderHook(() => useViewportMatch("(min-width: 768px)"));
|
|
20
|
-
expect(result.current).toBe(false);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("returns true when matched", () => {
|
|
24
|
-
vi.stubGlobal(
|
|
25
|
-
"matchMedia",
|
|
26
|
-
vi.fn().mockImplementation(() => ({
|
|
27
|
-
matches: true,
|
|
28
|
-
addEventListener: vi.fn(),
|
|
29
|
-
removeEventListener: vi.fn(),
|
|
30
|
-
})),
|
|
31
|
-
);
|
|
32
|
-
const { result } = renderHook(() => useViewportMatch("(min-width: 768px)"));
|
|
33
|
-
expect(result.current).toBe(true);
|
|
34
|
-
});
|
|
35
|
-
});
|
package/tests/setup.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
getLocalStorage,
|
|
4
|
-
updateLocalStorage,
|
|
5
|
-
removeLocalStorage,
|
|
6
|
-
getSessionStorage,
|
|
7
|
-
updateSessionStorage,
|
|
8
|
-
removeSessionStorage,
|
|
9
|
-
} from "@/packages/utils/browserStorage";
|
|
10
|
-
|
|
11
|
-
describe("browserStorage", () => {
|
|
12
|
-
let mockStorage: Record<string, string>;
|
|
13
|
-
let mockStorage2: Record<string, string>;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mockStorage = {};
|
|
17
|
-
mockStorage2 = {};
|
|
18
|
-
|
|
19
|
-
const createMockStorage = (store: Record<string, string>) => ({
|
|
20
|
-
getItem: vi.fn((key) => store[key] ?? null),
|
|
21
|
-
setItem: vi.fn((key, value) => { store[key] = value.toString(); }),
|
|
22
|
-
removeItem: vi.fn((key) => { delete store[key]; }),
|
|
23
|
-
clear: vi.fn(() => { Object.keys(store).forEach((k) => delete store[k]); }),
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
vi.stubGlobal("localStorage", createMockStorage(mockStorage));
|
|
27
|
-
vi.stubGlobal("sessionStorage", createMockStorage(mockStorage2));
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
afterEach(() => { vi.unstubAllGlobals(); });
|
|
31
|
-
|
|
32
|
-
test("localStorage operations", () => {
|
|
33
|
-
updateLocalStorage("foo", { bar: "baz" });
|
|
34
|
-
expect(localStorage.getItem("foo")).toBe('{"bar":"baz"}');
|
|
35
|
-
expect(getLocalStorage("foo")).toEqual({ bar: "baz" });
|
|
36
|
-
|
|
37
|
-
removeLocalStorage("foo");
|
|
38
|
-
expect(getLocalStorage("foo")).toBeNull();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("sessionStorage operations", () => {
|
|
42
|
-
updateSessionStorage("foo", { bar: "baz" });
|
|
43
|
-
expect(sessionStorage.getItem("foo")).toBe('{"bar":"baz"}');
|
|
44
|
-
expect(getSessionStorage("foo")).toEqual({ bar: "baz" });
|
|
45
|
-
|
|
46
|
-
removeSessionStorage("foo");
|
|
47
|
-
expect(getSessionStorage("foo")).toBeNull();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("handles invalid json gracefully", () => {
|
|
51
|
-
localStorage.setItem("invalid", "not-json");
|
|
52
|
-
expect(getLocalStorage("invalid")).toBeNull();
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { render, screen } from "@testing-library/react";
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { buildContext } from "@/packages/utils/buildContext";
|
|
5
|
-
|
|
6
|
-
describe("buildContext", () => {
|
|
7
|
-
const [Provider, useValue] = buildContext<string>("default");
|
|
8
|
-
|
|
9
|
-
function TestComponent() {
|
|
10
|
-
const val = useValue();
|
|
11
|
-
return <div data-testid="val">{val}</div>;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
test("returns default value when not wrapped in provider", () => {
|
|
15
|
-
render(<TestComponent />);
|
|
16
|
-
expect(screen.getByTestId("val").textContent).toBe("default");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("returns provided value", () => {
|
|
20
|
-
render(
|
|
21
|
-
<Provider value="provided">
|
|
22
|
-
<TestComponent />
|
|
23
|
-
</Provider>,
|
|
24
|
-
);
|
|
25
|
-
expect(screen.getByTestId("val").textContent).toBe("provided");
|
|
26
|
-
});
|
|
27
|
-
});
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, afterEach } from "vitest";
|
|
2
|
-
import { getDeviceInfo } from "@/packages/utils/checkDevice";
|
|
3
|
-
|
|
4
|
-
describe("getDeviceInfo", () => {
|
|
5
|
-
const originalUserAgent = navigator.userAgent;
|
|
6
|
-
|
|
7
|
-
afterEach(() => {
|
|
8
|
-
Object.defineProperty(navigator, "userAgent", {
|
|
9
|
-
value: originalUserAgent,
|
|
10
|
-
writable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("returns default values in SSR (no window)", () => {
|
|
16
|
-
const win = global.window;
|
|
17
|
-
(global as any).window = undefined;
|
|
18
|
-
const info = getDeviceInfo();
|
|
19
|
-
expect(info.isMobile).toBe(false);
|
|
20
|
-
expect(info.browser).toBe("unknown");
|
|
21
|
-
global.window = win;
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("detects mobile Chrome", () => {
|
|
25
|
-
Object.defineProperty(navigator, "userAgent", {
|
|
26
|
-
value: "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
|
|
27
|
-
writable: true,
|
|
28
|
-
configurable: true,
|
|
29
|
-
});
|
|
30
|
-
const info = getDeviceInfo();
|
|
31
|
-
expect(info.isMobile).toBe(true);
|
|
32
|
-
expect(info.isAndroid).toBe(true);
|
|
33
|
-
expect(info.browser).toBe("chrome");
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("detects iOS Safari", () => {
|
|
37
|
-
Object.defineProperty(navigator, "userAgent", {
|
|
38
|
-
value: "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
|
|
39
|
-
writable: true,
|
|
40
|
-
configurable: true,
|
|
41
|
-
});
|
|
42
|
-
const info = getDeviceInfo();
|
|
43
|
-
expect(info.isMobile).toBe(true);
|
|
44
|
-
expect(info.isIOS).toBe(true);
|
|
45
|
-
expect(info.isSafari).toBe(true);
|
|
46
|
-
expect(info.isIOSSafari).toBe(true);
|
|
47
|
-
expect(info.browser).toBe("safari");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("detects desktop Chrome", () => {
|
|
51
|
-
Object.defineProperty(navigator, "userAgent", {
|
|
52
|
-
value: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
53
|
-
writable: true,
|
|
54
|
-
configurable: true,
|
|
55
|
-
});
|
|
56
|
-
const info = getDeviceInfo();
|
|
57
|
-
expect(info.isMobile).toBe(false);
|
|
58
|
-
expect(info.browser).toBe("chrome");
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test("detects Mac Safari", () => {
|
|
62
|
-
Object.defineProperty(navigator, "userAgent", {
|
|
63
|
-
value: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/604.1",
|
|
64
|
-
writable: true,
|
|
65
|
-
configurable: true,
|
|
66
|
-
});
|
|
67
|
-
const info = getDeviceInfo();
|
|
68
|
-
expect(info.isMobile).toBe(false);
|
|
69
|
-
expect(info.isMacSafari).toBe(true);
|
|
70
|
-
expect(info.isSafari).toBe(true);
|
|
71
|
-
expect(info.browser).toBe("safari");
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test("detects Samsung Browser", () => {
|
|
75
|
-
Object.defineProperty(navigator, "userAgent", {
|
|
76
|
-
value: "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/24.0 Chrome/120.0.6099.230 Mobile Safari/537.36",
|
|
77
|
-
writable: true,
|
|
78
|
-
configurable: true,
|
|
79
|
-
});
|
|
80
|
-
const info = getDeviceInfo();
|
|
81
|
-
expect(info.isSamsungBrowser).toBe(true);
|
|
82
|
-
expect(info.browser).toBe("samsung");
|
|
83
|
-
});
|
|
84
|
-
});
|