@mui/internal-test-utils 1.0.0-dev.20240529-082515-213b5e33ab

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 (148) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +9 -0
  4. package/build/.tsbuildinfo +1 -0
  5. package/build/KarmaReporterReactProfiler.d.ts +51 -0
  6. package/build/KarmaReporterReactProfiler.d.ts.map +1 -0
  7. package/build/KarmaReporterReactProfiler.js +68 -0
  8. package/build/KarmaReporterReactProfiler.js.map +1 -0
  9. package/build/components.d.ts +36 -0
  10. package/build/components.d.ts.map +1 -0
  11. package/build/components.js +78 -0
  12. package/build/components.js.map +1 -0
  13. package/build/createDOM.d.ts +3 -0
  14. package/build/createDOM.d.ts.map +1 -0
  15. package/build/createDOM.js +60 -0
  16. package/build/createDOM.js.map +1 -0
  17. package/build/createDescribe.d.ts +8 -0
  18. package/build/createDescribe.d.ts.map +1 -0
  19. package/build/createDescribe.js +22 -0
  20. package/build/createDescribe.js.map +1 -0
  21. package/build/createMount.d.ts +9 -0
  22. package/build/createMount.d.ts.map +1 -0
  23. package/build/createMount.js +120 -0
  24. package/build/createMount.js.map +1 -0
  25. package/build/createRenderer.d.ts +231 -0
  26. package/build/createRenderer.d.ts.map +1 -0
  27. package/build/createRenderer.js +506 -0
  28. package/build/createRenderer.js.map +1 -0
  29. package/build/createRenderer.test.d.ts +2 -0
  30. package/build/createRenderer.test.d.ts.map +1 -0
  31. package/build/createRenderer.test.js +48 -0
  32. package/build/createRenderer.test.js.map +1 -0
  33. package/build/describeConformance.d.ts +152 -0
  34. package/build/describeConformance.d.ts.map +1 -0
  35. package/build/describeConformance.js +815 -0
  36. package/build/describeConformance.js.map +1 -0
  37. package/build/findOutermostIntrinsic.d.ts +14 -0
  38. package/build/findOutermostIntrinsic.d.ts.map +1 -0
  39. package/build/findOutermostIntrinsic.js +22 -0
  40. package/build/findOutermostIntrinsic.js.map +1 -0
  41. package/build/findOutermostIntrinsic.test.d.ts +2 -0
  42. package/build/findOutermostIntrinsic.test.d.ts.map +1 -0
  43. package/build/findOutermostIntrinsic.test.js +70 -0
  44. package/build/findOutermostIntrinsic.test.js.map +1 -0
  45. package/build/fireDiscreteEvent.d.ts +7 -0
  46. package/build/fireDiscreteEvent.d.ts.map +1 -0
  47. package/build/fireDiscreteEvent.js +98 -0
  48. package/build/fireDiscreteEvent.js.map +1 -0
  49. package/build/flushMicrotasks.d.ts +2 -0
  50. package/build/flushMicrotasks.d.ts.map +1 -0
  51. package/build/flushMicrotasks.js +11 -0
  52. package/build/flushMicrotasks.js.map +1 -0
  53. package/build/focusVisible.d.ts +7 -0
  54. package/build/focusVisible.d.ts.map +1 -0
  55. package/build/focusVisible.js +33 -0
  56. package/build/focusVisible.js.map +1 -0
  57. package/build/index.d.ts +18 -0
  58. package/build/index.d.ts.map +1 -0
  59. package/build/index.js +59 -0
  60. package/build/index.js.map +1 -0
  61. package/build/init.d.ts +2 -0
  62. package/build/init.d.ts.map +1 -0
  63. package/build/init.js +42 -0
  64. package/build/init.js.map +1 -0
  65. package/build/initMatchers.d.ts +81 -0
  66. package/build/initMatchers.d.ts.map +1 -0
  67. package/build/initMatchers.js +431 -0
  68. package/build/initMatchers.js.map +1 -0
  69. package/build/initMatchers.test.d.ts +2 -0
  70. package/build/initMatchers.test.d.ts.map +1 -0
  71. package/build/initMatchers.test.js +103 -0
  72. package/build/initMatchers.test.js.map +1 -0
  73. package/build/initPlaywrightMatchers.d.ts +25 -0
  74. package/build/initPlaywrightMatchers.d.ts.map +1 -0
  75. package/build/initPlaywrightMatchers.js +63 -0
  76. package/build/initPlaywrightMatchers.js.map +1 -0
  77. package/build/mochaHooks.d.ts +25 -0
  78. package/build/mochaHooks.d.ts.map +1 -0
  79. package/build/mochaHooks.js +171 -0
  80. package/build/mochaHooks.js.map +1 -0
  81. package/build/mochaHooks.test.d.ts +2 -0
  82. package/build/mochaHooks.test.d.ts.map +1 -0
  83. package/build/mochaHooks.test.js +112 -0
  84. package/build/mochaHooks.test.js.map +1 -0
  85. package/build/setup.d.ts +2 -0
  86. package/build/setup.d.ts.map +1 -0
  87. package/build/setup.js +10 -0
  88. package/build/setup.js.map +1 -0
  89. package/build/setupBabel.d.ts +2 -0
  90. package/build/setupBabel.d.ts.map +1 -0
  91. package/build/setupBabel.js +5 -0
  92. package/build/setupBabel.js.map +1 -0
  93. package/build/setupBabelPlaywright.d.ts +2 -0
  94. package/build/setupBabelPlaywright.d.ts.map +1 -0
  95. package/build/setupBabelPlaywright.js +11 -0
  96. package/build/setupBabelPlaywright.js.map +1 -0
  97. package/build/setupJSDOM.d.ts +7 -0
  98. package/build/setupJSDOM.d.ts.map +1 -0
  99. package/build/setupJSDOM.js +17 -0
  100. package/build/setupJSDOM.js.map +1 -0
  101. package/build/setupKarma.d.ts +2 -0
  102. package/build/setupKarma.d.ts.map +1 -0
  103. package/build/setupKarma.js +56 -0
  104. package/build/setupKarma.js.map +1 -0
  105. package/build/until.d.ts +2 -0
  106. package/build/until.d.ts.map +1 -0
  107. package/build/until.js +26 -0
  108. package/build/until.js.map +1 -0
  109. package/build/until.test.d.ts +2 -0
  110. package/build/until.test.d.ts.map +1 -0
  111. package/build/until.test.js +118 -0
  112. package/build/until.test.js.map +1 -0
  113. package/build/userEvent.d.ts +8 -0
  114. package/build/userEvent.d.ts.map +1 -0
  115. package/build/userEvent.js +61 -0
  116. package/build/userEvent.js.map +1 -0
  117. package/package.json +76 -0
  118. package/src/KarmaReporterReactProfiler.js +81 -0
  119. package/src/components.tsx +61 -0
  120. package/src/createDOM.d.ts +9 -0
  121. package/src/createDOM.js +67 -0
  122. package/src/createDescribe.ts +31 -0
  123. package/src/createMount.tsx +136 -0
  124. package/src/createRenderer.test.js +31 -0
  125. package/src/createRenderer.tsx +737 -0
  126. package/src/describeConformance.tsx +1117 -0
  127. package/src/findOutermostIntrinsic.test.js +68 -0
  128. package/src/findOutermostIntrinsic.ts +19 -0
  129. package/src/fireDiscreteEvent.ts +76 -0
  130. package/src/flushMicrotasks.ts +8 -0
  131. package/src/focusVisible.ts +28 -0
  132. package/src/index.ts +24 -0
  133. package/src/init.js +15 -0
  134. package/src/initMatchers.test.js +126 -0
  135. package/src/initMatchers.ts +658 -0
  136. package/src/initPlaywrightMatchers.ts +96 -0
  137. package/src/mochaHooks.js +209 -0
  138. package/src/mochaHooks.test.js +113 -0
  139. package/src/setup.js +10 -0
  140. package/src/setupBabel.js +3 -0
  141. package/src/setupBabelPlaywright.js +10 -0
  142. package/src/setupJSDOM.js +20 -0
  143. package/src/setupKarma.js +65 -0
  144. package/src/until.js +28 -0
  145. package/src/until.test.js +120 -0
  146. package/src/userEvent.ts +35 -0
  147. package/tsconfig.build.json +17 -0
  148. package/tsconfig.json +12 -0
@@ -0,0 +1,68 @@
1
+ import * as React from 'react';
2
+ import { expect } from 'chai';
3
+ import createMount from './createMount';
4
+ import findOutermostIntrinsic from './findOutermostIntrinsic';
5
+
6
+ describe('findOutermostIntrinsic', () => {
7
+ const mount = createMount({ strict: null });
8
+ const expectIntrinsic = (node, expected) => {
9
+ const wrapper = mount(node);
10
+ const outermostIntrinsic = findOutermostIntrinsic(wrapper);
11
+
12
+ if (expected === null) {
13
+ expect(outermostIntrinsic.exists()).to.equal(false);
14
+ } else {
15
+ expect(outermostIntrinsic.type()).to.equal(expected);
16
+ expect(outermostIntrinsic.type()).to.equal(
17
+ outermostIntrinsic.getDOMNode().nodeName.toLowerCase(),
18
+ );
19
+ }
20
+ };
21
+ const Headless = ({ children }) => children;
22
+
23
+ it('returns immediate DOM nodes', () => {
24
+ expectIntrinsic(<div>Hello, World!</div>, 'div');
25
+ });
26
+
27
+ it('only returns the outermost', () => {
28
+ expectIntrinsic(
29
+ <span>
30
+ <div>Hello, World!</div>
31
+ </span>,
32
+ 'span',
33
+ );
34
+ });
35
+
36
+ it('ignores components', () => {
37
+ expectIntrinsic(
38
+ <Headless>
39
+ <div>Hello, World!</div>
40
+ </Headless>,
41
+ 'div',
42
+ );
43
+ expectIntrinsic(
44
+ <Headless>
45
+ <Headless>
46
+ <div>Hello, World!</div>
47
+ </Headless>
48
+ </Headless>,
49
+ 'div',
50
+ );
51
+ expectIntrinsic(
52
+ <Headless>
53
+ <Headless>
54
+ <div>
55
+ <Headless>
56
+ <span>Hello, World!</span>
57
+ </Headless>
58
+ </div>
59
+ </Headless>
60
+ </Headless>,
61
+ 'div',
62
+ );
63
+ });
64
+
65
+ it('can handle that no DOM node is rendered', () => {
66
+ expectIntrinsic(<Headless>{false && <Headless />}</Headless>, null);
67
+ });
68
+ });
@@ -0,0 +1,19 @@
1
+ import { ReactWrapper } from 'enzyme';
2
+
3
+ /**
4
+ * checks if a given react wrapper wraps an intrinsic element i.e. a DOM node
5
+ * @param {import('enzyme').ReactWrapper} reactWrapper
6
+ * @returns {boolean} true if the given reactWrapper wraps an intrinsic element
7
+ */
8
+ export function wrapsIntrinsicElement(reactWrapper: ReactWrapper): boolean {
9
+ return typeof reactWrapper.type() === 'string';
10
+ }
11
+
12
+ /**
13
+ * like ReactWrapper#getDOMNode() but returns a ReactWrapper
14
+ * @param {import('enzyme').ReactWrapper} reactWrapper
15
+ * @returns {import('enzyme').ReactWrapper} the wrapper for the outermost DOM node
16
+ */
17
+ export default function findOutermostIntrinsic(reactWrapper: ReactWrapper): ReactWrapper {
18
+ return reactWrapper.findWhere((n) => n.exists() && wrapsIntrinsicElement(n)).first();
19
+ }
@@ -0,0 +1,76 @@
1
+ import * as React from 'react';
2
+ import { configure, fireEvent, getConfig } from '@testing-library/react';
3
+
4
+ const noWrapper = (callback: () => void) => callback();
5
+
6
+ /**
7
+ * @param {() => void} callback
8
+ * @returns {void}
9
+ */
10
+ function withMissingActWarningsIgnored(callback: () => void) {
11
+ if (React.version.startsWith('18')) {
12
+ callback();
13
+ return;
14
+ }
15
+
16
+ const originalConsoleError = console.error;
17
+ console.error = function silenceMissingActWarnings(message, ...args) {
18
+ const isMissingActWarning = /not wrapped in act\(...\)/.test(message);
19
+ if (!isMissingActWarning) {
20
+ originalConsoleError.call(console, message, ...args);
21
+ }
22
+ };
23
+
24
+ const originalConfig = getConfig();
25
+ configure({
26
+ eventWrapper: noWrapper,
27
+ });
28
+
29
+ try {
30
+ callback();
31
+ } finally {
32
+ configure(originalConfig);
33
+ console.error = originalConsoleError;
34
+ }
35
+ }
36
+
37
+ // -----------------------------------------
38
+ // WARNING ⚠️ WARNING ⚠️ WARNING ⚠️ WARNING
39
+ //
40
+ // Do not add events here because you want to ignore "missing act()" warnings.
41
+ // Only add events if you made sure that React actually considers these as "discrete".
42
+ // Be aware that "discrete events" are an implementation detail of React.
43
+ // To test discrete events we cannot use `fireEvent` from `@testing-library/react` because they are all wrapped in `act`.
44
+ // `act` overrides the "discrete event" semantics with "batching" semantics: https://github.com/facebook/react/blob/3fbd47b86285b6b7bdeab66d29c85951a84d4525/packages/react-reconciler/src/ReactFiberWorkLoop.old.js#L1061-L1064
45
+ // Note that using `fireEvent` from `@testing-library/dom` would not work since /react configures both `fireEvent` to use `act` as a wrapper.
46
+ // -----------------------------------------
47
+
48
+ export function click(...args: Parameters<(typeof fireEvent)['click']>) {
49
+ return withMissingActWarningsIgnored(() => {
50
+ fireEvent.click(...args);
51
+ });
52
+ }
53
+
54
+ export function keyDown(...args: Parameters<(typeof fireEvent)['keyDown']>) {
55
+ return withMissingActWarningsIgnored(() => {
56
+ fireEvent.keyDown(...args);
57
+ });
58
+ }
59
+
60
+ export function keyUp(...args: Parameters<(typeof fireEvent)['keyUp']>) {
61
+ return withMissingActWarningsIgnored(() => {
62
+ fireEvent.keyUp(...args);
63
+ });
64
+ }
65
+
66
+ export function mouseDown(...args: Parameters<(typeof fireEvent)['mouseDown']>) {
67
+ return withMissingActWarningsIgnored(() => {
68
+ fireEvent.mouseDown(...args);
69
+ });
70
+ }
71
+
72
+ export function mouseUp(...args: Parameters<(typeof fireEvent)['mouseUp']>) {
73
+ return withMissingActWarningsIgnored(() => {
74
+ fireEvent.mouseUp(...args);
75
+ });
76
+ }
@@ -0,0 +1,8 @@
1
+ import { act } from './createRenderer';
2
+
3
+ export default async function flushMicrotasks() {
4
+ if (/jsdom/.test(window.navigator.userAgent)) {
5
+ // This is only needed for JSDOM and causes issues in real browsers
6
+ await act(() => async () => {});
7
+ }
8
+ }
@@ -0,0 +1,28 @@
1
+ import { act, fireEvent } from './createRenderer';
2
+
3
+ export default function focusVisible(element: HTMLElement) {
4
+ act(() => {
5
+ element.blur();
6
+ fireEvent.keyDown(document.body, { key: 'Tab' });
7
+ element.focus();
8
+ });
9
+ }
10
+
11
+ export function simulatePointerDevice() {
12
+ // first focus on a page triggers focus visible until a pointer event
13
+ // has been dispatched
14
+ fireEvent.pointerDown(document.body);
15
+ }
16
+
17
+ /**
18
+ * See https://bugs.chromium.org/p/chromium/issues/detail?id=1127875 for more details.
19
+ */
20
+ export function programmaticFocusTriggersFocusVisible(): boolean {
21
+ try {
22
+ // So far this only applies to Chrome 86 beta which is the only tested browser supporting this pseudo class.
23
+ document.createElement('button').matches(':focus-visible');
24
+ return true;
25
+ } catch (error) {
26
+ return false;
27
+ }
28
+ }
package/src/index.ts ADDED
@@ -0,0 +1,24 @@
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 { default as createMount } from './createMount';
9
+ export { default as findOutermostIntrinsic, wrapsIntrinsicElement } from './findOutermostIntrinsic';
10
+ export {
11
+ default as focusVisible,
12
+ simulatePointerDevice,
13
+ programmaticFocusTriggersFocusVisible,
14
+ } from './focusVisible';
15
+ export {} from './initMatchers';
16
+ export * as fireDiscreteEvent from './fireDiscreteEvent';
17
+ export * as userEvent from './userEvent';
18
+ export { default as flushMicrotasks } from './flushMicrotasks';
19
+
20
+ /**
21
+ * 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.
22
+ * Useful for asserting on `console.warn` or `console.error` via `toErrorDev()`.
23
+ */
24
+ export const strictModeDoubleLoggingSuppressed = React.version.startsWith('17');
package/src/init.js ADDED
@@ -0,0 +1,15 @@
1
+ import enzyme from 'enzyme';
2
+ import Adapter from '@mnajdova/enzyme-adapter-react-18';
3
+ import * as testingLibrary from '@testing-library/react/pure';
4
+ import './initMatchers';
5
+
6
+ enzyme.configure({ adapter: new Adapter() });
7
+
8
+ // checking if an element is hidden is quite expensive
9
+ // this is only done in CI as a fail safe. It can still explicitly be checked
10
+ // in the test files which helps documenting what is part of the DOM but hidden
11
+ // from assistive technology
12
+ const defaultHidden = !process.env.CI;
13
+ // adds verbosity for something that might be confusing
14
+ console.warn(`${defaultHidden ? 'including' : 'excluding'} inaccessible elements by default`);
15
+ testingLibrary.configure({ defaultHidden });
@@ -0,0 +1,126 @@
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
+ ' at Context.', // `Context.it` in node 12.x, `Context.<anonymous>` in later node version
48
+ );
49
+ // check that the top stackframe points to this test
50
+ // if this test is moved to another file the next assertion fails
51
+ expect(caughtError.stack).to.match(
52
+ /- "expected message"\s+at Context\.(<anonymous>|it) \(.+\/initMatchers\.test\.js:\d+:\d+\)/,
53
+ );
54
+ });
55
+
56
+ it('is case sensitive', () => {
57
+ let caughtError;
58
+ try {
59
+ expect(() => console.error('expected Message')).toErrorDev('expected message');
60
+ } catch (error) {
61
+ caughtError = error;
62
+ }
63
+
64
+ expect(caughtError).to.have.property('stack');
65
+ expect(caughtError.stack).to.include(
66
+ 'Recorded unexpected console.error calls: \n\n' +
67
+ ' - Expected #1 "expected message" to be included in \n' +
68
+ '"expected Message"\n' +
69
+ ' at callback',
70
+ );
71
+ // check that the top stackframe points to this test
72
+ // if this test is moved to another file the next assertion fails
73
+ expect(caughtError.stack).to.match(
74
+ /"expected Message"\s+at callback \(.+\/initMatchers\.test\.js:\d+:\d+\)/,
75
+ );
76
+ });
77
+
78
+ it('fails if the order of calls does not match', () => {
79
+ expect(() => {
80
+ expect(() => {
81
+ console.error('another message');
82
+ console.error('expected message');
83
+ }).toErrorDev(['expected message', 'another message']);
84
+ }).to.throw('Recorded unexpected console.error calls');
85
+ });
86
+
87
+ it('fails if there are fewer messages than expected', () => {
88
+ expect(() => {
89
+ expect(() => {
90
+ console.error('expected message');
91
+ }).toErrorDev(['expected message', 'another message']);
92
+ }).to.throw('Could not match the following console.error calls');
93
+ });
94
+
95
+ it('passes if no messages were recorded if expected', () => {
96
+ expect(() => {}).not.toErrorDev();
97
+ expect(() => {}).not.toErrorDev([]);
98
+ });
99
+
100
+ it('fails if no arguments are used as a way of negating', () => {
101
+ expect(() => {
102
+ expect(() => {}).toErrorDev();
103
+ }).to.throw(
104
+ "Expected to call console.error but didn't provide messages. " +
105
+ "If you don't expect any messages prefer `expect().not.toErrorDev();",
106
+ );
107
+ });
108
+
109
+ it('fails if arguments are passed when negated', () => {
110
+ expect(() => {
111
+ expect(() => {}).not.toErrorDev('not unexpected?');
112
+ }).to.throw(
113
+ 'Expected no call to console.error but provided messages. ' +
114
+ "If you want to make sure a certain message isn't logged prefer the positive. " +
115
+ 'By expecting certain messages you automatically expect that no other messages are logged',
116
+ );
117
+ });
118
+
119
+ it('ignores `false` messages', () => {
120
+ const isReact16 = false;
121
+ expect(() => {
122
+ expect(() => {}).toErrorDev([isReact16 && 'some legacy error message']);
123
+ }).not.to.throw();
124
+ });
125
+ });
126
+ });