@musecat/functionkit 1.0.2 → 1.1.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.
Files changed (72) hide show
  1. package/.agents/references/hooks/useIntersectionObserver.md +4 -0
  2. package/.agents/references/hooks/useInterval.md +4 -0
  3. package/.agents/references/hooks/usePreservedCallback.md +4 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  6. package/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  7. package/.github/workflows/ci.yml +20 -0
  8. package/.local/state/gh/device-id +1 -0
  9. package/.prettierrc +8 -0
  10. package/AGENTS.md +14 -0
  11. package/CODE_OF_CONDUCT.md +55 -0
  12. package/CONTRIBUTING.md +39 -0
  13. package/biome.json +25 -0
  14. package/index.ts +1 -1
  15. package/package.json +21 -2
  16. package/packages/components/ScrolltoTop.tsx +1 -1
  17. package/packages/components/ViewportPortal.tsx +1 -2
  18. package/packages/cookie/cookie.shared.ts +7 -33
  19. package/packages/cookie/cookieNames.shared.ts +9 -0
  20. package/packages/datetime/dateTime.client.ts +1 -3
  21. package/packages/datetime/dateTime.server.ts +1 -3
  22. package/packages/datetime/dateTime.shared.ts +9 -47
  23. package/packages/hooks/useCheckInvisible.ts +1 -1
  24. package/packages/hooks/useClientDateTime.ts +3 -16
  25. package/packages/hooks/useDebounce.ts +2 -7
  26. package/packages/hooks/useGeolocation.ts +1 -5
  27. package/packages/hooks/useInterval.ts +1 -2
  28. package/packages/hooks/useKeyboardListNavigation.ts +10 -38
  29. package/packages/hooks/useLongPress.ts +13 -24
  30. package/packages/hooks/useRelativeDateTime.ts +1 -4
  31. package/packages/hooks/useViewportHeight.ts +1 -2
  32. package/packages/hooks/useViewportMatch.ts +0 -4
  33. package/packages/utils/buildContext.tsx +2 -3
  34. package/packages/utils/floatingMotion.ts +14 -20
  35. package/packages/utils/subscribeKeyboardHeight.ts +3 -0
  36. package/tests/components/ScrolltoTop.test.tsx +1 -1
  37. package/tests/components/SwitchCase.test.tsx +1 -2
  38. package/tests/components/ViewportPortal.test.tsx +10 -6
  39. package/tests/cookie/cookie.test.ts +47 -11
  40. package/tests/datetime/datetime.test.ts +257 -46
  41. package/tests/hooks/useAvoidKeyboard.test.ts +32 -1
  42. package/tests/hooks/useCheckInvisible.test.ts +36 -5
  43. package/tests/hooks/useCheckScroll.test.ts +2 -2
  44. package/tests/hooks/useClientDateTime.test.ts +2 -4
  45. package/tests/hooks/useDebounce.test.ts +30 -5
  46. package/tests/hooks/useDebouncedCallback.test.ts +41 -12
  47. package/tests/hooks/useDoubleClick.test.ts +58 -7
  48. package/tests/hooks/useGeolocation.test.ts +155 -4
  49. package/tests/hooks/useHasMounted.test.ts +1 -1
  50. package/tests/hooks/useIntersectionObserver.test.ts +70 -5
  51. package/tests/hooks/useInterval.test.ts +28 -3
  52. package/tests/hooks/useKeyboardHeight.test.ts +1 -1
  53. package/tests/hooks/useKeyboardListNavigation.test.ts +340 -18
  54. package/tests/hooks/useLongPress.test.ts +177 -15
  55. package/tests/hooks/usePreservedCallback.test.ts +7 -9
  56. package/tests/hooks/usePreservedReference.test.ts +19 -12
  57. package/tests/hooks/useRefEffect.test.ts +43 -6
  58. package/tests/hooks/useRelativeDateTime.test.ts +8 -6
  59. package/tests/hooks/useTimeout.test.ts +43 -5
  60. package/tests/hooks/useToggleState.test.ts +14 -6
  61. package/tests/hooks/useViewportHeight.test.ts +24 -2
  62. package/tests/hooks/useViewportMatch.test.ts +1 -1
  63. package/tests/utils/browserStorage.test.ts +68 -8
  64. package/tests/utils/buildContext.test.tsx +1 -2
  65. package/tests/utils/checkDevice.test.ts +62 -6
  66. package/tests/utils/clipboardShare.test.ts +79 -5
  67. package/tests/utils/floatingMotion.test.ts +60 -9
  68. package/tests/utils/keyboardTarget.test.ts +42 -1
  69. package/tests/utils/mergeRefs.test.ts +33 -1
  70. package/tests/utils/seen.test.ts +16 -7
  71. package/tests/utils/subscribeKeyboardHeight.test.ts +124 -2
  72. package/vitest.config.ts +7 -1
@@ -10,18 +10,13 @@ type UseKeyboardListNavigationOptions = {
10
10
  itemCount: number;
11
11
  };
12
12
 
13
- export function useKeyboardListNavigation({
14
- itemCount,
15
- }: UseKeyboardListNavigationOptions) {
13
+ export function useKeyboardListNavigation({ itemCount }: UseKeyboardListNavigationOptions) {
16
14
  const [activeIndex, setActiveIndex] = useState(-1);
17
15
  const itemRefs = useRef<(HTMLElement | null)[]>([]);
18
16
 
19
- const setItemRef = useCallback(
20
- (index: number, element: HTMLElement | null) => {
21
- itemRefs.current[index] = element;
22
- },
23
- [],
24
- );
17
+ const setItemRef = useCallback((index: number, element: HTMLElement | null) => {
18
+ itemRefs.current[index] = element;
19
+ }, []);
25
20
 
26
21
  const focusItem = useCallback((index: number) => {
27
22
  const target = itemRefs.current[index];
@@ -59,18 +54,6 @@ export function useKeyboardListNavigation({
59
54
 
60
55
  const moveActiveItem = useCallback(
61
56
  (key: string) => {
62
- if (itemCount === 0) {
63
- return false;
64
- }
65
-
66
- if (key === "Home") {
67
- return focusItem(0);
68
- }
69
-
70
- if (key === "End") {
71
- return focusItem(itemCount - 1);
72
- }
73
-
74
57
  if (key === "ArrowDown" || key === "ArrowRight") {
75
58
  const nextIndex = activeIndex < 0 ? 0 : (activeIndex + 1) % itemCount;
76
59
  return focusItem(nextIndex);
@@ -78,15 +61,13 @@ export function useKeyboardListNavigation({
78
61
 
79
62
  if (key === "ArrowUp" || key === "ArrowLeft") {
80
63
  const nextIndex =
81
- activeIndex < 0
82
- ? itemCount - 1
83
- : (activeIndex - 1 + itemCount) % itemCount;
64
+ activeIndex < 0 ? itemCount - 1 : (activeIndex - 1 + itemCount) % itemCount;
84
65
  return focusItem(nextIndex);
85
66
  }
86
67
 
87
- return false;
68
+ return focusBoundaryItem(key);
88
69
  },
89
- [activeIndex, focusItem, itemCount],
70
+ [activeIndex, focusItem, focusBoundaryItem, itemCount],
90
71
  );
91
72
 
92
73
  const clickActiveItem = useCallback(() => {
@@ -99,10 +80,7 @@ export function useKeyboardListNavigation({
99
80
  }, [activeIndex]);
100
81
 
101
82
  const handleListKeyDown = useCallback(
102
- (
103
- event: React.KeyboardEvent<HTMLElement>,
104
- options?: { container?: HTMLElement | null },
105
- ) => {
83
+ (event: React.KeyboardEvent<HTMLElement>, options?: { container?: HTMLElement | null }) => {
106
84
  if (itemCount === 0 || event.defaultPrevented) {
107
85
  return;
108
86
  }
@@ -144,15 +122,9 @@ export function useKeyboardListNavigation({
144
122
  return;
145
123
  }
146
124
 
147
- if (moveActiveItem(event.key)) {
148
- return;
149
- }
150
-
151
- if (focusBoundaryItem(event.key)) {
152
- return;
153
- }
125
+ moveActiveItem(event.key);
154
126
  },
155
- [clickActiveItem, moveActiveItem, focusBoundaryItem, itemCount],
127
+ [clickActiveItem, moveActiveItem, itemCount],
156
128
  );
157
129
 
158
130
  useEffect(() => {
@@ -14,12 +14,7 @@ export type UseLongPressOptions<E extends HTMLElement> = {
14
14
 
15
15
  export function useLongPress<E extends HTMLElement = HTMLElement>(
16
16
  onLongPress: (event: MouseEvent<E> | TouchEvent<E>) => void,
17
- {
18
- delay = 500,
19
- moveThreshold,
20
- onClick,
21
- onLongPressEnd,
22
- }: UseLongPressOptions<E> = {},
17
+ { delay = 500, moveThreshold, onClick, onLongPressEnd }: UseLongPressOptions<E> = {},
23
18
  ) {
24
19
  const timeoutRef = useRef<number | null>(null);
25
20
  const isLongPressActiveRef = useRef(false);
@@ -32,22 +27,18 @@ export function useLongPress<E extends HTMLElement = HTMLElement>(
32
27
  savedOnClick.current = onClick;
33
28
  savedOnLongPressEnd.current = onLongPressEnd;
34
29
 
35
- const hasThreshold =
36
- moveThreshold?.x !== undefined || moveThreshold?.y !== undefined;
30
+ const hasThreshold = moveThreshold?.x !== undefined || moveThreshold?.y !== undefined;
37
31
 
38
- const getClientPosition = useCallback(
39
- (event: MouseEvent<E> | TouchEvent<E>) => {
40
- if ("touches" in event.nativeEvent) {
41
- const touch = event.nativeEvent.touches[0];
42
- return { x: touch.clientX, y: touch.clientY };
43
- }
44
- return {
45
- x: event.nativeEvent.clientX,
46
- y: event.nativeEvent.clientY,
47
- };
48
- },
49
- [],
50
- );
32
+ const getClientPosition = useCallback((event: MouseEvent<E> | TouchEvent<E>) => {
33
+ if ("touches" in event.nativeEvent) {
34
+ const touch = event.nativeEvent.touches[0];
35
+ return { x: touch.clientX, y: touch.clientY };
36
+ }
37
+ return {
38
+ x: event.nativeEvent.clientX,
39
+ y: event.nativeEvent.clientY,
40
+ };
41
+ }, []);
51
42
 
52
43
  const isMovedBeyondThreshold = useCallback(
53
44
  (event: MouseEvent<E> | TouchEvent<E>) => {
@@ -113,8 +104,6 @@ export function useLongPress<E extends HTMLElement = HTMLElement>(
113
104
  onMouseLeave: cancelLongPress,
114
105
  onTouchStart: handlePressStart,
115
106
  onTouchEnd: handlePressEnd,
116
- ...(hasThreshold
117
- ? { onTouchMove: handlePressMove, onMouseMove: handlePressMove }
118
- : {}),
107
+ ...(hasThreshold ? { onTouchMove: handlePressMove, onMouseMove: handlePressMove } : {}),
119
108
  };
120
109
  }
@@ -12,10 +12,7 @@ type UseRelativeDateTimeOptions = {
12
12
  updateIntervalMs?: number;
13
13
  };
14
14
 
15
- export function useRelativeDateTime(
16
- value: DateInput,
17
- options?: UseRelativeDateTimeOptions,
18
- ) {
15
+ export function useRelativeDateTime(value: DateInput, options?: UseRelativeDateTimeOptions) {
19
16
  const [ready, setReady] = useState(false);
20
17
  const [text, setText] = useState("");
21
18
  const [isRelative, setIsRelative] = useState(false);
@@ -6,8 +6,7 @@ export function useViewportHeight() {
6
6
  const [height, setHeight] = useState(0);
7
7
 
8
8
  useEffect(() => {
9
- const update = () =>
10
- setHeight(window.visualViewport?.height ?? window.innerHeight);
9
+ const update = () => setHeight(window.visualViewport?.height ?? window.innerHeight);
11
10
 
12
11
  update();
13
12
  window.visualViewport?.addEventListener("resize", update);
@@ -6,10 +6,6 @@ export function useViewportMatch(mediaQuery: string): boolean {
6
6
  const [isMatched, setIsMatched] = useState(false);
7
7
 
8
8
  useEffect(() => {
9
- if (typeof window === "undefined") {
10
- return;
11
- }
12
-
13
9
  const mediaQueryList = window.matchMedia(mediaQuery);
14
10
  const syncMatchState = () => {
15
11
  setIsMatched(mediaQueryList.matches);
@@ -1,13 +1,12 @@
1
1
  "use client";
2
2
 
3
- import { createContext, type ReactNode, useContext, useMemo } from "react";
3
+ import { createContext, type ReactNode, useContext } from "react";
4
4
 
5
5
  export function buildContext<T>(defaultValue: T) {
6
6
  const Ctx = createContext<T>(defaultValue);
7
7
 
8
8
  function Provider({ value, children }: { value: T; children: ReactNode }) {
9
- const stable = useMemo(() => value, [value]);
10
- return <Ctx.Provider value={stable}>{children}</Ctx.Provider>;
9
+ return <Ctx.Provider value={value}>{children}</Ctx.Provider>;
11
10
  }
12
11
 
13
12
  function useValue() {
@@ -1,8 +1,4 @@
1
- export type FloatingMotionMode =
2
- | "anchored"
3
- | "center-selected"
4
- | "modal-center"
5
- | "mobile-sheet";
1
+ export type FloatingMotionMode = "anchored" | "center-selected" | "modal-center" | "mobile-sheet";
6
2
 
7
3
  export type FloatingPlacement =
8
4
  | "top-left"
@@ -21,9 +17,7 @@ export interface FloatingMotionPreset {
21
17
  ease: string;
22
18
  }
23
19
 
24
- export const getFloatingMotionPreset = (
25
- mode: FloatingMotionMode,
26
- ): FloatingMotionPreset => {
20
+ export const getFloatingMotionPreset = (mode: FloatingMotionMode): FloatingMotionPreset => {
27
21
  if (mode === "mobile-sheet") {
28
22
  return {
29
23
  enterMs: 360,
@@ -55,15 +49,20 @@ export const getFloatingMotionPreset = (
55
49
  };
56
50
  };
57
51
 
52
+ type FloatingRow = "top" | "middle" | "bottom";
53
+ type FloatingCol = "left" | "center" | "right";
54
+
55
+ function parsePlacement(placement: FloatingPlacement): [FloatingRow, FloatingCol] {
56
+ const [row, col] = placement.split("-") as [FloatingRow, FloatingCol];
57
+ return [row, col];
58
+ }
59
+
58
60
  export const getFloatingTransformOrigin = (
59
61
  placement?: FloatingPlacement,
60
62
  ): string => {
61
63
  if (!placement) return "top center";
62
64
 
63
- const [row, col] = placement.split("-") as [
64
- "top" | "middle" | "bottom",
65
- "left" | "center" | "right",
66
- ];
65
+ const [row, col] = parsePlacement(placement);
67
66
  const y = row === "top" ? "bottom" : row === "bottom" ? "top" : "center";
68
67
  const x = col === "right" ? "right" : col === "left" ? "left" : "center";
69
68
 
@@ -82,18 +81,13 @@ export const getFloatingHiddenTransform = ({
82
81
  if (mode === "center-selected") return "translateY(.45rem) scale(.99)";
83
82
  if (!placement) return "translateY(.4rem) scale(.975)";
84
83
 
85
- const [row, col] = placement.split("-") as [
86
- "top" | "middle" | "bottom",
87
- "left" | "center" | "right",
88
- ];
84
+ const [row, col] = parsePlacement(placement);
89
85
 
90
86
  if (row === "top") return "translateY(.4rem) scale(.975)";
91
87
  if (row === "bottom") return "translateY(-.4rem) scale(.975)";
92
88
 
93
- if (row === "middle") {
94
- if (col === "left") return "translateX(.4rem) scale(.975)";
95
- if (col === "right") return "translateX(-.4rem) scale(.975)";
96
- }
89
+ if (col === "left") return "translateX(.4rem) scale(.975)";
90
+ if (col === "right") return "translateX(-.4rem) scale(.975)";
97
91
 
98
92
  return "translateY(.4rem) scale(.975)";
99
93
  };
@@ -12,6 +12,7 @@ export function subscribeKeyboardHeight({
12
12
  throttleMs = 16,
13
13
  }: SubscribeKeyboardHeightOptions) {
14
14
  let ticking = false;
15
+ let disposed = false;
15
16
  let lastHeight = 0;
16
17
 
17
18
  const notify = (height: number) => {
@@ -19,6 +20,7 @@ export function subscribeKeyboardHeight({
19
20
  ticking = true;
20
21
 
21
22
  const run = () => {
23
+ if (disposed) return;
22
24
  if (height !== lastHeight) {
23
25
  lastHeight = height;
24
26
  callback(height);
@@ -47,6 +49,7 @@ export function subscribeKeyboardHeight({
47
49
 
48
50
  return {
49
51
  unsubscribe() {
52
+ disposed = true;
50
53
  window.visualViewport?.removeEventListener("resize", handleResize);
51
54
  window.visualViewport?.removeEventListener("scroll", handleResize);
52
55
  },
@@ -1,5 +1,5 @@
1
- import { describe, test, expect, vi } from "vitest";
2
1
  import { render } from "@testing-library/react";
2
+ import { describe, expect, test, vi } from "vitest";
3
3
  import { ScrolltoTop } from "@/packages/components/ScrolltoTop";
4
4
 
5
5
  describe("ScrolltoTop", () => {
@@ -1,7 +1,6 @@
1
- import { describe, test, expect } from "vitest";
2
1
  import { render } from "@testing-library/react";
2
+ import { describe, expect, test } from "vitest";
3
3
  import { SwitchCase } from "@/packages/components/SwitchCase";
4
- import React from "react";
5
4
 
6
5
  describe("SwitchCase", () => {
7
6
  const cases = {
@@ -1,10 +1,6 @@
1
- import { describe, test, expect, beforeEach } from "vitest";
2
1
  import { render, screen } from "@testing-library/react";
3
- import {
4
- ViewportPortal,
5
- getViewportPortalRoot,
6
- } from "@/packages/components/ViewportPortal";
7
- import React from "react";
2
+ import { beforeEach, describe, expect, test } from "vitest";
3
+ import { getViewportPortalRoot, ViewportPortal } from "@/packages/components/ViewportPortal";
8
4
 
9
5
  describe("ViewportPortal", () => {
10
6
  beforeEach(() => {
@@ -25,6 +21,14 @@ describe("ViewportPortal", () => {
25
21
  expect(document.querySelectorAll("#viewport-portal-root").length).toBe(1);
26
22
  });
27
23
 
24
+ test("getViewportPortalRoot returns null when document is undefined (SSR)", () => {
25
+ const origDocument = global.document;
26
+ // @ts-expect-error
27
+ delete global.document;
28
+ expect(getViewportPortalRoot()).toBeNull();
29
+ global.document = origDocument;
30
+ });
31
+
28
32
  test("ViewportPortal renders children into the portal root", () => {
29
33
  render(
30
34
  <ViewportPortal>
@@ -1,11 +1,11 @@
1
- import { describe, test, expect, beforeEach, vi, afterEach } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
2
  import {
3
- parseClientCookieNames,
3
+ clearAllClientCookies,
4
+ clearClientCookie,
4
5
  getClientCookie,
5
6
  setClientCookie,
6
- clearClientCookie,
7
- clearAllClientCookies,
8
7
  } from "@/packages/cookie/cookie.shared";
8
+ import { parseClientCookieNames } from "@/packages/cookie/cookieNames.shared";
9
9
 
10
10
  describe("cookie module", () => {
11
11
  beforeEach(() => {
@@ -44,6 +44,11 @@ describe("cookie module", () => {
44
44
  expect(getClientCookie("baz")).toBe("qux");
45
45
  });
46
46
 
47
+ test("skips cookies with empty name when parsing", () => {
48
+ document.cookie = "=value; foo=bar";
49
+ expect(getClientCookie("foo")).toBe("bar");
50
+ });
51
+
47
52
  test("returns undefined if cookie does not exist", () => {
48
53
  document.cookie = "foo=bar";
49
54
  expect(getClientCookie("missing")).toBeUndefined();
@@ -51,7 +56,7 @@ describe("cookie module", () => {
51
56
 
52
57
  test("handles undefined document", () => {
53
58
  const originalDocument = global.document;
54
- // @ts-ignore
59
+ // @ts-expect-error
55
60
  delete global.document;
56
61
 
57
62
  expect(getClientCookie("foo")).toBeUndefined();
@@ -61,6 +66,37 @@ describe("cookie module", () => {
61
66
  });
62
67
 
63
68
  describe("setClientCookie", () => {
69
+ test("handles undefined document in setClientCookie", () => {
70
+ const origDocument = global.document;
71
+ // @ts-expect-error
72
+ delete global.document;
73
+ setClientCookie("foo", "bar");
74
+ global.document = origDocument;
75
+ });
76
+
77
+ test("parseClientCookie handles malformed entries", () => {
78
+ const result = parseClientCookieNames("=value; key");
79
+ expect(result).toEqual(["key"]);
80
+ });
81
+
82
+ test("clearAllClientCookies handles empty cookie name", () => {
83
+ const mockDoc = { cookie: "=1;;" };
84
+ const entries = clearAllClientCookies({ documentRef: mockDoc as any });
85
+ expect(Array.isArray(entries)).toBe(true);
86
+ });
87
+
88
+ test("clearAllClientCookies skips entries with empty name", () => {
89
+ const mockDoc = { cookie: "a=1;;b=2" };
90
+ const entries = clearAllClientCookies({ documentRef: mockDoc as any });
91
+ // Entries with empty names should be skipped in the loop
92
+ expect(entries).toEqual(["a", "b"]);
93
+ });
94
+
95
+ test("setClientCookie with days=0 does not add expires", () => {
96
+ setClientCookie("foo", "bar", 0);
97
+ expect(document.cookie).toBe("foo=bar; path=/");
98
+ });
99
+
64
100
  test("sets cookie with name and value", () => {
65
101
  setClientCookie("foo", "bar");
66
102
  expect(document.cookie).toBe("foo=bar; path=/");
@@ -98,7 +134,7 @@ describe("cookie module", () => {
98
134
  clearClientCookie("foo", {
99
135
  hostname: "custom.com",
100
136
  path: "/custom",
101
- documentRef: mockDoc as any,
137
+ documentRef: mockDoc,
102
138
  });
103
139
  expect(mockDoc.cookie).toBe(
104
140
  "foo=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/custom; domain=custom.com;",
@@ -109,7 +145,7 @@ describe("cookie module", () => {
109
145
  describe("clearAllClientCookies", () => {
110
146
  test("clears all cookies based on documentRef.cookie", () => {
111
147
  const mockDoc = { cookie: "a=1; b=2" };
112
- const entries = clearAllClientCookies({ documentRef: mockDoc as any });
148
+ const entries = clearAllClientCookies({ documentRef: mockDoc });
113
149
 
114
150
  expect(entries).toEqual(["a", "b"]);
115
151
  expect(mockDoc.cookie).toContain(
@@ -122,8 +158,8 @@ describe("cookie module", () => {
122
158
  const mockDoc = { cookie: "a=1; b=2" };
123
159
 
124
160
  const entries = clearAllClientCookies({
125
- documentRef: mockDoc as any,
126
- cookieStore: cookieStore as any,
161
+ documentRef: mockDoc,
162
+ cookieStore,
127
163
  });
128
164
 
129
165
  expect(entries).toEqual(["a", "b"]);
@@ -133,7 +169,7 @@ describe("cookie module", () => {
133
169
 
134
170
  test("clears cookies from root path when includeRoot is true", () => {
135
171
  const mockDoc = { cookie: "a=1" };
136
- clearAllClientCookies({ documentRef: mockDoc as any, includeRoot: true });
172
+ clearAllClientCookies({ documentRef: mockDoc, includeRoot: true });
137
173
 
138
174
  // The function iterates and updates document.cookie, so it will contain the last assignment.
139
175
  // With paths ["/", "/test/path"] and domain "example.com"
@@ -145,7 +181,7 @@ describe("cookie module", () => {
145
181
  test("uses provided cookieString instead of documentRef.cookie", () => {
146
182
  const mockDoc = { cookie: "a=1" };
147
183
  const entries = clearAllClientCookies({
148
- documentRef: mockDoc as any,
184
+ documentRef: mockDoc,
149
185
  cookieString: "x=1; y=2",
150
186
  });
151
187