react-panel-layout 0.6.1 → 0.7.1

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 (127) hide show
  1. package/dist/FloatingWindow-CE-WzkNv.js +1542 -0
  2. package/dist/FloatingWindow-CE-WzkNv.js.map +1 -0
  3. package/dist/FloatingWindow-DpFpmX1f.cjs +2 -0
  4. package/dist/FloatingWindow-DpFpmX1f.cjs.map +1 -0
  5. package/dist/GridLayout-EwKszYBy.cjs +2 -0
  6. package/dist/{GridLayout-DKTg_N61.cjs.map → GridLayout-EwKszYBy.cjs.map} +1 -1
  7. package/dist/GridLayout-kiWdpMLQ.js +947 -0
  8. package/dist/{GridLayout-UWNxXw77.js.map → GridLayout-kiWdpMLQ.js.map} +1 -1
  9. package/dist/PanelSystem-Dmy5YI_6.cjs +3 -0
  10. package/dist/PanelSystem-Dmy5YI_6.cjs.map +1 -0
  11. package/dist/{PanelSystem-BqUzNtf2.js → PanelSystem-DrYsYwuV.js} +208 -247
  12. package/dist/PanelSystem-DrYsYwuV.js.map +1 -0
  13. package/dist/components/window/Drawer.d.ts +1 -0
  14. package/dist/components/window/DrawerRevealContext.d.ts +61 -0
  15. package/dist/components/window/drawerRevealAnimationUtils.d.ts +212 -0
  16. package/dist/components/window/drawerStyles.d.ts +5 -0
  17. package/dist/components/window/useDrawerSwipeTransform.d.ts +8 -2
  18. package/dist/components/window/useDrawerTransform.d.ts +68 -0
  19. package/dist/components/window/useRevealDrawerTransform.d.ts +56 -0
  20. package/dist/config.cjs +1 -1
  21. package/dist/config.cjs.map +1 -1
  22. package/dist/config.js +8 -7
  23. package/dist/config.js.map +1 -1
  24. package/dist/dialog/index.d.ts +1 -1
  25. package/dist/grid.cjs +1 -1
  26. package/dist/grid.js +2 -2
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.js +4 -4
  29. package/dist/modules/dialog/DialogContainer.d.ts +22 -2
  30. package/dist/modules/dialog/Modal.d.ts +23 -2
  31. package/dist/modules/dialog/SwipeDialogContainer.d.ts +6 -2
  32. package/dist/modules/dialog/types.d.ts +12 -0
  33. package/dist/modules/drawer/drawerStateMachine.d.ts +168 -0
  34. package/dist/modules/drawer/revealDrawerConstants.d.ts +33 -0
  35. package/dist/modules/drawer/revealDrawerStateMachine.d.ts +146 -0
  36. package/dist/modules/drawer/strategies/index.d.ts +8 -0
  37. package/dist/modules/drawer/strategies/overlayStrategy.d.ts +12 -0
  38. package/dist/modules/drawer/strategies/revealStrategy.d.ts +12 -0
  39. package/dist/modules/drawer/strategies/types.d.ts +116 -0
  40. package/dist/panels.cjs +1 -1
  41. package/dist/panels.js +1 -1
  42. package/dist/stack.cjs +1 -1
  43. package/dist/stack.cjs.map +1 -1
  44. package/dist/stack.js +306 -347
  45. package/dist/stack.js.map +1 -1
  46. package/dist/types.d.ts +14 -0
  47. package/dist/useAnimationFrame-CRuFlk5t.js +394 -0
  48. package/dist/useAnimationFrame-CRuFlk5t.js.map +1 -0
  49. package/dist/useAnimationFrame-XRpDXkwV.cjs +2 -0
  50. package/dist/useAnimationFrame-XRpDXkwV.cjs.map +1 -0
  51. package/dist/window.cjs +1 -1
  52. package/dist/window.js +1 -1
  53. package/package.json +1 -1
  54. package/src/components/gesture/SwipeSafeZone.tsx +1 -0
  55. package/src/components/grid/GridLayout.tsx +110 -38
  56. package/src/components/window/Drawer.tsx +114 -10
  57. package/src/components/window/DrawerLayers.tsx +48 -15
  58. package/src/components/window/DrawerRevealContext.spec.ts +20 -0
  59. package/src/components/window/DrawerRevealContext.tsx +99 -0
  60. package/src/components/window/drawerRevealAnimationUtils.spec.ts +375 -0
  61. package/src/components/window/drawerRevealAnimationUtils.ts +415 -0
  62. package/src/components/window/drawerStyles.spec.ts +39 -0
  63. package/src/components/window/drawerStyles.ts +24 -0
  64. package/src/components/window/useDrawerSwipeTransform.ts +28 -90
  65. package/src/components/window/useDrawerTransform.ts +505 -0
  66. package/src/components/window/useRevealDrawerTransform.spec.ts +1936 -0
  67. package/src/components/window/useRevealDrawerTransform.ts +105 -0
  68. package/src/demo/components/FullscreenDemoPage.tsx +47 -0
  69. package/src/demo/fullscreenRoutes.tsx +32 -0
  70. package/src/demo/index.tsx +5 -0
  71. package/src/demo/pages/Dialog/components/CardExpandDemo.tsx +23 -8
  72. package/src/demo/pages/Drawer/components/DrawerBasics.module.css +6 -1
  73. package/src/demo/pages/Drawer/components/DrawerBasics.tsx +14 -4
  74. package/src/demo/pages/Drawer/components/DrawerReveal.module.css +157 -0
  75. package/src/demo/pages/Drawer/components/DrawerReveal.tsx +128 -0
  76. package/src/demo/pages/Drawer/reveal/index.tsx +17 -0
  77. package/src/demo/pages/Drawer/reveal-fullscreen/index.tsx +135 -0
  78. package/src/demo/pages/Drawer/reveal-fullscreen/styles.module.css +233 -0
  79. package/src/demo/pages/Stack/components/StackBasics.spec.tsx +56 -52
  80. package/src/demo/pages/Stack/components/StackTablet.spec.tsx +39 -49
  81. package/src/demo/routes.tsx +2 -0
  82. package/src/dialog/index.ts +2 -0
  83. package/src/hooks/gesture/testing/createGestureSimulator.ts +1 -0
  84. package/src/hooks/gesture/useNativeGestureGuard.spec.ts +10 -2
  85. package/src/hooks/gesture/useSwipeInput.spec.ts +69 -0
  86. package/src/hooks/gesture/useSwipeInput.ts +2 -0
  87. package/src/hooks/gesture/utils.ts +15 -4
  88. package/src/hooks/useAnimatedVisibility.spec.ts +3 -3
  89. package/src/hooks/useOperationContinuity.spec.ts +17 -10
  90. package/src/hooks/useOperationContinuity.ts +5 -5
  91. package/src/hooks/useSharedElementTransition.ts +28 -7
  92. package/src/modules/dialog/DialogContainer.tsx +39 -5
  93. package/src/modules/dialog/Modal.tsx +46 -4
  94. package/src/modules/dialog/SwipeDialogContainer.tsx +12 -2
  95. package/src/modules/dialog/dialogAnimationUtils.spec.ts +0 -1
  96. package/src/modules/dialog/types.ts +14 -0
  97. package/src/modules/dialog/useDialogContainer.spec.ts +11 -3
  98. package/src/modules/dialog/useDialogSwipeInput.spec.ts +49 -28
  99. package/src/modules/dialog/useDialogSwipeInput.ts +37 -6
  100. package/src/modules/dialog/useDialogTransform.spec.ts +63 -30
  101. package/src/modules/drawer/drawerStateMachine.ts +500 -0
  102. package/src/modules/drawer/revealDrawerConstants.ts +38 -0
  103. package/src/modules/drawer/revealDrawerStateMachine.spec.ts +558 -0
  104. package/src/modules/drawer/revealDrawerStateMachine.ts +197 -0
  105. package/src/modules/drawer/strategies/index.ts +9 -0
  106. package/src/modules/drawer/strategies/overlayStrategy.ts +133 -0
  107. package/src/modules/drawer/strategies/revealStrategy.ts +111 -0
  108. package/src/modules/drawer/strategies/types.ts +160 -0
  109. package/src/modules/drawer/useDrawerSwipeInput.ts +7 -4
  110. package/src/modules/pivot/SwipePivotContent.spec.tsx +48 -37
  111. package/src/modules/pivot/usePivotSwipeInput.spec.ts +8 -8
  112. package/src/modules/stack/swipeTransitionContinuity.spec.tsx +1 -1
  113. package/src/types.ts +15 -0
  114. package/dist/FloatingWindow-CUXnEtrb.js +0 -827
  115. package/dist/FloatingWindow-CUXnEtrb.js.map +0 -1
  116. package/dist/FloatingWindow-DMwyK0eK.cjs +0 -2
  117. package/dist/FloatingWindow-DMwyK0eK.cjs.map +0 -1
  118. package/dist/GridLayout-DKTg_N61.cjs +0 -2
  119. package/dist/GridLayout-UWNxXw77.js +0 -926
  120. package/dist/PanelSystem-BqUzNtf2.js.map +0 -1
  121. package/dist/PanelSystem-D603LKKv.cjs +0 -3
  122. package/dist/PanelSystem-D603LKKv.cjs.map +0 -1
  123. package/dist/useNativeGestureGuard-C7TSqEkr.cjs +0 -2
  124. package/dist/useNativeGestureGuard-C7TSqEkr.cjs.map +0 -1
  125. package/dist/useNativeGestureGuard-CGYo6O0r.js +0 -347
  126. package/dist/useNativeGestureGuard-CGYo6O0r.js.map +0 -1
  127. package/src/components/window/useDrawerSwipeTransform.spec.ts +0 -234
@@ -1,20 +1,52 @@
1
1
  /**
2
2
  * @file Tests for useDialogSwipeInput hook
3
3
  */
4
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
5
4
  import { renderHook, act } from "@testing-library/react";
6
5
  import * as React from "react";
7
6
  import { useDialogSwipeInput } from "./useDialogSwipeInput.js";
8
7
 
9
- // Mock ResizeObserver
10
- vi.stubGlobal(
11
- "ResizeObserver",
12
- class {
13
- observe = vi.fn();
14
- unobserve = vi.fn();
15
- disconnect = vi.fn();
16
- },
17
- );
8
+ /**
9
+ * Call tracker for testing callbacks.
10
+ */
11
+ type CallTracker = {
12
+ calls: ReadonlyArray<ReadonlyArray<unknown>>;
13
+ fn: (...args: ReadonlyArray<unknown>) => void;
14
+ };
15
+
16
+ const createCallTracker = (): CallTracker => {
17
+ const calls: Array<ReadonlyArray<unknown>> = [];
18
+ const fn = (...args: ReadonlyArray<unknown>): void => {
19
+ calls.push(args);
20
+ };
21
+ return { calls, fn };
22
+ };
23
+
24
+ /**
25
+ * Cast native PointerEvent to React.PointerEvent for testing.
26
+ */
27
+ function asReactPointerEvent(e: PointerEvent): React.PointerEvent<HTMLElement> {
28
+ // eslint-disable-next-line custom/no-as-outside-guard -- test helper for event casting
29
+ return e as unknown as React.PointerEvent<HTMLElement>;
30
+ }
31
+
32
+ // Simple ResizeObserver mock
33
+ const originalResizeObserver = globalThis.ResizeObserver;
34
+
35
+ // eslint-disable-next-line no-restricted-syntax -- mock class needed for ResizeObserver
36
+ class MockResizeObserver {
37
+ observe(): void {}
38
+ unobserve(): void {}
39
+ disconnect(): void {}
40
+ }
41
+
42
+ beforeEach(() => {
43
+ // eslint-disable-next-line custom/no-as-outside-guard -- test mock assignment
44
+ globalThis.ResizeObserver = MockResizeObserver as unknown as typeof ResizeObserver;
45
+ });
46
+
47
+ afterEach(() => {
48
+ globalThis.ResizeObserver = originalResizeObserver;
49
+ });
18
50
 
19
51
  describe("useDialogSwipeInput", () => {
20
52
  const createMockContainer = (dimensions: { width: number; height: number }) => {
@@ -24,15 +56,6 @@ describe("useDialogSwipeInput", () => {
24
56
  return container;
25
57
  };
26
58
 
27
- beforeEach(() => {
28
- vi.useFakeTimers();
29
- });
30
-
31
- afterEach(() => {
32
- vi.useRealTimers();
33
- vi.clearAllMocks();
34
- });
35
-
36
59
  describe("initialization", () => {
37
60
  it("should return idle state initially", () => {
38
61
  const container = createMockContainer({ width: 400, height: 300 });
@@ -43,7 +66,7 @@ describe("useDialogSwipeInput", () => {
43
66
  containerRef,
44
67
  openDirection: "bottom",
45
68
  enabled: true,
46
- onSwipeDismiss: vi.fn(),
69
+ onSwipeDismiss: createCallTracker().fn,
47
70
  }),
48
71
  );
49
72
 
@@ -61,7 +84,7 @@ describe("useDialogSwipeInput", () => {
61
84
  containerRef,
62
85
  openDirection: "bottom",
63
86
  enabled: true,
64
- onSwipeDismiss: vi.fn(),
87
+ onSwipeDismiss: createCallTracker().fn,
65
88
  }),
66
89
  );
67
90
 
@@ -80,7 +103,7 @@ describe("useDialogSwipeInput", () => {
80
103
  containerRef,
81
104
  openDirection: "bottom",
82
105
  enabled: true,
83
- onSwipeDismiss: vi.fn(),
106
+ onSwipeDismiss: createCallTracker().fn,
84
107
  }),
85
108
  );
86
109
 
@@ -97,7 +120,7 @@ describe("useDialogSwipeInput", () => {
97
120
  containerRef,
98
121
  openDirection: "left",
99
122
  enabled: true,
100
- onSwipeDismiss: vi.fn(),
123
+ onSwipeDismiss: createCallTracker().fn,
101
124
  }),
102
125
  );
103
126
 
@@ -116,7 +139,7 @@ describe("useDialogSwipeInput", () => {
116
139
  containerRef,
117
140
  openDirection: "bottom",
118
141
  enabled: false,
119
- onSwipeDismiss: vi.fn(),
142
+ onSwipeDismiss: createCallTracker().fn,
120
143
  }),
121
144
  );
122
145
 
@@ -128,9 +151,7 @@ describe("useDialogSwipeInput", () => {
128
151
  });
129
152
 
130
153
  act(() => {
131
- result.current.containerProps.onPointerDown?.(
132
- pointerEvent as unknown as React.PointerEvent,
133
- );
154
+ result.current.containerProps.onPointerDown?.(asReactPointerEvent(pointerEvent));
134
155
  });
135
156
 
136
157
  expect(result.current.state.phase).toBe("idle");
@@ -147,7 +168,7 @@ describe("useDialogSwipeInput", () => {
147
168
  containerRef,
148
169
  openDirection: "bottom",
149
170
  enabled: true,
150
- onSwipeDismiss: vi.fn(),
171
+ onSwipeDismiss: createCallTracker().fn,
151
172
  }),
152
173
  );
153
174
 
@@ -17,6 +17,36 @@ import {
17
17
  import type { DialogOpenDirection } from "./dialogAnimationUtils.js";
18
18
  import { getAnimationAxis, getDirectionSign } from "./dialogAnimationUtils.js";
19
19
 
20
+ /**
21
+ * Get sign from displacement value.
22
+ */
23
+ function getSignFromDisplacement(value: number): -1 | 0 | 1 {
24
+ if (value > 0) {
25
+ return 1;
26
+ }
27
+ if (value < 0) {
28
+ return -1;
29
+ }
30
+ return 0;
31
+ }
32
+
33
+ type TrackingPoint = { timestamp: number } | null;
34
+
35
+ /**
36
+ * Compute velocity from tracking points.
37
+ */
38
+ function computeSwipeVelocity(
39
+ start: TrackingPoint,
40
+ current: TrackingPoint,
41
+ primaryValue: number,
42
+ ): number {
43
+ if (start === null || current === null) {
44
+ return 0;
45
+ }
46
+ const duration = Math.max(1, current.timestamp - start.timestamp);
47
+ return Math.abs(primaryValue) / duration;
48
+ }
49
+
20
50
  /**
21
51
  * Default dismiss threshold (30% of container size).
22
52
  */
@@ -77,7 +107,10 @@ function isScrollableElement(element: HTMLElement): boolean {
77
107
  (style.overflowY === "scroll" || style.overflowY === "auto") &&
78
108
  element.scrollHeight > element.clientHeight;
79
109
 
80
- return isScrollableX || isScrollableY;
110
+ if (isScrollableX) {
111
+ return true;
112
+ }
113
+ return isScrollableY;
81
114
  }
82
115
 
83
116
  /**
@@ -206,7 +239,7 @@ export function useDialogSwipeInput(
206
239
  if (containerSize <= 0) {
207
240
  return 0;
208
241
  }
209
- const sign = primaryDisplacement > 0 ? 1 : primaryDisplacement < 0 ? -1 : 0;
242
+ const sign = getSignFromDisplacement(primaryDisplacement);
210
243
  if (sign !== expectedSign) {
211
244
  return 0; // Wrong direction
212
245
  }
@@ -244,13 +277,11 @@ export function useDialogSwipeInput(
244
277
  if (containerSize > 0) {
245
278
  const finalDisplacement = lastDisplacementRef.current;
246
279
  const primaryValue = axis === "x" ? finalDisplacement.x : finalDisplacement.y;
247
- const sign = primaryValue > 0 ? 1 : primaryValue < 0 ? -1 : 0;
280
+ const sign = getSignFromDisplacement(primaryValue);
248
281
 
249
282
  if (sign === expectedSign) {
250
283
  const ratio = Math.abs(primaryValue) / containerSize;
251
- const velocity = tracking.start && tracking.current
252
- ? Math.abs(primaryValue) / Math.max(1, tracking.current.timestamp - tracking.start.timestamp)
253
- : 0;
284
+ const velocity = computeSwipeVelocity(tracking.start, tracking.current, primaryValue);
254
285
 
255
286
  if (ratio >= dismissThreshold || velocity >= VELOCITY_THRESHOLD) {
256
287
  onSwipeDismiss();
@@ -1,67 +1,94 @@
1
1
  /**
2
2
  * @file Tests for useDialogTransform hook
3
3
  */
4
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
5
4
  import { renderHook, act, waitFor } from "@testing-library/react";
6
5
  import { useDialogTransform } from "./useDialogTransform.js";
7
6
  import type { ContinuousOperationState } from "../../hooks/gesture/types.js";
8
7
  import { IDLE_CONTINUOUS_OPERATION_STATE } from "../../hooks/gesture/types.js";
9
8
 
10
9
  // Mock ResizeObserver
11
- const mockResizeObserver = vi.fn();
12
- vi.stubGlobal("ResizeObserver", class {
13
- constructor(callback: ResizeObserverCallback) {
14
- mockResizeObserver(callback);
15
- }
16
- observe = vi.fn();
17
- unobserve = vi.fn();
18
- disconnect = vi.fn();
19
- });
10
+ const createMockResizeObserver = () => {
11
+ const callbacks: ResizeObserverCallback[] = [];
12
+ return {
13
+ callbacks,
14
+ MockClass: class {
15
+ constructor(callback: ResizeObserverCallback) {
16
+ callbacks.push(callback);
17
+ }
18
+ observe(): void {
19
+ // no-op
20
+ }
21
+ unobserve(): void {
22
+ // no-op
23
+ }
24
+ disconnect(): void {
25
+ // no-op
26
+ }
27
+ },
28
+ };
29
+ };
30
+
31
+ const { MockClass: MockResizeObserver } = createMockResizeObserver();
32
+ globalThis.ResizeObserver = MockResizeObserver;
20
33
 
21
34
  describe("useDialogTransform", () => {
22
- let rafCallbacks: FrameRequestCallback[] = [];
23
- let rafId = 0;
35
+ const createRAFTracker = () => {
36
+ const callbacks: FrameRequestCallback[] = [];
37
+ const tracker = { callbacks, nextId: 0 };
38
+ return tracker;
39
+ };
24
40
 
25
- beforeEach(() => {
26
- rafCallbacks = [];
27
- rafId = 0;
41
+ const rafTracker = createRAFTracker();
42
+ const originalRAF = globalThis.requestAnimationFrame;
43
+ const originalCAF = globalThis.cancelAnimationFrame;
28
44
 
29
- vi.stubGlobal("requestAnimationFrame", (cb: FrameRequestCallback) => {
30
- rafCallbacks.push(cb);
31
- return ++rafId;
32
- });
33
- vi.stubGlobal("cancelAnimationFrame", (id: number) => {
45
+ beforeEach(() => {
46
+ rafTracker.callbacks.length = 0;
47
+ rafTracker.nextId = 0;
48
+
49
+ globalThis.requestAnimationFrame = (cb: FrameRequestCallback): number => {
50
+ rafTracker.callbacks.push(cb);
51
+ rafTracker.nextId += 1;
52
+ return rafTracker.nextId;
53
+ };
54
+ globalThis.cancelAnimationFrame = (): void => {
34
55
  // Mock cancel
35
- });
56
+ };
36
57
  });
37
58
 
38
59
  afterEach(() => {
39
- vi.unstubAllGlobals();
40
- vi.clearAllMocks();
60
+ globalThis.requestAnimationFrame = originalRAF;
61
+ globalThis.cancelAnimationFrame = originalCAF;
41
62
  });
42
63
 
43
64
  const runAnimationFrames = (count = 1, deltaMs = 16) => {
44
65
  const now = performance.now();
45
66
  for (let i = 0; i < count; i++) {
46
- const callbacks = [...rafCallbacks];
47
- rafCallbacks = [];
67
+ const callbacks = [...rafTracker.callbacks];
68
+ rafTracker.callbacks.length = 0;
48
69
  callbacks.forEach(cb => cb(now + deltaMs * (i + 1)));
49
70
  }
50
71
  };
51
72
 
52
73
  const createMockElement = (dimensions: { width: number; height: number }) => {
74
+ const setPropertyCalls: Array<{ prop: string; value: string }> = [];
75
+ // eslint-disable-next-line custom/no-as-outside-guard -- Required for DOM mock
53
76
  return {
54
77
  clientWidth: dimensions.width,
55
78
  clientHeight: dimensions.height,
56
79
  style: {
57
80
  transform: "",
58
- setProperty: vi.fn(),
81
+ setProperty: (prop: string, value: string): void => {
82
+ setPropertyCalls.push({ prop, value });
83
+ },
59
84
  viewTransitionName: "",
60
85
  },
86
+ _setPropertyCalls: setPropertyCalls,
61
87
  } as unknown as HTMLDivElement;
62
88
  };
63
89
 
64
90
  const createMockBackdrop = () => {
91
+ // eslint-disable-next-line custom/no-as-outside-guard -- Required for DOM mock
65
92
  return {
66
93
  style: {
67
94
  opacity: "",
@@ -140,7 +167,10 @@ describe("useDialogTransform", () => {
140
167
  const backdrop = createMockBackdrop();
141
168
  const elementRef = { current: element };
142
169
  const backdropRef = { current: backdrop };
143
- const onOpenComplete = vi.fn();
170
+ const onOpenCompleteCalls: unknown[] = [];
171
+ const onOpenComplete = (): void => {
172
+ onOpenCompleteCalls.push(undefined);
173
+ };
144
174
 
145
175
  const { result, rerender } = renderHook(
146
176
  ({ visible }) =>
@@ -170,7 +200,7 @@ describe("useDialogTransform", () => {
170
200
  expect(result.current.phase).toBe("open");
171
201
  });
172
202
 
173
- expect(onOpenComplete).toHaveBeenCalled();
203
+ expect(onOpenCompleteCalls.length).toBeGreaterThan(0);
174
204
  });
175
205
  });
176
206
 
@@ -218,7 +248,10 @@ describe("useDialogTransform", () => {
218
248
  const backdrop = createMockBackdrop();
219
249
  const elementRef = { current: element };
220
250
  const backdropRef = { current: backdrop };
221
- const onCloseComplete = vi.fn();
251
+ const onCloseCompleteCalls: unknown[] = [];
252
+ const onCloseComplete = (): void => {
253
+ onCloseCompleteCalls.push(undefined);
254
+ };
222
255
 
223
256
  const { result, rerender } = renderHook(
224
257
  ({ visible }) =>
@@ -260,7 +293,7 @@ describe("useDialogTransform", () => {
260
293
  expect(result.current.phase).toBe("closed");
261
294
  });
262
295
 
263
- expect(onCloseComplete).toHaveBeenCalled();
296
+ expect(onCloseCompleteCalls.length).toBeGreaterThan(0);
264
297
  });
265
298
  });
266
299