@mui/internal-test-utils 1.0.19 → 1.0.21

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 (55) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/chai.types.d.ts +75 -0
  3. package/build/chai.types.d.ts.map +1 -0
  4. package/build/chai.types.js +3 -0
  5. package/build/chai.types.js.map +1 -0
  6. package/build/chaiPlugin.d.ts +5 -0
  7. package/build/chaiPlugin.d.ts.map +1 -0
  8. package/build/chaiPlugin.js +406 -0
  9. package/build/chaiPlugin.js.map +1 -0
  10. package/build/createDOM.js +4 -4
  11. package/build/createDOM.js.map +1 -1
  12. package/build/createRenderer.d.ts +37 -62
  13. package/build/createRenderer.d.ts.map +1 -1
  14. package/build/createRenderer.js +85 -40
  15. package/build/createRenderer.js.map +1 -1
  16. package/build/describeConformance.d.ts.map +1 -1
  17. package/build/describeConformance.js +41 -19
  18. package/build/describeConformance.js.map +1 -1
  19. package/build/describeSkipIf.d.ts +3 -0
  20. package/build/describeSkipIf.d.ts.map +1 -0
  21. package/build/describeSkipIf.js +10 -0
  22. package/build/describeSkipIf.js.map +1 -0
  23. package/build/index.d.ts +1 -0
  24. package/build/index.d.ts.map +1 -1
  25. package/build/index.js +3 -1
  26. package/build/index.js.map +1 -1
  27. package/build/initMatchers.d.ts +1 -74
  28. package/build/initMatchers.d.ts.map +1 -1
  29. package/build/initMatchers.js +4 -400
  30. package/build/initMatchers.js.map +1 -1
  31. package/build/initMatchers.test.js +4 -6
  32. package/build/initMatchers.test.js.map +1 -1
  33. package/build/mochaHooks.test.js +5 -1
  34. package/build/mochaHooks.test.js.map +1 -1
  35. package/build/setupJSDOM.js +2 -2
  36. package/build/setupJSDOM.js.map +1 -1
  37. package/build/setupVitest.d.ts +2 -0
  38. package/build/setupVitest.d.ts.map +1 -0
  39. package/build/setupVitest.js +121 -0
  40. package/build/setupVitest.js.map +1 -0
  41. package/package.json +6 -4
  42. package/src/chai.types.ts +106 -0
  43. package/src/chaiPlugin.ts +512 -0
  44. package/src/createDOM.js +4 -4
  45. package/src/createRenderer.tsx +106 -51
  46. package/src/describeConformance.tsx +39 -20
  47. package/src/describeSkipIf.tsx +9 -0
  48. package/src/index.ts +1 -0
  49. package/src/initMatchers.test.js +4 -6
  50. package/src/initMatchers.ts +4 -615
  51. package/src/mochaHooks.test.js +2 -1
  52. package/src/setupJSDOM.js +2 -2
  53. package/src/setupVitest.ts +117 -0
  54. package/tsconfig.json +5 -2
  55. package/tsconfig.tsbuildinfo +0 -1
@@ -1,23 +1,22 @@
1
1
  /* eslint-env mocha */
2
- import * as React from 'react';
3
- import * as ReactDOMServer from 'react-dom/server';
4
2
  import createEmotionCache from '@emotion/cache';
5
3
  import { CacheProvider as EmotionCacheProvider } from '@emotion/react';
6
4
  import {
7
- act as rtlAct,
8
5
  buildQueries,
9
6
  cleanup,
10
- fireEvent as rtlFireEvent,
11
- queries,
12
- queryHelpers,
13
- render as testingLibraryRender,
14
7
  prettyDOM,
15
- within,
8
+ queries,
16
9
  RenderResult,
10
+ act as rtlAct,
11
+ fireEvent as rtlFireEvent,
17
12
  screen as rtlScreen,
18
13
  Screen,
14
+ render as testingLibraryRender,
15
+ within,
19
16
  } from '@testing-library/react/pure';
20
17
  import { userEvent } from '@testing-library/user-event';
18
+ import * as React from 'react';
19
+ import * as ReactDOMServer from 'react-dom/server';
21
20
  import { useFakeTimers } from 'sinon';
22
21
  import reactMajor from './reactMajor';
23
22
 
@@ -114,8 +113,8 @@ class DispatchingProfiler implements Profiler {
114
113
 
115
114
  private renders: RenderMark[] = [];
116
115
 
117
- constructor(test: import('mocha').Test) {
118
- this.id = test.fullTitle();
116
+ constructor(id: string) {
117
+ this.id = id;
119
118
  }
120
119
 
121
120
  onRender: Profiler['onRender'] = (
@@ -193,18 +192,6 @@ const [
193
192
  },
194
193
  );
195
194
 
196
- const queryAllByMuiTest = queryHelpers.queryAllByAttribute.bind(null, 'data-mui-test');
197
- const [queryByMuiTest, getAllByMuiTest, getByMuiTest, findAllByMuiTest, findByMuiTest] =
198
- buildQueries(
199
- queryAllByMuiTest,
200
- function getMultipleError(container, dataMuiTest) {
201
- return `Found multiple elements with the data-mui-test attribute of: ${dataMuiTest}`;
202
- },
203
- function getMissingError(container, dataMuiTest) {
204
- return `Found no element with the data-mui-test attribute of: ${dataMuiTest}`;
205
- },
206
- );
207
-
208
195
  const customQueries = {
209
196
  queryDescriptionOf,
210
197
  queryAllDescriptionsOf,
@@ -212,30 +199,6 @@ const customQueries = {
212
199
  getAllDescriptionsOf,
213
200
  findDescriptionOf,
214
201
  findAllDescriptionsOf,
215
- /**
216
- * @deprecated Use `queryAllByTestId` instead
217
- */
218
- queryAllByMuiTest,
219
- /**
220
- * @deprecated Use `queryByTestId` instead
221
- */
222
- queryByMuiTest,
223
- /**
224
- * @deprecated Use `getAllByTestId` instead
225
- */
226
- getAllByMuiTest,
227
- /**
228
- * @deprecated Use `getByTestId` instead
229
- */
230
- getByMuiTest,
231
- /**
232
- * @deprecated Use `findAllByTestId` instead
233
- */
234
- findAllByMuiTest,
235
- /**
236
- * @deprecated Use `findByTestId` instead
237
- */
238
- findByMuiTest,
239
202
  };
240
203
 
241
204
  interface RenderConfiguration {
@@ -375,11 +338,88 @@ export interface Clock {
375
338
 
376
339
  export type ClockConfig = undefined | number | Date;
377
340
 
341
+ const isVitest =
342
+ // VITEST is present on the environment when not in browser mode.
343
+ process.env.VITEST === 'true' ||
344
+ // VITEST_BROWSER_DEBUG is present on vitest in browser mode.
345
+ typeof process.env.VITEST_BROWSER_DEBUG !== 'undefined';
346
+
347
+ function createVitestClock(
348
+ defaultMode: 'fake' | 'real',
349
+ config: ClockConfig,
350
+ options: Exclude<Parameters<typeof useFakeTimers>[0], number | Date>,
351
+ vi: any,
352
+ ): Clock {
353
+ if (defaultMode === 'fake') {
354
+ beforeEach(() => {
355
+ vi.useFakeTimers(options);
356
+ if (config) {
357
+ vi.setSystemTime(config);
358
+ }
359
+ });
360
+ afterEach(() => {
361
+ vi.useRealTimers();
362
+ });
363
+ } else {
364
+ beforeEach(() => {
365
+ if (config) {
366
+ vi.setSystemTime(config);
367
+ }
368
+ });
369
+ afterEach(() => {
370
+ vi.useRealTimers();
371
+ });
372
+ }
373
+
374
+ return {
375
+ withFakeTimers: () => {
376
+ beforeEach(() => {
377
+ vi.useFakeTimers(options);
378
+ });
379
+ afterEach(() => {
380
+ vi.useRealTimers();
381
+ });
382
+ },
383
+ runToLast: () => {
384
+ traceSync('runToLast', () => {
385
+ rtlAct(() => {
386
+ vi.runOnlyPendingTimers();
387
+ });
388
+ });
389
+ },
390
+ isReal() {
391
+ return !vi.isFakeTimers();
392
+ },
393
+ restore() {
394
+ vi.useRealTimers();
395
+ },
396
+ tick(timeoutMS: number) {
397
+ traceSync('tick', () => {
398
+ rtlAct(() => {
399
+ vi.advanceTimersByTime(timeoutMS);
400
+ });
401
+ });
402
+ },
403
+ runAll() {
404
+ traceSync('runAll', () => {
405
+ rtlAct(() => {
406
+ vi.runAllTimers();
407
+ });
408
+ });
409
+ },
410
+ };
411
+ }
412
+
378
413
  function createClock(
379
414
  defaultMode: 'fake' | 'real',
380
415
  config: ClockConfig,
381
- options?: Exclude<Parameters<typeof useFakeTimers>[0], number | Date>,
416
+ options: Exclude<Parameters<typeof useFakeTimers>[0], number | Date>,
417
+ vi: any,
382
418
  ): Clock {
419
+ if (isVitest) {
420
+ return createVitestClock(defaultMode, config, options, vi);
421
+ }
422
+
383
423
  let clock: ReturnType<typeof useFakeTimers> | null = null;
384
424
 
385
425
  let mode = defaultMode;
@@ -467,6 +507,11 @@ export interface CreateRendererOptions extends Pick<RenderOptions, 'strict' | 's
467
507
  clock?: 'fake' | 'real';
468
508
  clockConfig?: ClockConfig;
469
509
  clockOptions?: Parameters<typeof createClock>[2];
510
+ /**
511
+ * Vitest needs to be injected because this file is transpiled to commonjs and vitest is an esm module.
512
+ * @default {}
513
+ */
514
+ vi?: any;
470
515
  }
471
516
 
472
517
  export function createRenderer(globalOptions: CreateRendererOptions = {}): Renderer {
@@ -475,11 +520,12 @@ export function createRenderer(globalOptions: CreateRendererOptions = {}): Rende
475
520
  clockConfig,
476
521
  strict: globalStrict = true,
477
522
  strictEffects: globalStrictEffects = globalStrict,
523
+ vi = (globalThis as any).vi || {},
478
524
  clockOptions,
479
525
  } = globalOptions;
480
526
  // save stack to re-use in test-hooks
481
527
  const { stack: createClientRenderStack } = new Error();
482
- const clock = createClock(clockMode, clockConfig, clockOptions);
528
+ const clock = createClock(clockMode, clockConfig, clockOptions, vi);
483
529
 
484
530
  /**
485
531
  * Flag whether `createRenderer` was called in a suite i.e. describe() block.
@@ -531,13 +577,22 @@ export function createRenderer(globalOptions: CreateRendererOptions = {}): Rende
531
577
  throw error;
532
578
  }
533
579
 
534
- const test = this.currentTest;
535
- if (test === undefined) {
580
+ let id: string | null = null;
581
+
582
+ if (isVitest) {
583
+ // @ts-expect-error
584
+ id = expect.getState().currentTestName;
585
+ } else {
586
+ id = this.currentTest?.fullTitle() ?? null;
587
+ }
588
+
589
+ if (!id) {
536
590
  throw new Error(
537
591
  'Unable to find the currently running test. This is a bug with the client-renderer. Please report this issue to a maintainer.',
538
592
  );
539
593
  }
540
- profiler = new UsedProfiler(test);
594
+
595
+ profiler = new UsedProfiler(id);
541
596
 
542
597
  emotionCache = createEmotionCache({ key: 'emotion-client-render' });
543
598
 
@@ -1,6 +1,6 @@
1
1
  /* eslint-env mocha */
2
- import * as React from 'react';
3
2
  import { expect } from 'chai';
3
+ import * as React from 'react';
4
4
  import createDescribe from './createDescribe';
5
5
  import { MuiRenderResult } from './createRenderer';
6
6
 
@@ -321,7 +321,9 @@ function testSlotsProp(element: React.ReactElement<any>, getOptions: () => Confo
321
321
  const renderedElement = queryByTestId('customized');
322
322
  expect(renderedElement).not.to.equal(null);
323
323
 
324
- expect(renderedElement!.nodeName.toLowerCase()).to.equal(slotElement);
324
+ if (typeof slotElement === 'string') {
325
+ expect(renderedElement!.nodeName.toLowerCase()).to.equal(slotElement);
326
+ }
325
327
  if (slotOptions.expectedClassName) {
326
328
  expect(renderedElement).to.have.class(slotOptions.expectedClassName);
327
329
  }
@@ -425,7 +427,9 @@ function testSlotsProp(element: React.ReactElement<any>, getOptions: () => Confo
425
427
  const renderedElement = queryByTestId('customized');
426
428
  expect(renderedElement).not.to.equal(null);
427
429
 
428
- expect(renderedElement!.nodeName.toLowerCase()).to.equal(slotElement);
430
+ if (typeof slotElement === 'string') {
431
+ expect(renderedElement!.nodeName.toLowerCase()).to.equal(slotElement);
432
+ }
429
433
  if (slotOptions.expectedClassName) {
430
434
  expect(renderedElement).to.have.class(slotOptions.expectedClassName);
431
435
  }
@@ -617,12 +621,14 @@ function testThemeDefaultProps(
617
621
  });
618
622
 
619
623
  describe('default props provider:', () => {
620
- it('respect custom default props', async function test() {
624
+ it('respect custom default props', async function test(t = {}) {
621
625
  const testProp = 'data-id';
622
626
  const { muiName, render, DefaultPropsProvider } = getOptions();
623
627
 
624
628
  if (!DefaultPropsProvider) {
625
- this.skip();
629
+ // @ts-ignore
630
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
631
+ this?.skip?.() ?? t?.skip();
626
632
  }
627
633
 
628
634
  if (!muiName) {
@@ -634,6 +640,7 @@ function testThemeDefaultProps(
634
640
  }
635
641
 
636
642
  const { container } = await render(
643
+ // @ts-expect-error we skip it above.
637
644
  <DefaultPropsProvider
638
645
  value={{
639
646
  [muiName]: {
@@ -661,9 +668,11 @@ function testThemeStyleOverrides(
661
668
  getOptions: () => ConformanceOptions,
662
669
  ) {
663
670
  describe('theme style overrides:', () => {
664
- it("respect theme's styleOverrides custom state", async function test() {
671
+ it("respect theme's styleOverrides custom state", async function test(t = {}) {
665
672
  if (/jsdom/.test(window.navigator.userAgent)) {
666
- this.skip();
673
+ // @ts-ignore
674
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
675
+ this?.skip?.() ?? t?.skip();
667
676
  }
668
677
  const { muiName, testStateOverrides, render, ThemeProvider, createTheme } = getOptions();
669
678
 
@@ -716,9 +725,11 @@ function testThemeStyleOverrides(
716
725
  expect(container.firstChild).to.toHaveComputedStyle(testStyle);
717
726
  });
718
727
 
719
- it("respect theme's styleOverrides slots", async function test() {
728
+ it("respect theme's styleOverrides slots", async function test(t = {}) {
720
729
  if (/jsdom/.test(window.navigator.userAgent)) {
721
- this.skip();
730
+ // @ts-ignore
731
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
732
+ this?.skip?.() ?? t?.skip();
722
733
  }
723
734
 
724
735
  const {
@@ -827,9 +838,11 @@ function testThemeStyleOverrides(
827
838
  }
828
839
  });
829
840
 
830
- it('overrideStyles does not replace each other in slots', async function test() {
841
+ it('overrideStyles does not replace each other in slots', async function test(t = {}) {
831
842
  if (/jsdom/.test(window.navigator.userAgent)) {
832
- this.skip();
843
+ // @ts-ignore
844
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
845
+ this?.skip?.() ?? t?.skip();
833
846
  }
834
847
 
835
848
  const { muiName, classes, testStateOverrides, render, ThemeProvider, createTheme } =
@@ -905,9 +918,11 @@ function testThemeStyleOverrides(
905
918
  */
906
919
  function testThemeVariants(element: React.ReactElement<any>, getOptions: () => ConformanceOptions) {
907
920
  describe('theme variants:', () => {
908
- it("respect theme's variants", async function test() {
921
+ it("respect theme's variants", async function test(t = {}) {
909
922
  if (/jsdom/.test(window.navigator.userAgent)) {
910
- this.skip();
923
+ // @ts-ignore
924
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
925
+ this?.skip?.() ?? t?.skip();
911
926
  }
912
927
 
913
928
  const { muiName, testVariantProps, render, ThemeProvider, createTheme } = getOptions();
@@ -960,9 +975,11 @@ function testThemeVariants(element: React.ReactElement<any>, getOptions: () => C
960
975
  expect(getByTestId('without-props')).not.to.toHaveComputedStyle(testStyle);
961
976
  });
962
977
 
963
- it('supports custom variant', async function test() {
978
+ it('supports custom variant', async function test(t = {}) {
964
979
  if (/jsdom/.test(window.navigator.userAgent)) {
965
- this.skip();
980
+ // @ts-ignore
981
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
982
+ this?.skip?.() ?? t?.skip();
966
983
  }
967
984
 
968
985
  const { muiName, testCustomVariant, render, ThemeProvider, createTheme } = getOptions();
@@ -1013,12 +1030,14 @@ function testThemeCustomPalette(
1013
1030
  getOptions: () => ConformanceOptions,
1014
1031
  ) {
1015
1032
  describe('theme extended palette:', () => {
1016
- it('should render without errors', function test() {
1033
+ it('should render without errors', function test(t = {}) {
1017
1034
  const { render, ThemeProvider, createTheme } = getOptions();
1018
1035
  if (!/jsdom/.test(window.navigator.userAgent) || !render || !ThemeProvider || !createTheme) {
1019
- this.skip();
1036
+ // @ts-ignore
1037
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
1038
+ this?.skip?.() ?? t?.skip();
1020
1039
  }
1021
-
1040
+ // @ts-ignore
1022
1041
  const theme = createTheme({
1023
1042
  palette: {
1024
1043
  custom: {
@@ -1034,7 +1053,7 @@ function testThemeCustomPalette(
1034
1053
  },
1035
1054
  },
1036
1055
  });
1037
-
1056
+ // @ts-ignore
1038
1057
  expect(() => render(<ThemeProvider theme={theme}>{element}</ThemeProvider>)).not.to.throw();
1039
1058
  });
1040
1059
  });
@@ -1069,7 +1088,7 @@ function describeConformance(
1069
1088
  beforeEach(() => {
1070
1089
  originalMatchmedia = window.matchMedia;
1071
1090
  // Create mocks of localStorage getItem and setItem functions
1072
- Object.defineProperty(global, 'localStorage', {
1091
+ Object.defineProperty(globalThis, 'localStorage', {
1073
1092
  value: {
1074
1093
  getItem: (key: string) => storage[key],
1075
1094
  setItem: (key: string, value: string) => {
@@ -0,0 +1,9 @@
1
+ // Shim for vitest describe.skipIf to be able to run mocha and vitest side-by-side
2
+ // TODO: Remove after migration to vitest is complete
3
+ const describeSkipIf: (condition: boolean) => Mocha.PendingSuiteFunction =
4
+ (describe as any).skipIf ??
5
+ function describeSkipIf(condition: boolean) {
6
+ return condition ? describe.skip : describe;
7
+ };
8
+
9
+ export default describeSkipIf;
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ export {} from './initMatchers';
15
15
  export * as fireDiscreteEvent from './fireDiscreteEvent';
16
16
  export { default as flushMicrotasks } from './flushMicrotasks';
17
17
  export { default as reactMajor } from './reactMajor';
18
+ export { default as describeSkipIf } from './describeSkipIf';
18
19
 
19
20
  /**
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.
@@ -43,13 +43,12 @@ describe('custom matchers', () => {
43
43
  expect(caughtError.stack).to.include(
44
44
  'Could not match the following console.error calls. ' +
45
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
46
+ ' - "expected message"\n',
48
47
  );
49
48
  // check that the top stackframe points to this test
50
49
  // if this test is moved to another file the next assertion fails
51
50
  expect(caughtError.stack).to.match(
52
- /- "expected message"\s+at Context\.(<anonymous>|it) \(.+\/initMatchers\.test\.js:\d+:\d+\)/,
51
+ /- "expected message"\s+at .*\/initMatchers\.test\.js:\d+:\d+/,
53
52
  );
54
53
  });
55
54
 
@@ -65,13 +64,12 @@ describe('custom matchers', () => {
65
64
  expect(caughtError.stack).to.include(
66
65
  'Recorded unexpected console.error calls: \n\n' +
67
66
  ' - Expected #1 "expected message" to be included in \n' +
68
- '"expected Message"\n' +
69
- ' at callback',
67
+ '"expected Message"\n',
70
68
  );
71
69
  // check that the top stackframe points to this test
72
70
  // if this test is moved to another file the next assertion fails
73
71
  expect(caughtError.stack).to.match(
74
- /"expected Message"\s+at callback \(.+\/initMatchers\.test\.js:\d+:\d+\)/,
72
+ /"expected Message"\s+at .*\/initMatchers\.test\.js:\d+:\d+/,
75
73
  );
76
74
  });
77
75