@wordpress/compose 8.7.2-next.v.202609031004.0 → 8.8.2-next.v.202609171837.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 (40) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +90 -90
  3. package/build/hooks/use-fixed-window-list/index.cjs.map +2 -2
  4. package/build/hooks/use-focus-outside/index.cjs +1 -0
  5. package/build/hooks/use-focus-outside/index.cjs.map +2 -2
  6. package/build/hooks/use-keyboard-shortcut/index.cjs.map +2 -2
  7. package/build/hooks/use-resize-observer/use-resize-observer.cjs +9 -0
  8. package/build/hooks/use-resize-observer/use-resize-observer.cjs.map +2 -2
  9. package/build-module/hooks/use-fixed-window-list/index.mjs.map +2 -2
  10. package/build-module/hooks/use-focus-outside/index.mjs +1 -0
  11. package/build-module/hooks/use-focus-outside/index.mjs.map +2 -2
  12. package/build-module/hooks/use-keyboard-shortcut/index.mjs.map +2 -2
  13. package/build-module/hooks/use-resize-observer/use-resize-observer.mjs +10 -1
  14. package/build-module/hooks/use-resize-observer/use-resize-observer.mjs.map +2 -2
  15. package/build-types/hooks/use-focus-outside/index.d.ts.map +1 -1
  16. package/build-types/hooks/use-resize-observer/use-resize-observer.d.ts.map +1 -1
  17. package/package.json +13 -13
  18. package/src/higher-order/pure/test/index.jsdom.test.jsx +1 -0
  19. package/src/higher-order/with-global-events/test/index.jsdom.test.jsx +18 -15
  20. package/src/higher-order/with-global-events/test/listener.jsdom.test.js +13 -4
  21. package/src/higher-order/with-instance-id/test/index.jsdom.test.jsx +1 -0
  22. package/src/higher-order/with-state/test/index.jsdom.test.jsx +1 -0
  23. package/src/hooks/use-copy-on-click/test/index.jsdom.test.tsx +18 -17
  24. package/src/hooks/use-copy-to-clipboard/test/index.jsdom.test.tsx +12 -11
  25. package/src/hooks/use-dialog/test/index.jsdom.test.tsx +14 -13
  26. package/src/hooks/use-disabled/test/index.jsdom.test.jsx +1 -0
  27. package/src/hooks/use-drop-zone/test/index.jsdom.test.jsx +1 -0
  28. package/src/hooks/use-fixed-window-list/index.ts +1 -1
  29. package/src/hooks/use-focus-outside/index.ts +3 -3
  30. package/src/hooks/use-focus-outside/test/index.jsdom.test.jsx +7 -8
  31. package/src/hooks/use-instance-id/test/index.jsdom.test.jsx +1 -0
  32. package/src/hooks/use-keyboard-shortcut/index.ts +3 -3
  33. package/src/hooks/use-media-query/test/{index.jsdom.test.jsx → index.browser.test.jsx} +23 -21
  34. package/src/hooks/use-merge-refs/test/index.jsdom.test.jsx +1 -0
  35. package/src/hooks/use-observable-value/test/index.jsdom.test.jsx +2 -1
  36. package/src/hooks/use-resize-observer/test/index.browser.test.ts +24 -0
  37. package/src/hooks/use-resize-observer/use-resize-observer.ts +13 -1
  38. package/src/hooks/use-state-with-history/test/index.jsdom.test.jsx +1 -0
  39. package/src/hooks/use-viewport-match/test/index.jsdom.test.jsx +2 -3
  40. package/src/utils/subscribe-delegated-listener/test/index.jsdom.test.js +17 -16
@@ -1,3 +1,4 @@
1
+ import { describe, expect, it, vi } from 'vitest';
1
2
  import { render, screen } from '@testing-library/react';
2
3
  import userEvent from '@testing-library/user-event';
3
4
  import { createPortal } from 'react-dom';
@@ -20,7 +21,7 @@ function Dialog( { onClose }: { onClose?: () => void } ) {
20
21
  describe( 'useDialog', () => {
21
22
  it( 'should call onClose when Escape is pressed', async () => {
22
23
  const user = userEvent.setup();
23
- const onClose = jest.fn();
24
+ const onClose = vi.fn();
24
25
 
25
26
  render( <Dialog onClose={ onClose } /> );
26
27
 
@@ -32,7 +33,7 @@ describe( 'useDialog', () => {
32
33
 
33
34
  it( 'should not call onClose when Escape is pressed if defaultPrevented', async () => {
34
35
  const user = userEvent.setup();
35
- const onClose = jest.fn();
36
+ const onClose = vi.fn();
36
37
 
37
38
  function DialogWithChild() {
38
39
  const [ ref, props ] = useDialog( {
@@ -69,8 +70,8 @@ describe( 'useDialog', () => {
69
70
 
70
71
  it( 'should stop Escape event from propagating to parent elements', async () => {
71
72
  const user = userEvent.setup();
72
- const onClose = jest.fn();
73
- const parentKeyDownHandler = jest.fn();
73
+ const onClose = vi.fn();
74
+ const parentKeyDownHandler = vi.fn();
74
75
 
75
76
  render(
76
77
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
@@ -88,7 +89,7 @@ describe( 'useDialog', () => {
88
89
 
89
90
  it( 'should let Escape propagate when there is no onClose handler', async () => {
90
91
  const user = userEvent.setup();
91
- const parentKeyDownHandler = jest.fn();
92
+ const parentKeyDownHandler = vi.fn();
92
93
 
93
94
  render(
94
95
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
@@ -105,8 +106,8 @@ describe( 'useDialog', () => {
105
106
 
106
107
  it( 'should not close when a portaled descendant handles Escape and stops propagation', async () => {
107
108
  const user = userEvent.setup();
108
- const onClose = jest.fn();
109
- const descendantHandled = jest.fn();
109
+ const onClose = vi.fn();
110
+ const descendantHandled = vi.fn();
110
111
 
111
112
  const portalTarget = document.createElement( 'div' );
112
113
  document.body.appendChild( portalTarget );
@@ -153,8 +154,8 @@ describe( 'useDialog', () => {
153
154
 
154
155
  it( 'should close only the innermost dialog when nested', async () => {
155
156
  const user = userEvent.setup();
156
- const outerOnClose = jest.fn();
157
- const innerOnClose = jest.fn();
157
+ const outerOnClose = vi.fn();
158
+ const innerOnClose = vi.fn();
158
159
 
159
160
  function NestedDialogs() {
160
161
  const [ outerRef, outerProps ] = useDialog( {
@@ -196,8 +197,8 @@ describe( 'useDialog', () => {
196
197
 
197
198
  it( 'should call the consumer-provided onKeyDown alongside close-on-Escape', async () => {
198
199
  const user = userEvent.setup();
199
- const onClose = jest.fn();
200
- const consumerOnKeyDown = jest.fn();
200
+ const onClose = vi.fn();
201
+ const consumerOnKeyDown = vi.fn();
201
202
 
202
203
  function DialogWithConsumerOnKeyDown() {
203
204
  const [ ref, props ] = useDialog( {
@@ -227,7 +228,7 @@ describe( 'useDialog', () => {
227
228
 
228
229
  it( 'should let the consumer-provided onKeyDown opt out of close-on-Escape via preventDefault', async () => {
229
230
  const user = userEvent.setup();
230
- const onClose = jest.fn();
231
+ const onClose = vi.fn();
231
232
 
232
233
  function DialogOptingOut() {
233
234
  const [ ref, props ] = useDialog( {
@@ -255,7 +256,7 @@ describe( 'useDialog', () => {
255
256
 
256
257
  it( 'should not call onClose for non-Escape keys', async () => {
257
258
  const user = userEvent.setup();
258
- const onClose = jest.fn();
259
+ const onClose = vi.fn();
259
260
 
260
261
  render( <Dialog onClose={ onClose } /> );
261
262
 
@@ -1,3 +1,4 @@
1
+ import { describe, expect, it } from 'vitest';
1
2
  import { render, screen, waitFor } from '@testing-library/react';
2
3
  import { forwardRef } from '@wordpress/element';
3
4
  import useDisabled from '../';
@@ -1,3 +1,4 @@
1
+ import { describe, expect, it } from 'vitest';
1
2
  import { render, screen } from '@testing-library/react';
2
3
  import { useState } from '@wordpress/element';
3
4
  import useDropZone from '../';
@@ -86,7 +86,7 @@ export default function useFixedWindowList(
86
86
  // Aim to keep opening list view fast, afterward we can optimize for scrolling.
87
87
  const overscan = initRender
88
88
  ? visibleItems
89
- : windowOverscan ?? visibleItems;
89
+ : ( windowOverscan ?? visibleItems );
90
90
  const firstViewableIndex = Math.floor(
91
91
  scrollContainer.scrollTop / itemHeight
92
92
  );
@@ -12,9 +12,7 @@ const INPUT_BUTTON_TYPES = [ 'button', 'submit' ];
12
12
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus
13
13
  */
14
14
  type FocusNormalizedButton =
15
- | HTMLButtonElement
16
- | HTMLLinkElement
17
- | HTMLInputElement;
15
+ HTMLButtonElement | HTMLLinkElement | HTMLInputElement;
18
16
 
19
17
  /**
20
18
  * Returns true if the given element is a button element subject to focus
@@ -148,6 +146,8 @@ export default function useFocusOutside(
148
146
  return;
149
147
  }
150
148
 
149
+ // Keep only the latest blur check so a subsequent focus event can cancel it.
150
+ clearTimeout( blurCheckTimeoutIdRef.current );
151
151
  blurCheckTimeoutIdRef.current = setTimeout( () => {
152
152
  // If document is not focused then focus should remain
153
153
  // inside the wrapped component and therefore we cancel
@@ -1,3 +1,4 @@
1
+ import { describe, expect, it, vi } from 'vitest';
1
2
  import { render, screen } from '@testing-library/react';
2
3
  import userEvent from '@testing-library/user-event';
3
4
  import useFocusOutside from '../';
@@ -19,7 +20,7 @@ const FocusOutsideComponent = ( { onFocusOutside: callback } ) => (
19
20
 
20
21
  describe( 'useFocusOutside', () => {
21
22
  it( 'should not call handler if focus shifts to element within component', async () => {
22
- const mockOnFocusOutside = jest.fn();
23
+ const mockOnFocusOutside = vi.fn();
23
24
  const user = userEvent.setup();
24
25
 
25
26
  render(
@@ -40,7 +41,7 @@ describe( 'useFocusOutside', () => {
40
41
  } );
41
42
 
42
43
  it( 'should not call handler if focus transitions via click to button', async () => {
43
- const mockOnFocusOutside = jest.fn();
44
+ const mockOnFocusOutside = vi.fn();
44
45
  const user = userEvent.setup();
45
46
 
46
47
  render(
@@ -57,7 +58,7 @@ describe( 'useFocusOutside', () => {
57
58
  } );
58
59
 
59
60
  it( 'should call handler if focus shifts to element outside component', async () => {
60
- const mockOnFocusOutside = jest.fn();
61
+ const mockOnFocusOutside = vi.fn();
61
62
  const user = userEvent.setup();
62
63
 
63
64
  render(
@@ -82,10 +83,10 @@ describe( 'useFocusOutside', () => {
82
83
  it( 'should not call handler if focus shifts outside the component when the document does not have focus', async () => {
83
84
  // Force document.hasFocus() to return false to simulate the window/document losing focus
84
85
  // See https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus.
85
- const mockedDocumentHasFocus = jest
86
+ const mockedDocumentHasFocus = vi
86
87
  .spyOn( document, 'hasFocus' )
87
88
  .mockImplementation( () => false );
88
- const mockOnFocusOutside = jest.fn();
89
+ const mockOnFocusOutside = vi.fn();
89
90
  const user = userEvent.setup();
90
91
 
91
92
  render(
@@ -114,9 +115,7 @@ describe( 'useFocusOutside', () => {
114
115
  const promise = new Promise( ( resolve ) => {
115
116
  resolvePromise = resolve;
116
117
  } );
117
- const mockOnFocusOutside = jest
118
- .fn()
119
- .mockImplementation( resolvePromise );
118
+ const mockOnFocusOutside = vi.fn().mockImplementation( resolvePromise );
120
119
  const user = userEvent.setup();
121
120
 
122
121
  const { unmount } = render(
@@ -1,3 +1,4 @@
1
+ import { describe, expect, it } from 'vitest';
1
2
  import { render } from '@testing-library/react';
2
3
  import useInstanceId from '../';
3
4
 
@@ -62,9 +62,9 @@ function useKeyboardShortcut(
62
62
  target && target.current
63
63
  ? target.current
64
64
  : // We were passing `document` here previously, so to successfully cast it to Element we must cast it first to `unknown`.
65
- // Not sure if this is a mistake but it was the behavior previous to the addition of types so we're just doing what's
66
- // necessary to maintain the existing behavior.
67
- ( document as unknown as Element )
65
+ // Not sure if this is a mistake but it was the behavior previous to the addition of types so we're just doing what's
66
+ // necessary to maintain the existing behavior.
67
+ ( document as unknown as Element )
68
68
  );
69
69
 
70
70
  const shortcutsArray = Array.isArray( shortcuts )
@@ -1,5 +1,7 @@
1
- import { act, render } from '@testing-library/react';
2
- import { matchMedia, setMedia } from 'mock-match-media';
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
+ import { page } from 'vitest/browser';
3
+ import { waitFor } from '@testing-library/react';
4
+ import { render } from 'vitest-browser-react';
3
5
  import useMediaQuery from '../';
4
6
 
5
7
  const TestComponent = ( { query } ) => {
@@ -8,23 +10,25 @@ const TestComponent = ( { query } ) => {
8
10
  };
9
11
 
10
12
  describe( 'useMediaQuery', () => {
13
+ let initialViewport;
14
+
11
15
  beforeAll( () => {
12
- window.matchMedia = matchMedia;
16
+ initialViewport = {
17
+ width: window.innerWidth,
18
+ height: window.innerHeight,
19
+ };
13
20
  } );
14
21
 
15
- beforeEach( () => {
16
- setMedia( {
17
- width: '960px',
18
- } );
22
+ beforeEach( async () => {
23
+ await page.viewport( 960, 768 );
19
24
  } );
20
25
 
21
- afterEach( () => {
22
- // Do not clean up, this will break our cache. Browsers also do not
23
- // reset media queries.
26
+ afterAll( async () => {
27
+ await page.viewport( initialViewport.width, initialViewport.height );
24
28
  } );
25
29
 
26
30
  it( 'should return true when the query matches', async () => {
27
- const { container } = render(
31
+ const { container } = await render(
28
32
  <TestComponent query="(min-width: 782px)" />
29
33
  );
30
34
 
@@ -32,23 +36,21 @@ describe( 'useMediaQuery', () => {
32
36
  } );
33
37
 
34
38
  it( 'should correctly update the value when the query evaluation matches', async () => {
35
- const { container } = render(
39
+ const { container } = await render(
36
40
  <TestComponent query="(min-width: 782px)" />
37
41
  );
38
42
 
39
43
  expect( container ).toHaveTextContent( 'useMediaQuery: true' );
40
44
 
41
- act( () => {
42
- setMedia( {
43
- width: '600px',
44
- } );
45
- } );
45
+ await page.viewport( 600, 768 );
46
46
 
47
- expect( container ).toHaveTextContent( 'useMediaQuery: false' );
47
+ await waitFor( () => {
48
+ expect( container ).toHaveTextContent( 'useMediaQuery: false' );
49
+ } );
48
50
  } );
49
51
 
50
52
  it( 'should return false when the query does not match', async () => {
51
- const { container } = render(
53
+ const { container } = await render(
52
54
  <TestComponent query="(max-width: 782px)" />
53
55
  );
54
56
 
@@ -56,12 +58,12 @@ describe( 'useMediaQuery', () => {
56
58
  } );
57
59
 
58
60
  it( 'should return false when a query is not passed', async () => {
59
- const { container, rerender } = render( <TestComponent /> );
61
+ const { container, rerender } = await render( <TestComponent /> );
60
62
 
61
63
  // Query will be case to a boolean to simplify the return type.
62
64
  expect( container ).toHaveTextContent( 'useMediaQuery: false' );
63
65
 
64
- rerender( <TestComponent query={ false } /> );
66
+ await rerender( <TestComponent query={ false } /> );
65
67
 
66
68
  expect( container ).toHaveTextContent( 'useMediaQuery: false' );
67
69
  } );
@@ -1,3 +1,4 @@
1
+ import { afterEach, describe, expect, it } from 'vitest';
1
2
  import { render, screen, fireEvent } from '@testing-library/react';
2
3
  import { useCallback, useState } from '@wordpress/element';
3
4
  import useMergeRefs from '../';
@@ -1,3 +1,4 @@
1
+ import { describe, expect, test, vi } from 'vitest';
1
2
  import { render, screen, act } from '@testing-library/react';
2
3
  import { observableMap } from '../../../utils/observable-map';
3
4
  import useObservableValue from '..';
@@ -7,7 +8,7 @@ describe( 'useObservableValue', () => {
7
8
  const map = observableMap();
8
9
  map.set( 'a', 1 );
9
10
 
10
- const MapUI = jest.fn( () => {
11
+ const MapUI = vi.fn( () => {
11
12
  const value = useObservableValue( map, 'a' );
12
13
  return <div>value is { value }</div>;
13
14
  } );
@@ -0,0 +1,24 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+ import { act } from '@testing-library/react';
3
+ import { renderHook } from 'vitest-browser-react';
4
+ import useResizeObserver from '..';
5
+
6
+ afterEach( () => {
7
+ vi.restoreAllMocks();
8
+ } );
9
+
10
+ describe( 'useResizeObserver', () => {
11
+ it( 'disconnects the observer on unmount', async () => {
12
+ const disconnect = vi.spyOn( ResizeObserver.prototype, 'disconnect' );
13
+ const { result, unmount } = await renderHook( () =>
14
+ useResizeObserver( vi.fn() )
15
+ );
16
+
17
+ act( () => result.current( document.createElement( 'div' ) ) );
18
+ expect( disconnect ).not.toHaveBeenCalled();
19
+
20
+ await unmount();
21
+
22
+ expect( disconnect ).toHaveBeenCalledOnce();
23
+ } );
24
+ } );
@@ -1,4 +1,4 @@
1
- import { useRef } from '@wordpress/element';
1
+ import { useEffect, useRef } from '@wordpress/element';
2
2
  import useEvent from '../use-event';
3
3
 
4
4
  // This is the current implementation of `useResizeObserver`.
@@ -14,6 +14,18 @@ export function useResizeObserver< T extends HTMLElement >(
14
14
 
15
15
  const observedElementRef = useRef< T | null >( null );
16
16
  const resizeObserverRef = useRef< ResizeObserver >( undefined );
17
+ useEffect( () => {
18
+ if ( observedElementRef.current ) {
19
+ resizeObserverRef.current?.observe(
20
+ observedElementRef.current,
21
+ resizeObserverOptions
22
+ );
23
+ }
24
+ return () => resizeObserverRef.current?.disconnect();
25
+ // This effect owns the observer lifecycle. The returned ref handles
26
+ // element and option changes without recreating the observer.
27
+ // eslint-disable-next-line react-hooks/exhaustive-deps
28
+ }, [] );
17
29
  return useEvent( ( element?: T | null ) => {
18
30
  if ( element === observedElementRef.current ) {
19
31
  return;
@@ -1,3 +1,4 @@
1
+ import { describe, expect, it } from 'vitest';
1
2
  import { screen, render, fireEvent } from '@testing-library/react';
2
3
  import useStateWithHistory from '../';
3
4
 
@@ -1,9 +1,8 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
1
2
  import { render } from '@testing-library/react';
2
3
  import useViewportMatch from '../';
3
- jest.mock( '../../use-media-query', () => {
4
- return jest.fn();
5
- } );
6
4
  import useMediaQueryMock from '../../use-media-query';
5
+ vi.mock( import( '../../use-media-query' ), () => ( { default: vi.fn() } ) );
7
6
 
8
7
  describe( 'useViewportMatch', () => {
9
8
  afterEach( () => {
@@ -1,3 +1,4 @@
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
1
2
  import subscribeDelegatedListener from '..';
2
3
 
3
4
  describe( 'subscribeDelegatedListener', () => {
@@ -27,14 +28,14 @@ describe( 'subscribeDelegatedListener', () => {
27
28
  }
28
29
 
29
30
  test( 'invokes element subscriber when event fires on that element', () => {
30
- const cb = jest.fn();
31
+ const cb = vi.fn();
31
32
  subscribeDelegatedListener( target, 'click', cb );
32
33
  fire( target );
33
34
  expect( cb ).toHaveBeenCalledTimes( 1 );
34
35
  } );
35
36
 
36
37
  test( 'invokes element subscriber when event fires on a descendant', () => {
37
- const cb = jest.fn();
38
+ const cb = vi.fn();
38
39
  const child = document.createElement( 'b' );
39
40
  target.appendChild( child );
40
41
  subscribeDelegatedListener( target, 'click', cb );
@@ -43,7 +44,7 @@ describe( 'subscribeDelegatedListener', () => {
43
44
  } );
44
45
 
45
46
  test( 'does not invoke element subscriber when event fires outside its subtree', () => {
46
- const cb = jest.fn();
47
+ const cb = vi.fn();
47
48
  const sibling = document.createElement( 'div' );
48
49
  document.body.appendChild( sibling );
49
50
  subscribeDelegatedListener( target, 'click', cb );
@@ -83,8 +84,8 @@ describe( 'subscribeDelegatedListener', () => {
83
84
  } );
84
85
 
85
86
  test( 'capture and bubble registries are independent', () => {
86
- const captureCb = jest.fn();
87
- const bubbleCb = jest.fn();
87
+ const captureCb = vi.fn();
88
+ const bubbleCb = vi.fn();
88
89
  subscribeDelegatedListener( target, 'click', captureCb, true );
89
90
  subscribeDelegatedListener( target, 'click', bubbleCb, false );
90
91
  fire( target );
@@ -93,15 +94,15 @@ describe( 'subscribeDelegatedListener', () => {
93
94
  } );
94
95
 
95
96
  test( 'document subscriber always fires for events in the document', () => {
96
- const cb = jest.fn();
97
+ const cb = vi.fn();
97
98
  subscribeDelegatedListener( document, 'click', cb );
98
99
  fire( target );
99
100
  expect( cb ).toHaveBeenCalledTimes( 1 );
100
101
  } );
101
102
 
102
103
  test( 'window subscriber fans out independently of element subscribers', () => {
103
- const winCb = jest.fn();
104
- const elCb = jest.fn();
104
+ const winCb = vi.fn();
105
+ const elCb = vi.fn();
105
106
  subscribeDelegatedListener( window, 'resize', winCb );
106
107
  subscribeDelegatedListener( target, 'resize', elCb );
107
108
  window.dispatchEvent( new Event( 'resize' ) );
@@ -111,8 +112,8 @@ describe( 'subscribeDelegatedListener', () => {
111
112
  } );
112
113
 
113
114
  test( 'multiple callbacks for the same element all fire', () => {
114
- const a = jest.fn();
115
- const b = jest.fn();
115
+ const a = vi.fn();
116
+ const b = vi.fn();
116
117
  subscribeDelegatedListener( target, 'click', a );
117
118
  subscribeDelegatedListener( target, 'click', b );
118
119
  fire( target );
@@ -121,7 +122,7 @@ describe( 'subscribeDelegatedListener', () => {
121
122
  } );
122
123
 
123
124
  test( 'unsubscribe stops further dispatch', () => {
124
- const cb = jest.fn();
125
+ const cb = vi.fn();
125
126
  const unsub = subscribeDelegatedListener( target, 'click', cb );
126
127
  fire( target );
127
128
  expect( cb ).toHaveBeenCalledTimes( 1 );
@@ -131,12 +132,12 @@ describe( 'subscribeDelegatedListener', () => {
131
132
  } );
132
133
 
133
134
  test( 'attaches one native listener per (root, eventType, phase) regardless of subscriber count', () => {
134
- const spy = jest.spyOn( document, 'addEventListener' );
135
+ const spy = vi.spyOn( document, 'addEventListener' );
135
136
  // First subscribe attaches the native listener; subsequent ones
136
137
  // for the same key share it.
137
- subscribeDelegatedListener( target, 'mousemove', jest.fn() );
138
- subscribeDelegatedListener( root, 'mousemove', jest.fn() );
139
- subscribeDelegatedListener( document, 'mousemove', jest.fn() );
138
+ subscribeDelegatedListener( target, 'mousemove', vi.fn() );
139
+ subscribeDelegatedListener( root, 'mousemove', vi.fn() );
140
+ subscribeDelegatedListener( document, 'mousemove', vi.fn() );
140
141
  const nativeMousemoves = spy.mock.calls.filter(
141
142
  ( [ type, , opts ] ) => type === 'mousemove' && ! opts // bubble-phase only
142
143
  ).length;
@@ -154,7 +155,7 @@ describe( 'subscribeDelegatedListener', () => {
154
155
  const iframeTarget = iframeDoc.createElement( 'span' );
155
156
  iframeDoc.body.appendChild( iframeTarget );
156
157
 
157
- const cb = jest.fn();
158
+ const cb = vi.fn();
158
159
  expect( () =>
159
160
  subscribeDelegatedListener( iframeTarget, 'click', cb )
160
161
  ).not.toThrow();