@trackunit/react-vite-test-setup 0.0.49-alpha-df0e8d549b3.0 → 0.0.50
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.cjs.js +73 -7
- package/index.esm.js +68 -3
- package/package.json +1 -1
- package/src/configureReliableAsyncUtils.d.ts +31 -0
- package/src/index.d.ts +1 -0
package/index.cjs.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var react = require('@testing-library/react');
|
|
4
|
+
var vitest = require('vitest');
|
|
3
5
|
require('vitest-canvas-mock');
|
|
4
6
|
var failOnConsole = require('vitest-fail-on-console');
|
|
5
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
var vitest = require('vitest');
|
|
7
8
|
require('@testing-library/jest-dom/vitest');
|
|
8
|
-
var react$1 = require('@testing-library/react');
|
|
9
9
|
var util = require('util');
|
|
10
|
-
var react = require('react');
|
|
10
|
+
var react$1 = require('react');
|
|
11
11
|
var reactI18next = require('react-i18next');
|
|
12
12
|
var polyfill = require('@js-temporal/polyfill');
|
|
13
13
|
var web = require('@react-spring/web');
|
|
@@ -32,6 +32,66 @@ function _interopNamespaceDefault(e) {
|
|
|
32
32
|
|
|
33
33
|
var reactI18next__namespace = /*#__PURE__*/_interopNamespaceDefault(reactI18next);
|
|
34
34
|
|
|
35
|
+
// Tracks the decorators we've installed so repeated `setupReactTestingLibrary()`
|
|
36
|
+
// calls don't stack the decorator on top of itself.
|
|
37
|
+
const reliableAsyncWrappers = new WeakSet();
|
|
38
|
+
/**
|
|
39
|
+
* Makes React Testing Library's async utilities (`waitFor`, `findBy*`,
|
|
40
|
+
* `waitForElementToBeRemoved`) poll in real wall-clock time even though
|
|
41
|
+
* `setupTimeAndLanguage` collapses the global `setTimeout`/`setInterval` to fire
|
|
42
|
+
* at 0ms.
|
|
43
|
+
*
|
|
44
|
+
* Every RTL async utility funnels through the configurable `asyncWrapper`:
|
|
45
|
+
* `@testing-library/react` installs an `act`-based one on import, and
|
|
46
|
+
* `@testing-library/dom`'s `waitFor` — plus `findBy*` and
|
|
47
|
+
* `waitForElementToBeRemoved`, which build on the module-internal `waitFor` —
|
|
48
|
+
* run their poll/timeout loop inside it. We decorate that single seam: for the
|
|
49
|
+
* duration of each async-utility call we temporarily restore the real timers
|
|
50
|
+
* (`globalThis.ORG_setTimeout`/`ORG_setInterval`), then put the collapsed 0ms
|
|
51
|
+
* timers back in a `finally`. Timers stay instant everywhere else, so debounces
|
|
52
|
+
* and animations still resolve immediately and the suite does not slow down.
|
|
53
|
+
*
|
|
54
|
+
* Guards:
|
|
55
|
+
* - Delegates unchanged when fake timers are active (`vi.isFakeTimers()`), so
|
|
56
|
+
* opt-in fake-timer tests keep RTL's fake-timer path.
|
|
57
|
+
* - No-ops the timer swap when `ORG_setTimeout` is absent (projects that don't
|
|
58
|
+
* collapse timers), leaving behaviour unchanged there.
|
|
59
|
+
* - Idempotent: repeated calls don't stack decorators.
|
|
60
|
+
*
|
|
61
|
+
* Must run after RTL's `act` wrapper is installed, i.e. from
|
|
62
|
+
* `setupReactTestingLibrary()`.
|
|
63
|
+
*/
|
|
64
|
+
const configureReliableAsyncUtils = () => {
|
|
65
|
+
const originalAsyncWrapper = react.getConfig().asyncWrapper;
|
|
66
|
+
if (reliableAsyncWrappers.has(originalAsyncWrapper)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const reliableAsyncWrapper = async (cb) => {
|
|
70
|
+
const orgSetTimeout = globalThis.ORG_setTimeout;
|
|
71
|
+
const orgSetInterval = globalThis.ORG_setInterval;
|
|
72
|
+
// Preserve fake-timer tests, and don't touch projects that never collapsed
|
|
73
|
+
// timers in the first place.
|
|
74
|
+
if (vitest.vi.isFakeTimers() || orgSetTimeout === undefined) {
|
|
75
|
+
return originalAsyncWrapper(cb);
|
|
76
|
+
}
|
|
77
|
+
const collapsedSetTimeout = global.setTimeout;
|
|
78
|
+
const collapsedSetInterval = global.setInterval;
|
|
79
|
+
global.setTimeout = orgSetTimeout;
|
|
80
|
+
if (orgSetInterval !== undefined) {
|
|
81
|
+
global.setInterval = orgSetInterval;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
return await originalAsyncWrapper(cb);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
global.setTimeout = collapsedSetTimeout;
|
|
88
|
+
global.setInterval = collapsedSetInterval;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
reliableAsyncWrappers.add(reliableAsyncWrapper);
|
|
92
|
+
react.configure({ asyncWrapper: reliableAsyncWrapper });
|
|
93
|
+
};
|
|
94
|
+
|
|
35
95
|
/**
|
|
36
96
|
* Sets up a mock implementation for HTML Canvas API in testing environments.
|
|
37
97
|
*
|
|
@@ -599,13 +659,13 @@ const setupTranslations = () => {
|
|
|
599
659
|
}
|
|
600
660
|
return Object.keys(reactNodes).map((key, i) => {
|
|
601
661
|
const child = reactNodes[key];
|
|
602
|
-
const isElement = react.isValidElement(child);
|
|
662
|
+
const isElement = react$1.isValidElement(child);
|
|
603
663
|
if (typeof child === "string") {
|
|
604
664
|
return child;
|
|
605
665
|
}
|
|
606
666
|
if (hasChildren(child)) {
|
|
607
667
|
const inner = renderNodes(getChildren(child));
|
|
608
|
-
return react.cloneElement(child, { ...child.props, key: i }, inner);
|
|
668
|
+
return react$1.cloneElement(child, { ...child.props, key: i }, inner);
|
|
609
669
|
}
|
|
610
670
|
if (typeof child === "object" && !isElement) {
|
|
611
671
|
return Object.keys(child).reduce((str, childKey) => `${str}${child[childKey]}`, "");
|
|
@@ -741,7 +801,7 @@ const installPostMessagePolyfill = () => {
|
|
|
741
801
|
* @returns {Promise<void>} - Returns a promise that resolves after the wait time.
|
|
742
802
|
*/
|
|
743
803
|
const flushPromisesInAct = (waitTimeInMS = 0) => {
|
|
744
|
-
return react
|
|
804
|
+
return react.act(() => {
|
|
745
805
|
return new Promise(resolve => {
|
|
746
806
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
747
807
|
if (global.ORG_setTimeout) {
|
|
@@ -764,7 +824,7 @@ vitest.afterEach(async () => {
|
|
|
764
824
|
// `vi.useRealTimers()` is a no-op when no fake timers are installed.
|
|
765
825
|
vitest.vi.useRealTimers();
|
|
766
826
|
vitest.vi.clearAllMocks();
|
|
767
|
-
react
|
|
827
|
+
react.cleanup();
|
|
768
828
|
await flushPromisesInAct();
|
|
769
829
|
});
|
|
770
830
|
const setupResponseForTanstackRouter = () => {
|
|
@@ -973,6 +1033,11 @@ const setupReactTestingLibrary = () => {
|
|
|
973
1033
|
setupResizeObserver();
|
|
974
1034
|
setupIntersectionObserver();
|
|
975
1035
|
installPostMessagePolyfill();
|
|
1036
|
+
// Make RTL's async utilities (waitFor/findBy*/waitForElementToBeRemoved) wait
|
|
1037
|
+
// in real wall-clock time despite the 0ms timer collapse from
|
|
1038
|
+
// `setupTimeAndLanguage`. Runs last so RTL's `act` asyncWrapper is already
|
|
1039
|
+
// installed before we decorate it. See `configureReliableAsyncUtils`.
|
|
1040
|
+
configureReliableAsyncUtils();
|
|
976
1041
|
};
|
|
977
1042
|
|
|
978
1043
|
/**
|
|
@@ -1292,6 +1357,7 @@ const setupTanstackReactRouter = () => {
|
|
|
1292
1357
|
}));
|
|
1293
1358
|
};
|
|
1294
1359
|
|
|
1360
|
+
exports.configureReliableAsyncUtils = configureReliableAsyncUtils;
|
|
1295
1361
|
exports.createMockClickEvent = createMockClickEvent;
|
|
1296
1362
|
exports.createMockMapboxMap = createMockMapboxMap;
|
|
1297
1363
|
exports.setupAllMocks = setupAllMocks;
|
package/index.esm.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { getConfig, configure, cleanup, act } from '@testing-library/react';
|
|
2
|
+
import { vi, beforeEach, afterEach } from 'vitest';
|
|
1
3
|
import 'vitest-canvas-mock';
|
|
2
4
|
import failOnConsole from 'vitest-fail-on-console';
|
|
3
5
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import { vi, beforeEach, afterEach } from 'vitest';
|
|
5
6
|
import '@testing-library/jest-dom/vitest';
|
|
6
|
-
import { cleanup, act } from '@testing-library/react';
|
|
7
7
|
import { TextEncoder, TextDecoder } from 'util';
|
|
8
8
|
import { isValidElement, cloneElement } from 'react';
|
|
9
9
|
import * as reactI18next from 'react-i18next';
|
|
@@ -11,6 +11,66 @@ import { Temporal } from '@js-temporal/polyfill';
|
|
|
11
11
|
import { Globals } from '@react-spring/web';
|
|
12
12
|
import { WritableStream, TransformStream } from 'web-streams-polyfill';
|
|
13
13
|
|
|
14
|
+
// Tracks the decorators we've installed so repeated `setupReactTestingLibrary()`
|
|
15
|
+
// calls don't stack the decorator on top of itself.
|
|
16
|
+
const reliableAsyncWrappers = new WeakSet();
|
|
17
|
+
/**
|
|
18
|
+
* Makes React Testing Library's async utilities (`waitFor`, `findBy*`,
|
|
19
|
+
* `waitForElementToBeRemoved`) poll in real wall-clock time even though
|
|
20
|
+
* `setupTimeAndLanguage` collapses the global `setTimeout`/`setInterval` to fire
|
|
21
|
+
* at 0ms.
|
|
22
|
+
*
|
|
23
|
+
* Every RTL async utility funnels through the configurable `asyncWrapper`:
|
|
24
|
+
* `@testing-library/react` installs an `act`-based one on import, and
|
|
25
|
+
* `@testing-library/dom`'s `waitFor` — plus `findBy*` and
|
|
26
|
+
* `waitForElementToBeRemoved`, which build on the module-internal `waitFor` —
|
|
27
|
+
* run their poll/timeout loop inside it. We decorate that single seam: for the
|
|
28
|
+
* duration of each async-utility call we temporarily restore the real timers
|
|
29
|
+
* (`globalThis.ORG_setTimeout`/`ORG_setInterval`), then put the collapsed 0ms
|
|
30
|
+
* timers back in a `finally`. Timers stay instant everywhere else, so debounces
|
|
31
|
+
* and animations still resolve immediately and the suite does not slow down.
|
|
32
|
+
*
|
|
33
|
+
* Guards:
|
|
34
|
+
* - Delegates unchanged when fake timers are active (`vi.isFakeTimers()`), so
|
|
35
|
+
* opt-in fake-timer tests keep RTL's fake-timer path.
|
|
36
|
+
* - No-ops the timer swap when `ORG_setTimeout` is absent (projects that don't
|
|
37
|
+
* collapse timers), leaving behaviour unchanged there.
|
|
38
|
+
* - Idempotent: repeated calls don't stack decorators.
|
|
39
|
+
*
|
|
40
|
+
* Must run after RTL's `act` wrapper is installed, i.e. from
|
|
41
|
+
* `setupReactTestingLibrary()`.
|
|
42
|
+
*/
|
|
43
|
+
const configureReliableAsyncUtils = () => {
|
|
44
|
+
const originalAsyncWrapper = getConfig().asyncWrapper;
|
|
45
|
+
if (reliableAsyncWrappers.has(originalAsyncWrapper)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const reliableAsyncWrapper = async (cb) => {
|
|
49
|
+
const orgSetTimeout = globalThis.ORG_setTimeout;
|
|
50
|
+
const orgSetInterval = globalThis.ORG_setInterval;
|
|
51
|
+
// Preserve fake-timer tests, and don't touch projects that never collapsed
|
|
52
|
+
// timers in the first place.
|
|
53
|
+
if (vi.isFakeTimers() || orgSetTimeout === undefined) {
|
|
54
|
+
return originalAsyncWrapper(cb);
|
|
55
|
+
}
|
|
56
|
+
const collapsedSetTimeout = global.setTimeout;
|
|
57
|
+
const collapsedSetInterval = global.setInterval;
|
|
58
|
+
global.setTimeout = orgSetTimeout;
|
|
59
|
+
if (orgSetInterval !== undefined) {
|
|
60
|
+
global.setInterval = orgSetInterval;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
return await originalAsyncWrapper(cb);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
global.setTimeout = collapsedSetTimeout;
|
|
67
|
+
global.setInterval = collapsedSetInterval;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
reliableAsyncWrappers.add(reliableAsyncWrapper);
|
|
71
|
+
configure({ asyncWrapper: reliableAsyncWrapper });
|
|
72
|
+
};
|
|
73
|
+
|
|
14
74
|
/**
|
|
15
75
|
* Sets up a mock implementation for HTML Canvas API in testing environments.
|
|
16
76
|
*
|
|
@@ -952,6 +1012,11 @@ const setupReactTestingLibrary = () => {
|
|
|
952
1012
|
setupResizeObserver();
|
|
953
1013
|
setupIntersectionObserver();
|
|
954
1014
|
installPostMessagePolyfill();
|
|
1015
|
+
// Make RTL's async utilities (waitFor/findBy*/waitForElementToBeRemoved) wait
|
|
1016
|
+
// in real wall-clock time despite the 0ms timer collapse from
|
|
1017
|
+
// `setupTimeAndLanguage`. Runs last so RTL's `act` asyncWrapper is already
|
|
1018
|
+
// installed before we decorate it. See `configureReliableAsyncUtils`.
|
|
1019
|
+
configureReliableAsyncUtils();
|
|
955
1020
|
};
|
|
956
1021
|
|
|
957
1022
|
/**
|
|
@@ -1271,4 +1336,4 @@ const setupTanstackReactRouter = () => {
|
|
|
1271
1336
|
}));
|
|
1272
1337
|
};
|
|
1273
1338
|
|
|
1274
|
-
export { createMockClickEvent, createMockMapboxMap, setupAllMocks, setupBasicMocks, setupCanvasMock, setupDefaultMocks, setupFailOnConsole, setupGoogleMaps, setupHelmetMock, setupIntersectionObserver, setupMapbox, setupMatchMediaMock, setupReactTestingLibrary, setupReactVirtualizedAutoSizer, setupResizeObserver, setupTanstackReactRouter, setupTanstackReactVirtual, setupTimeAndLanguage, setupTimeZone, setupTranslations, setupWebStreams };
|
|
1339
|
+
export { configureReliableAsyncUtils, createMockClickEvent, createMockMapboxMap, setupAllMocks, setupBasicMocks, setupCanvasMock, setupDefaultMocks, setupFailOnConsole, setupGoogleMaps, setupHelmetMock, setupIntersectionObserver, setupMapbox, setupMatchMediaMock, setupReactTestingLibrary, setupReactVirtualizedAutoSizer, setupResizeObserver, setupTanstackReactRouter, setupTanstackReactVirtual, setupTimeAndLanguage, setupTimeZone, setupTranslations, setupWebStreams };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-vite-test-setup",
|
|
3
3
|
"description": "Test setup utilities for React applications",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.50",
|
|
5
5
|
"repository": "https://github.com/Trackunit/manager",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
7
7
|
"engines": {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
var ORG_setTimeout: typeof setTimeout | undefined;
|
|
3
|
+
var ORG_setInterval: typeof setInterval | undefined;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Makes React Testing Library's async utilities (`waitFor`, `findBy*`,
|
|
7
|
+
* `waitForElementToBeRemoved`) poll in real wall-clock time even though
|
|
8
|
+
* `setupTimeAndLanguage` collapses the global `setTimeout`/`setInterval` to fire
|
|
9
|
+
* at 0ms.
|
|
10
|
+
*
|
|
11
|
+
* Every RTL async utility funnels through the configurable `asyncWrapper`:
|
|
12
|
+
* `@testing-library/react` installs an `act`-based one on import, and
|
|
13
|
+
* `@testing-library/dom`'s `waitFor` — plus `findBy*` and
|
|
14
|
+
* `waitForElementToBeRemoved`, which build on the module-internal `waitFor` —
|
|
15
|
+
* run their poll/timeout loop inside it. We decorate that single seam: for the
|
|
16
|
+
* duration of each async-utility call we temporarily restore the real timers
|
|
17
|
+
* (`globalThis.ORG_setTimeout`/`ORG_setInterval`), then put the collapsed 0ms
|
|
18
|
+
* timers back in a `finally`. Timers stay instant everywhere else, so debounces
|
|
19
|
+
* and animations still resolve immediately and the suite does not slow down.
|
|
20
|
+
*
|
|
21
|
+
* Guards:
|
|
22
|
+
* - Delegates unchanged when fake timers are active (`vi.isFakeTimers()`), so
|
|
23
|
+
* opt-in fake-timer tests keep RTL's fake-timer path.
|
|
24
|
+
* - No-ops the timer swap when `ORG_setTimeout` is absent (projects that don't
|
|
25
|
+
* collapse timers), leaving behaviour unchanged there.
|
|
26
|
+
* - Idempotent: repeated calls don't stack decorators.
|
|
27
|
+
*
|
|
28
|
+
* Must run after RTL's `act` wrapper is installed, i.e. from
|
|
29
|
+
* `setupReactTestingLibrary()`.
|
|
30
|
+
*/
|
|
31
|
+
export declare const configureReliableAsyncUtils: () => void;
|
package/src/index.d.ts
CHANGED