@mui/internal-test-utils 2.0.15 → 2.0.16

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 (212) hide show
  1. package/{src/chai.types.ts → chai.types.d.ts} +7 -40
  2. package/chai.types.js +5 -0
  3. package/chaiPlugin.d.ts +4 -0
  4. package/chaiPlugin.js +287 -0
  5. package/{build/components.d.ts → components.d.ts} +18 -19
  6. package/components.js +64 -0
  7. package/createDOM.d.ts +2 -0
  8. package/{src/createDOM.js → createDOM.js} +17 -35
  9. package/createDescribe.d.ts +7 -0
  10. package/createDescribe.js +26 -0
  11. package/createRenderer.d.ts +214 -0
  12. package/createRenderer.js +428 -0
  13. package/createRenderer.test.d.ts +1 -0
  14. package/describeConformance.d.ts +200 -0
  15. package/describeConformance.js +1038 -0
  16. package/env.d.ts +1 -0
  17. package/env.js +11 -0
  18. package/esm/chai.types.d.ts +74 -0
  19. package/esm/chai.types.js +3 -0
  20. package/esm/chaiPlugin.d.ts +4 -0
  21. package/esm/chaiPlugin.js +281 -0
  22. package/esm/components.d.ts +35 -0
  23. package/esm/components.js +56 -0
  24. package/esm/createDOM.d.ts +2 -0
  25. package/esm/createDOM.js +47 -0
  26. package/esm/createDescribe.d.ts +7 -0
  27. package/esm/createDescribe.js +19 -0
  28. package/esm/createRenderer.d.ts +214 -0
  29. package/esm/createRenderer.js +390 -0
  30. package/esm/createRenderer.test.d.ts +1 -0
  31. package/esm/describeConformance.d.ts +200 -0
  32. package/esm/describeConformance.js +1024 -0
  33. package/esm/env.d.ts +1 -0
  34. package/esm/env.js +5 -0
  35. package/{build → esm}/fireDiscreteEvent.d.ts +1 -2
  36. package/{src/fireDiscreteEvent.ts → esm/fireDiscreteEvent.js} +10 -18
  37. package/esm/flushMicrotasks.d.ts +1 -0
  38. package/{src/flushMicrotasks.ts → esm/flushMicrotasks.js} +2 -3
  39. package/{build → esm}/focusVisible.d.ts +1 -2
  40. package/{src/focusVisible.ts → esm/focusVisible.js} +10 -9
  41. package/esm/index.d.ts +18 -0
  42. package/esm/index.js +27 -0
  43. package/esm/init.d.ts +1 -0
  44. package/{src → esm}/init.js +4 -2
  45. package/esm/initMatchers.d.ts +1 -0
  46. package/esm/initMatchers.js +6 -0
  47. package/esm/initMatchers.test.d.ts +1 -0
  48. package/esm/initPlaywrightMatchers.d.ts +24 -0
  49. package/esm/initPlaywrightMatchers.js +40 -0
  50. package/esm/package.json +1 -0
  51. package/esm/reactMajor.d.ts +2 -0
  52. package/esm/reactMajor.js +2 -0
  53. package/esm/setup.d.ts +1 -0
  54. package/{src → esm}/setup.js +2 -4
  55. package/esm/setupVitest.d.ts +1 -0
  56. package/esm/setupVitest.js +28 -0
  57. package/esm/setupVitestBrowser.d.ts +1 -0
  58. package/esm/setupVitestBrowser.js +30 -0
  59. package/fireDiscreteEvent.d.ts +6 -0
  60. package/fireDiscreteEvent.js +79 -0
  61. package/flushMicrotasks.d.ts +1 -0
  62. package/flushMicrotasks.js +10 -0
  63. package/focusVisible.d.ts +7 -0
  64. package/focusVisible.js +44 -0
  65. package/index.d.ts +18 -0
  66. package/index.js +139 -0
  67. package/init.d.ts +1 -0
  68. package/init.js +15 -0
  69. package/initMatchers.d.ts +1 -0
  70. package/initMatchers.js +10 -0
  71. package/initMatchers.test.d.ts +1 -0
  72. package/initPlaywrightMatchers.d.ts +24 -0
  73. package/initPlaywrightMatchers.js +42 -0
  74. package/package.json +89 -46
  75. package/reactMajor.d.ts +2 -0
  76. package/reactMajor.js +9 -0
  77. package/setup.d.ts +1 -0
  78. package/setup.js +10 -0
  79. package/setupVitest.d.ts +1 -0
  80. package/setupVitest.js +32 -0
  81. package/setupVitestBrowser.d.ts +1 -0
  82. package/setupVitestBrowser.js +34 -0
  83. package/build/.tsbuildinfo +0 -1
  84. package/build/KarmaReporterReactProfiler.d.ts +0 -51
  85. package/build/KarmaReporterReactProfiler.d.ts.map +0 -1
  86. package/build/KarmaReporterReactProfiler.js +0 -66
  87. package/build/KarmaReporterReactProfiler.js.map +0 -1
  88. package/build/chai.types.d.ts +0 -75
  89. package/build/chai.types.d.ts.map +0 -1
  90. package/build/chai.types.js +0 -3
  91. package/build/chai.types.js.map +0 -1
  92. package/build/chaiPlugin.d.ts +0 -5
  93. package/build/chaiPlugin.d.ts.map +0 -1
  94. package/build/chaiPlugin.js +0 -416
  95. package/build/chaiPlugin.js.map +0 -1
  96. package/build/components.d.ts.map +0 -1
  97. package/build/components.js +0 -88
  98. package/build/components.js.map +0 -1
  99. package/build/createDOM.d.ts +0 -3
  100. package/build/createDOM.d.ts.map +0 -1
  101. package/build/createDOM.js +0 -60
  102. package/build/createDOM.js.map +0 -1
  103. package/build/createDescribe.d.ts +0 -8
  104. package/build/createDescribe.d.ts.map +0 -1
  105. package/build/createDescribe.js +0 -22
  106. package/build/createDescribe.js.map +0 -1
  107. package/build/createRenderer.d.ts +0 -215
  108. package/build/createRenderer.d.ts.map +0 -1
  109. package/build/createRenderer.js +0 -564
  110. package/build/createRenderer.js.map +0 -1
  111. package/build/createRenderer.test.d.ts +0 -2
  112. package/build/createRenderer.test.d.ts.map +0 -1
  113. package/build/createRenderer.test.js +0 -58
  114. package/build/createRenderer.test.js.map +0 -1
  115. package/build/describeConformance.d.ts +0 -201
  116. package/build/describeConformance.d.ts.map +0 -1
  117. package/build/describeConformance.js +0 -859
  118. package/build/describeConformance.js.map +0 -1
  119. package/build/describeSkipIf.d.ts +0 -4
  120. package/build/describeSkipIf.d.ts.map +0 -1
  121. package/build/describeSkipIf.js +0 -10
  122. package/build/describeSkipIf.js.map +0 -1
  123. package/build/fireDiscreteEvent.d.ts.map +0 -1
  124. package/build/fireDiscreteEvent.js +0 -77
  125. package/build/fireDiscreteEvent.js.map +0 -1
  126. package/build/flushMicrotasks.d.ts +0 -2
  127. package/build/flushMicrotasks.d.ts.map +0 -1
  128. package/build/flushMicrotasks.js +0 -8
  129. package/build/flushMicrotasks.js.map +0 -1
  130. package/build/focusVisible.d.ts.map +0 -1
  131. package/build/focusVisible.js +0 -38
  132. package/build/focusVisible.js.map +0 -1
  133. package/build/index.d.ts +0 -18
  134. package/build/index.d.ts.map +0 -1
  135. package/build/index.js +0 -68
  136. package/build/index.js.map +0 -1
  137. package/build/init.d.ts +0 -2
  138. package/build/init.d.ts.map +0 -1
  139. package/build/init.js +0 -46
  140. package/build/init.js.map +0 -1
  141. package/build/initMatchers.d.ts +0 -2
  142. package/build/initMatchers.d.ts.map +0 -1
  143. package/build/initMatchers.js +0 -45
  144. package/build/initMatchers.js.map +0 -1
  145. package/build/initMatchers.test.d.ts +0 -2
  146. package/build/initMatchers.test.d.ts.map +0 -1
  147. package/build/initMatchers.test.js +0 -101
  148. package/build/initMatchers.test.js.map +0 -1
  149. package/build/initPlaywrightMatchers.d.ts +0 -25
  150. package/build/initPlaywrightMatchers.d.ts.map +0 -1
  151. package/build/initPlaywrightMatchers.js +0 -73
  152. package/build/initPlaywrightMatchers.js.map +0 -1
  153. package/build/mochaHooks.d.ts +0 -24
  154. package/build/mochaHooks.d.ts.map +0 -1
  155. package/build/mochaHooks.js +0 -165
  156. package/build/mochaHooks.js.map +0 -1
  157. package/build/mochaHooks.test.d.ts +0 -2
  158. package/build/mochaHooks.test.d.ts.map +0 -1
  159. package/build/mochaHooks.test.js +0 -128
  160. package/build/mochaHooks.test.js.map +0 -1
  161. package/build/reactMajor.d.ts +0 -3
  162. package/build/reactMajor.d.ts.map +0 -1
  163. package/build/reactMajor.js +0 -38
  164. package/build/reactMajor.js.map +0 -1
  165. package/build/setup.d.ts +0 -2
  166. package/build/setup.d.ts.map +0 -1
  167. package/build/setup.js +0 -10
  168. package/build/setup.js.map +0 -1
  169. package/build/setupBabel.d.ts +0 -2
  170. package/build/setupBabel.d.ts.map +0 -1
  171. package/build/setupBabel.js +0 -5
  172. package/build/setupBabel.js.map +0 -1
  173. package/build/setupBabelPlaywright.d.ts +0 -2
  174. package/build/setupBabelPlaywright.d.ts.map +0 -1
  175. package/build/setupBabelPlaywright.js +0 -14
  176. package/build/setupBabelPlaywright.js.map +0 -1
  177. package/build/setupJSDOM.d.ts +0 -7
  178. package/build/setupJSDOM.d.ts.map +0 -1
  179. package/build/setupJSDOM.js +0 -17
  180. package/build/setupJSDOM.js.map +0 -1
  181. package/build/setupKarma.d.ts +0 -2
  182. package/build/setupKarma.d.ts.map +0 -1
  183. package/build/setupKarma.js +0 -56
  184. package/build/setupKarma.js.map +0 -1
  185. package/build/setupVitest.d.ts +0 -2
  186. package/build/setupVitest.d.ts.map +0 -1
  187. package/build/setupVitest.js +0 -131
  188. package/build/setupVitest.js.map +0 -1
  189. package/src/KarmaReporterReactProfiler.js +0 -82
  190. package/src/chai-augmentation.d.ts +0 -8
  191. package/src/chaiPlugin.ts +0 -515
  192. package/src/components.tsx +0 -61
  193. package/src/createDOM.d.ts +0 -9
  194. package/src/createDescribe.ts +0 -31
  195. package/src/createRenderer.test.js +0 -31
  196. package/src/createRenderer.tsx +0 -808
  197. package/src/describeConformance.tsx +0 -1257
  198. package/src/describeSkipIf.tsx +0 -11
  199. package/src/index.ts +0 -25
  200. package/src/initMatchers.test.js +0 -124
  201. package/src/initMatchers.ts +0 -7
  202. package/src/initPlaywrightMatchers.ts +0 -101
  203. package/src/mochaHooks.js +0 -200
  204. package/src/mochaHooks.test.js +0 -116
  205. package/src/reactMajor.ts +0 -3
  206. package/src/setupBabel.js +0 -3
  207. package/src/setupBabelPlaywright.js +0 -13
  208. package/src/setupJSDOM.js +0 -20
  209. package/src/setupKarma.js +0 -65
  210. package/src/setupVitest.ts +0 -117
  211. package/tsconfig.build.json +0 -16
  212. package/tsconfig.json +0 -17
@@ -1,11 +0,0 @@
1
- import type { PendingSuiteFunction } from 'mocha';
2
-
3
- // Shim for vitest describe.skipIf to be able to run mocha and vitest side-by-side
4
- // TODO: Remove after migration to vitest is complete
5
- const describeSkipIf: (condition: boolean) => PendingSuiteFunction =
6
- (describe as any).skipIf ??
7
- function describeSkipIf(condition: boolean) {
8
- return condition ? describe.skip : describe;
9
- };
10
-
11
- export default describeSkipIf;
package/src/index.ts DELETED
@@ -1,25 +0,0 @@
1
- import * as React from 'react';
2
-
3
- export * from './components';
4
- export { default as describeConformance } from './describeConformance';
5
- export * from './describeConformance';
6
- export { default as createDescribe } from './createDescribe';
7
- export * from './createRenderer';
8
- export {
9
- default as focusVisible,
10
- simulatePointerDevice,
11
- simulateKeyboardDevice,
12
- programmaticFocusTriggersFocusVisible,
13
- } from './focusVisible';
14
- export {} from './initMatchers';
15
- export * as fireDiscreteEvent from './fireDiscreteEvent';
16
- export { default as flushMicrotasks } from './flushMicrotasks';
17
- export { default as reactMajor } from './reactMajor';
18
-
19
- /**
20
- * Set to true if console logs during [lifecycles that are invoked twice in `React.StrictMode`](https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects) are suppressed.
21
- * Useful for asserting on `console.warn` or `console.error` via `toErrorDev()`.
22
- * TODO: Refactor to use reactMajor when fixing the React 17 cron test.
23
- * https://github.com/mui/material-ui/issues/43153
24
- */
25
- export const strictModeDoubleLoggingSuppressed = React.version.startsWith('17');
@@ -1,124 +0,0 @@
1
- import { expect } from 'chai';
2
- import { createSandbox } from 'sinon';
3
-
4
- describe('custom matchers', () => {
5
- const consoleSandbox = createSandbox();
6
-
7
- beforeEach(() => {
8
- // otherwise our global setup throws on unexpected calls in afterEach
9
- consoleSandbox.stub(console, 'warn');
10
- consoleSandbox.stub(console, 'error');
11
- });
12
-
13
- afterEach(() => {
14
- consoleSandbox.restore();
15
- });
16
-
17
- describe('toErrorDev()', () => {
18
- it('passes if the message is exactly the same', () => {
19
- expect(() => console.error('expected message')).toErrorDev('expected message');
20
- });
21
-
22
- it('passes if the message is a subset', () => {
23
- expect(() => console.error('expected message')).toErrorDev('pected messa');
24
- });
25
-
26
- it('passes if multiple messages are expected', () => {
27
- expect(() => {
28
- console.error('expected message');
29
- console.error('another message');
30
- }).toErrorDev(['expected message', 'another message']);
31
- });
32
-
33
- it("fails if an expected console.error call wasn't recorded with a useful stacktrace", () => {
34
- let caughtError;
35
- try {
36
- console.error('expected message');
37
- expect(() => {}).toErrorDev('expected message');
38
- } catch (error) {
39
- caughtError = error;
40
- }
41
-
42
- expect(caughtError).to.have.property('stack');
43
- expect(caughtError.stack).to.include(
44
- 'Could not match the following console.error calls. ' +
45
- "Make sure previous actions didn't call console.error by wrapping them in expect(() => {}).not.toErrorDev(): \n\n" +
46
- ' - "expected message"\n',
47
- );
48
- // check that the top stackframe points to this test
49
- // if this test is moved to another file the next assertion fails
50
- expect(caughtError.stack).to.match(
51
- /- "expected message"\s+at .*\/initMatchers\.test\.js:\d+:\d+/,
52
- );
53
- });
54
-
55
- it('is case sensitive', () => {
56
- let caughtError;
57
- try {
58
- expect(() => console.error('expected Message')).toErrorDev('expected message');
59
- } catch (error) {
60
- caughtError = error;
61
- }
62
-
63
- expect(caughtError).to.have.property('stack');
64
- expect(caughtError.stack).to.include(
65
- 'Recorded unexpected console.error calls: \n\n' +
66
- ' - Expected #1 "expected message" to be included in \n' +
67
- '"expected Message"\n',
68
- );
69
- // check that the top stackframe points to this test
70
- // if this test is moved to another file the next assertion fails
71
- expect(caughtError.stack).to.match(
72
- /"expected Message"\s+at .*\/initMatchers\.test\.js:\d+:\d+/,
73
- );
74
- });
75
-
76
- it('fails if the order of calls does not match', () => {
77
- expect(() => {
78
- expect(() => {
79
- console.error('another message');
80
- console.error('expected message');
81
- }).toErrorDev(['expected message', 'another message']);
82
- }).to.throw('Recorded unexpected console.error calls');
83
- });
84
-
85
- it('fails if there are fewer messages than expected', () => {
86
- expect(() => {
87
- expect(() => {
88
- console.error('expected message');
89
- }).toErrorDev(['expected message', 'another message']);
90
- }).to.throw('Could not match the following console.error calls');
91
- });
92
-
93
- it('passes if no messages were recorded if expected', () => {
94
- expect(() => {}).not.toErrorDev();
95
- expect(() => {}).not.toErrorDev([]);
96
- });
97
-
98
- it('fails if no arguments are used as a way of negating', () => {
99
- expect(() => {
100
- expect(() => {}).toErrorDev();
101
- }).to.throw(
102
- "Expected to call console.error but didn't provide messages. " +
103
- "If you don't expect any messages prefer `expect().not.toErrorDev();",
104
- );
105
- });
106
-
107
- it('fails if arguments are passed when negated', () => {
108
- expect(() => {
109
- expect(() => {}).not.toErrorDev('not unexpected?');
110
- }).to.throw(
111
- 'Expected no call to console.error but provided messages. ' +
112
- "If you want to make sure a certain message isn't logged prefer the positive. " +
113
- 'By expecting certain messages you automatically expect that no other messages are logged',
114
- );
115
- });
116
-
117
- it('ignores `false` messages', () => {
118
- const isReact16 = false;
119
- expect(() => {
120
- expect(() => {}).toErrorDev([isReact16 && 'some legacy error message']);
121
- }).not.to.throw();
122
- });
123
- });
124
- });
@@ -1,7 +0,0 @@
1
- import * as chai from 'chai';
2
- import chaiDom from 'chai-dom';
3
- import './chai.types';
4
- import chaiPlugin from './chaiPlugin';
5
-
6
- chai.use(chaiDom);
7
- chai.use(chaiPlugin);
@@ -1,101 +0,0 @@
1
- import * as chai from 'chai';
2
- import * as DomTestingLibrary from '@testing-library/dom';
3
- import type { ElementHandle } from '@playwright/test';
4
-
5
- // https://stackoverflow.com/a/46755166/3406963
6
- declare global {
7
- // eslint-disable-next-line @typescript-eslint/no-namespace
8
- namespace Chai {
9
- interface Assertion {
10
- /**
11
- * Checks if the element handle is actually focused i.e. the element handle is pointing to `document.activeElement`.
12
- */
13
- toHaveFocus(): Promise<void>;
14
- /**
15
- * Checks if the element handle has the given attribute.
16
- * @example expect($element).toHaveAttribute('aria-expanded') is like `[aria-expanded]` CSS selector
17
- * @example expect($element).toHaveAttribute('aria-expanded', 'true') is like `[aria-expanded="true"]` CSS selector
18
- */
19
- toHaveAttribute(attributeName: string, attributeValue?: string): Promise<void>;
20
- }
21
- }
22
-
23
- interface Window {
24
- DomTestingLibrary: typeof DomTestingLibrary;
25
- /**
26
- * @example $element.evaluate(element => window.pageElementToString(element))
27
- */
28
- elementToString(element: Node | null | undefined): string | false;
29
- }
30
- }
31
-
32
- chai.use((chaiAPI, utils) => {
33
- chai.Assertion.addMethod('toHaveFocus', async function elementHandleIsFocused() {
34
- const $elementOrHandle: ElementHandle | Promise<ElementHandle> = utils.flag(this, 'object');
35
- if ($elementOrHandle == null) {
36
- throw new chai.AssertionError(
37
- `Expected an element handle but got ${String($elementOrHandle)}.`,
38
- );
39
- }
40
- const $element =
41
- typeof ($elementOrHandle as Promise<any>).then === 'function'
42
- ? await ($elementOrHandle as Promise<ElementHandle>)
43
- : ($elementOrHandle as ElementHandle);
44
-
45
- const { isFocused, stringifiedActiveElement, stringifiedElement } = await $element.evaluate(
46
- (element) => {
47
- const activeElement =
48
- element.ownerDocument !== null ? element.ownerDocument.activeElement : null;
49
- return {
50
- isFocused: activeElement === element,
51
- stringifiedElement: window.elementToString(element),
52
- stringifiedActiveElement: window.elementToString(activeElement),
53
- };
54
- },
55
- );
56
-
57
- this.assert(
58
- isFocused,
59
- `expected element to have focus`,
60
- `expected element to NOT have focus \n${stringifiedElement}`,
61
- stringifiedElement,
62
- stringifiedActiveElement,
63
- );
64
- });
65
-
66
- chai.Assertion.addMethod(
67
- 'toHaveAttribute',
68
- async function elementHandleHasAttribute(attributeName: string, attributeValue?: string) {
69
- const $elementOrHandle: ElementHandle | Promise<ElementHandle> = utils.flag(this, 'object');
70
- if ($elementOrHandle == null) {
71
- throw new chai.AssertionError(
72
- `Expected an element handle but got ${String($elementOrHandle)}.`,
73
- );
74
- }
75
- const $element =
76
- typeof ($elementOrHandle as Promise<any>).then === 'function'
77
- ? await ($elementOrHandle as Promise<ElementHandle>)
78
- : ($elementOrHandle as ElementHandle);
79
-
80
- const actualAttributeValue = await $element.getAttribute(attributeName);
81
-
82
- if (attributeValue === undefined) {
83
- this.assert(
84
- actualAttributeValue !== null,
85
- `expected element to have attribute \`${attributeName}\``,
86
- `expected element to NOT have attribute \`${attributeName}\``,
87
- null,
88
- null,
89
- );
90
- } else {
91
- this.assert(
92
- actualAttributeValue === attributeValue,
93
- `expected element to have attribute \`${attributeName}="${attributeValue}"\``,
94
- `expected element to NOT have attribute \`${attributeName}="${attributeValue}"\``,
95
- attributeValue,
96
- actualAttributeValue,
97
- );
98
- }
99
- },
100
- );
101
- });
package/src/mochaHooks.js DELETED
@@ -1,200 +0,0 @@
1
- // @ts-check
2
- const formatUtil = require('format-util');
3
-
4
- /**
5
- * @typedef {(this: import('mocha').Context) => void} MochaHook
6
- *
7
- * @typedef {object} MochaHooks
8
- * @property {MochaHook[]} beforeAll
9
- * @property {MochaHook[]} afterAll
10
- * @property {MochaHook[]} beforeEach
11
- * @property {MochaHook[]} afterEach
12
- *
13
- * @typedef {object} Mocha -- custom definition for `const mocha = require('mocha')`
14
- * @property {import('mocha').utils} utils
15
- */
16
-
17
- const isKarma = Boolean(process.env.KARMA);
18
-
19
- /**
20
- * Polyfills for https://github.com/facebook/react/issues/19416.
21
- * @param {[stack: string, message: string][]} consoleCalls
22
- * @returns {[stack: string, message: string][]}
23
- */
24
- function dedupeActWarningsByComponent(consoleCalls) {
25
- /**
26
- * @type {[stack: string, message: string][]}
27
- */
28
- const dedupedCalls = [];
29
-
30
- /**
31
- * @type {string | undefined}
32
- */
33
- let updatingComponentOutsideAct;
34
-
35
- consoleCalls.forEach(([stack, message]) => {
36
- const componentName = message.match(
37
- /An update to (.+?) ran an effect, but was not wrapped in act/,
38
- )?.[1];
39
-
40
- const duplicateMissingActWarning =
41
- componentName !== undefined && componentName === updatingComponentOutsideAct;
42
- if (!duplicateMissingActWarning) {
43
- dedupedCalls.push([stack, message]);
44
- }
45
- updatingComponentOutsideAct = componentName;
46
- });
47
-
48
- return dedupedCalls;
49
- }
50
-
51
- /**
52
- * @param {Mocha} Mocha
53
- * @param {'warn' | 'error'} methodName
54
- * @param {string} expectedMatcher
55
- * @returns MochaHooks
56
- */
57
- function createUnexpectedConsoleMessagesHooks(Mocha, methodName, expectedMatcher) {
58
- /**
59
- * @type {MochaHooks}
60
- */
61
- const mochaHooks = {
62
- beforeAll: [],
63
- afterAll: [],
64
- beforeEach: [],
65
- afterEach: [],
66
- };
67
- /**
68
- * @type {[stack: string, message: string][]}
69
- */
70
- const unexpectedCalls = [];
71
- const stackTraceFilter = Mocha.utils.stackTraceFilter();
72
-
73
- /**
74
- * @param {string} format
75
- * @param {...unknown} args
76
- * @returns {void}
77
- */
78
- function logUnexpectedConsoleCalls(format, ...args) {
79
- const message = formatUtil(format, ...args);
80
-
81
- // Safe stack so that test dev can track where the unexpected console message was created.
82
- const { stack } = new Error();
83
- if (stack === undefined) {
84
- throw new TypeError(
85
- `Unable to get stack. Logging unexpected console calls is only supported in environments where Error.prototype.stack is implemented.`,
86
- );
87
- }
88
-
89
- if (process.env.NODE_ENV === 'production') {
90
- // TODO: mock scheduler
91
- if (message.includes('act(...) is not supported in production builds of React')) {
92
- return;
93
- }
94
- }
95
-
96
- if (message.includes('Warning: useLayoutEffect does nothing on the server')) {
97
- // Controversial warning that is commonly ignored by switching to `useEffect` on the server.
98
- // https://github.com/facebook/react/issues/14927
99
- // However, this switch doesn't work since it relies on environment sniffing and we test SSR in a browser environment.
100
- return;
101
- }
102
-
103
- // Unclear why this is an issue for the current occurrences of this warning.
104
- // TODO: Revisit once https://github.com/facebook/react/issues/22796 is resolved
105
- if (
106
- message.includes(
107
- 'Detected multiple renderers concurrently rendering the same context provider.',
108
- )
109
- ) {
110
- return;
111
- }
112
-
113
- unexpectedCalls.push([
114
- // first line includes the (empty) error message
115
- // i.e. Remove the `Error:` line
116
- // second line is this frame
117
- stackTraceFilter(stack.split('\n').slice(2).join('\n')),
118
- message,
119
- ]);
120
- }
121
-
122
- /**
123
- * @type {Console['warn' | 'error']}
124
- */
125
- let originalConsoleMethod;
126
- mochaHooks.beforeAll.push(function registerConsoleStub() {
127
- // eslint-disable-next-line no-console
128
- originalConsoleMethod = console[methodName];
129
- // eslint-disable-next-line no-console
130
- console[methodName] = logUnexpectedConsoleCalls;
131
- });
132
-
133
- mochaHooks.afterAll.push(function registerConsoleStub() {
134
- // eslint-disable-next-line no-console
135
- console[methodName] = originalConsoleMethod;
136
- });
137
-
138
- mochaHooks.afterEach.push(function flushUnexpectedCalls() {
139
- const actionableCalls = dedupeActWarningsByComponent(unexpectedCalls);
140
- const actionableCallCount = actionableCalls.length;
141
- const formattedCalls = actionableCalls.map(
142
- ([stack, message], index) =>
143
- `console.${methodName} message #${index + 1}:\n ${message}\n\nStack:\n${stack}`,
144
- );
145
- unexpectedCalls.length = 0;
146
-
147
- // eslint-disable-next-line no-console
148
- if (console[methodName] !== logUnexpectedConsoleCalls) {
149
- throw new Error(`Did not tear down spy or stub of console.${methodName} in your test.`);
150
- }
151
- if (actionableCallCount > 0) {
152
- // In karma `file` is `null`.
153
- // We still have the stacktrace though
154
- // @ts-expect-error -- this.currentTest being undefined would be a bug
155
- const location = this.currentTest.file ?? '(unknown file)';
156
- const message =
157
- `Expected test not to call console.${methodName}() but instead received ${actionableCallCount} calls.\n\n` +
158
- 'If the warning is expected, test for it explicitly by ' +
159
- // Don't add any punctuation after the location.
160
- // Otherwise it's not clickable in IDEs
161
- `using the ${expectedMatcher}() matcher.\nTest location:\n ${location} `;
162
-
163
- const error = new Error(`${message}\n\n${formattedCalls.join('\n\n')}`);
164
- // The stack of `flushUnexpectedCalls` is irrelevant.
165
- // It includes no clue where the test was triggered
166
- error.stack = '';
167
-
168
- if (isKarma) {
169
- // @ts-expect-error -- this.currentTest being undefined would be a bug
170
- const testPath = `"${this.currentTest.fullTitle()}"`;
171
-
172
- error.message += `\n\nin ${testPath}`;
173
- throw error;
174
- } else {
175
- // @ts-expect-error -- this.test being undefined would be a bug
176
- this.test.error(error);
177
- }
178
- }
179
- });
180
-
181
- return mochaHooks;
182
- }
183
-
184
- /**
185
- * @param {Mocha} Mocha
186
- * @returns MochaHooks
187
- */
188
- function createMochaHooks(Mocha) {
189
- const warnHooks = createUnexpectedConsoleMessagesHooks(Mocha, 'warn', 'toWarnDev');
190
- const errorHooks = createUnexpectedConsoleMessagesHooks(Mocha, 'error', 'toErrorDev');
191
-
192
- return {
193
- beforeAll: [...warnHooks.beforeAll, ...errorHooks.beforeAll],
194
- afterAll: [...warnHooks.afterAll, ...errorHooks.afterAll],
195
- beforeEach: [...warnHooks.beforeEach, ...errorHooks.beforeEach],
196
- afterEach: [...warnHooks.afterEach, ...errorHooks.afterEach],
197
- };
198
- }
199
-
200
- module.exports = { createMochaHooks };
@@ -1,116 +0,0 @@
1
- import * as Mocha from 'mocha';
2
- import { expect } from 'chai';
3
- import * as React from 'react';
4
- import { stub } from 'sinon';
5
- import { createMochaHooks } from './mochaHooks';
6
- import { createRenderer, act } from './createRenderer';
7
- import describeSkipIf from './describeSkipIf';
8
-
9
- describeSkipIf(process.env.VITEST)('mochaHooks', () => {
10
- // one block per hook.
11
- describe('afterEach', () => {
12
- describe('on unexpected console.(warn|error) in afterEach', function suite() {
13
- const mochaHooks = createMochaHooks(Mocha);
14
-
15
- beforeEach(function beforeEachHook() {
16
- mochaHooks.beforeAll.forEach((beforeAllMochaHook) => {
17
- beforeAllMochaHook.call(this);
18
- });
19
- mochaHooks.beforeEach.forEach((beforeEachMochaHook) => {
20
- beforeEachMochaHook.call(this);
21
- });
22
- });
23
-
24
- it('throws an error', () => {
25
- console.warn('unexpected warning');
26
- console.error('unexpected error');
27
- });
28
-
29
- afterEach(function afterEachHook() {
30
- const errorStub = stub(this.test, 'error');
31
- mochaHooks.afterEach.forEach((afterEachMochaHook) => {
32
- afterEachMochaHook.call(this);
33
- });
34
- mochaHooks.afterAll.forEach((afterAllMochaHook) => {
35
- afterAllMochaHook.call(this);
36
- });
37
-
38
- expect(errorStub.callCount).to.equal(2);
39
- expect(String(errorStub.firstCall.args[0])).to.include(
40
- 'console.warn message #1:\n unexpected warning\n\nStack:',
41
- );
42
- expect(String(errorStub.secondCall.args[0])).to.include(
43
- 'console.error message #1:\n unexpected error\n\nStack:',
44
- );
45
- });
46
- });
47
-
48
- // TODO: May not be relevant in React 18
49
- describe('when having missing act() warnings by component', () => {
50
- const mochaHooks = createMochaHooks(Mocha);
51
- // missing act warnings only happen in StrictMode
52
- const { render } = createRenderer({ strict: true });
53
-
54
- beforeEach(function beforeEachHook() {
55
- mochaHooks.beforeAll.forEach((beforeAllMochaHook) => {
56
- beforeAllMochaHook.call(this);
57
- });
58
- mochaHooks.beforeEach.forEach((beforeEachMochaHook) => {
59
- beforeEachMochaHook.call(this);
60
- });
61
- });
62
-
63
- it('dedupes them', () => {
64
- const Child = React.forwardRef(function Child() {
65
- React.useEffect(() => {});
66
- React.useEffect(() => {});
67
- return null;
68
- });
69
-
70
- let unsafeSetState;
71
- function Parent() {
72
- const [state, setState] = React.useState(0);
73
- // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler -- unsafeSetState is required outside the component
74
- unsafeSetState = setState;
75
-
76
- React.useEffect(() => {});
77
- React.useEffect(() => {});
78
-
79
- return <Child rerender={state} />;
80
- }
81
-
82
- render(<Parent />);
83
-
84
- // not wrapped in act()
85
- unsafeSetState(1);
86
- // make sure effects are flushed
87
- // eslint-disable-next-line testing-library/no-unnecessary-act
88
- act(() => {});
89
- });
90
-
91
- afterEach(function afterEachHook() {
92
- const errorStub = stub(this.test, 'error');
93
- mochaHooks.afterEach.forEach((afterEachMochaHook) => {
94
- afterEachMochaHook.call(this);
95
- });
96
- mochaHooks.afterAll.forEach((afterAllMochaHook) => {
97
- afterAllMochaHook.call(this);
98
- });
99
-
100
- expect(errorStub.callCount).to.equal(1);
101
- const error = String(errorStub.firstCall.args[0]);
102
- expect(
103
- error.match(/An update to Parent inside a test was not wrapped in act/g),
104
- ).to.have.lengthOf(1);
105
- expect(
106
- error.match(/An update to Parent ran an effect, but was not wrapped in act/g) ?? [],
107
- ).to.have.lengthOf(React.startTransition !== undefined ? 0 : 1);
108
- expect(
109
- error.match(
110
- /An update to ForwardRef\(Child\) ran an effect, but was not wrapped in act/g,
111
- ) ?? [],
112
- ).to.have.lengthOf(React.startTransition !== undefined ? 0 : 1);
113
- });
114
- });
115
- });
116
- });
package/src/reactMajor.ts DELETED
@@ -1,3 +0,0 @@
1
- import * as React from 'react';
2
-
3
- export default parseInt(React.version, 10);
package/src/setupBabel.js DELETED
@@ -1,3 +0,0 @@
1
- require('@babel/register')({
2
- extensions: ['.js', '.mjs', '.cjs', '.jsx', '.ts', '.tsx'],
3
- });
@@ -1,13 +0,0 @@
1
- // In playwright we sometimes write functions that are executed in the browser environment.
2
- // Since we can't tell babel which parts of the code are executed in which environment we can only disable it entirely.
3
- // We're only stripping types and compiling ES6 to CommonJS modules which should be safe.
4
-
5
- require('@babel/register')({
6
- configFile: false,
7
- extensions: ['.js', '.ts', '.tsx'],
8
- presets: [require.resolve('@babel/preset-typescript')],
9
- plugins: [
10
- require.resolve('@babel/plugin-transform-modules-commonjs'),
11
- require.resolve('babel-plugin-transform-import-meta'),
12
- ],
13
- });
package/src/setupJSDOM.js DELETED
@@ -1,20 +0,0 @@
1
- const testingLibrary = require('@testing-library/dom');
2
- const Mocha = require('mocha');
3
- const createDOM = require('./createDOM');
4
- const { createMochaHooks } = require('./mochaHooks');
5
-
6
- // Enable missing act warnings: https://github.com/reactwg/react-18/discussions/102
7
- globalThis.jest = null;
8
- globalThis.IS_REACT_ACT_ENVIRONMENT = true;
9
-
10
- createDOM();
11
- require('./init');
12
-
13
- testingLibrary.configure({
14
- // JSDOM logs errors otherwise on `getComputedStyle(element, pseudoElement)` calls.
15
- computedStyleSupportsPseudoElements: false,
16
- });
17
-
18
- const mochaHooks = createMochaHooks(Mocha);
19
-
20
- module.exports = { mochaHooks };