Skip to content

Commit

Permalink
Migrate from Jest to Vitest (#3342)
Browse files Browse the repository at this point in the history
  • Loading branch information
chaance authored Jan 22, 2025
1 parent bfd3da3 commit cb15185
Show file tree
Hide file tree
Showing 21 changed files with 1,350 additions and 2,535 deletions.
3 changes: 3 additions & 0 deletions .yarn/versions/ebaeefc2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declined:
- primitives
- "@radix-ui/react-slot"
42 changes: 8 additions & 34 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"scripts": {
"lint": "eslint packages",
"types:check": "tsc --skipLibCheck --noEmit",
"test": "jest",
"test:ci": "yarn types:check && jest --ci && yarn cypress:ci",
"test": "vitest",
"test:ci": "yarn types:check && vitest run && yarn cypress:ci",
"storybook": "BROWSER=none storybook dev -p 9009",
"cypress:ci": "start-server-and-test storybook http://localhost:9009 cypress:run",
"cypress:run": "cypress run",
Expand Down Expand Up @@ -46,8 +46,6 @@
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/fs-extra": "^11",
"@types/jest": "^29.5.14",
"@types/jest-axe": "^3.5.9",
"@types/react": "^19.0.7",
"@types/react-dom": "^19.0.3",
"@types/react-test-renderer": "^19.0.0",
Expand All @@ -61,10 +59,7 @@
"fs-extra": "^11.1.1",
"glob": "^10.2.2",
"husky": "^4.3.6",
"jest": "^29.7.0",
"jest-axe": "^6.0.0",
"jest-environment-jsdom": "^29.7.0",
"jest-watch-typeahead": "^2.2.2",
"jsdom": "^26.0.0",
"lint-staged": "^10.5.3",
"prettier": "^2.0.5",
"pretty-quick": "^2.0.1",
Expand All @@ -74,9 +69,12 @@
"replace-in-files": "^3.0.0",
"start-server-and-test": "2.0.3",
"storybook": "^8.5.0",
"ts-jest": "^29.2.5",
"tsup": "8.0.2",
"typescript": "^5.7.3"
"typescript": "^5.7.3",
"vite": "^6.0.7",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.0.2",
"vitest-axe": "^1.0.0-pre.3"
},
"resolutions": {
"chokidar": "3.4.3"
Expand All @@ -85,30 +83,6 @@
"node": ">=12",
"yarn": ">=2"
},
"jest": {
"testEnvironment": "jsdom",
"roots": [
"<rootDir>/packages"
],
"testMatch": [
"**/?(*.)+(test).+(ts|tsx|js)"
],
"transform": {
"^.+\\.(ts|tsx)$": "ts-jest"
},
"moduleNameMapper": {
"@radix-ui/react-(.+)$": "<rootDir>/packages/react/$1/src",
"@radix-ui/(.+)$": "<rootDir>packages/core/$1/src"
},
"watchPlugins": [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname"
],
"setupFilesAfterEnv": [
"<rootDir>/scripts/setup-tests.ts",
"jest-axe/extend-expect"
]
},
"prettier": {
"printWidth": 100,
"singleQuote": true
Expand Down
4 changes: 2 additions & 2 deletions packages/react/accessible-icon/src/AccesibleIcon.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render } from '@testing-library/react';
import { AccessibleIcon } from '@radix-ui/react-accessible-icon';
Expand Down Expand Up @@ -56,7 +56,7 @@ describe('given an AccessibleIcon without children', () => {
it('should error', () => {
// Even though the error is caught, it still gets printed to the console
// so we mock that out to avoid the wall of red text.
const spy = jest.spyOn(console, 'error');
const spy = vi.spyOn(console, 'error');
spy.mockImplementation(() => {});

expect(() => render(<AccessibleIconTest />)).toThrowError();
Expand Down
15 changes: 8 additions & 7 deletions packages/react/accordion/src/Accordion.test.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import * as React from 'react';
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import * as Accordion from '@radix-ui/react-accordion';
import type { Mock } from 'vitest';

const ITEMS = ['One', 'Two', 'Three'];

describe('given a single Accordion', () => {
let handleValueChange: jest.Mock;
let handleValueChange: Mock;
let rendered: RenderResult;

describe('with default orientation=vertical', () => {
beforeEach(() => {
handleValueChange = jest.fn();
handleValueChange = vi.fn();
rendered = render(<AccordionTest type="single" onValueChange={handleValueChange} />);
});

Expand Down Expand Up @@ -132,7 +133,7 @@ describe('given a single Accordion', () => {
describe('with orientation=horizontal', () => {
describe('and default dir="ltr"', () => {
beforeEach(() => {
handleValueChange = jest.fn();
handleValueChange = vi.fn();
rendered = render(
<AccordionTest type="single" orientation="horizontal" onValueChange={handleValueChange} />
);
Expand Down Expand Up @@ -206,7 +207,7 @@ describe('given a single Accordion', () => {

describe('and dir="rtl"', () => {
beforeEach(() => {
handleValueChange = jest.fn();
handleValueChange = vi.fn();
rendered = render(
<AccordionTest
type="single"
Expand Down Expand Up @@ -284,11 +285,11 @@ describe('given a single Accordion', () => {
});

describe('given a multiple Accordion', () => {
let handleValueChange: jest.Mock;
let handleValueChange: Mock;
let rendered: RenderResult;

beforeEach(() => {
handleValueChange = jest.fn();
handleValueChange = vi.fn();
rendered = render(<AccordionTest type="multiple" onValueChange={handleValueChange} />);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/react/alert-dialog/src/AlertDialog.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import * as AlertDialog from '@radix-ui/react-alert-dialog';
Expand Down
2 changes: 1 addition & 1 deletion packages/react/arrow/src/Arrow.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render } from '@testing-library/react';
import { Arrow } from '@radix-ui/react-arrow';
Expand Down
2 changes: 1 addition & 1 deletion packages/react/aspect-ratio/src/AspectRatio.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render } from '@testing-library/react';
import { AspectRatio } from '@radix-ui/react-aspect-ratio';
Expand Down
2 changes: 1 addition & 1 deletion packages/react/avatar/src/Avatar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render, waitFor } from '@testing-library/react';
import * as Avatar from '@radix-ui/react-avatar';
Expand Down
112 changes: 57 additions & 55 deletions packages/react/checkbox/src/Checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import { Checkbox, CheckboxIndicator } from '@radix-ui/react-checkbox';
Expand Down Expand Up @@ -72,7 +72,7 @@ describe('given an uncontrolled `checked` Checkbox', () => {
let rendered: RenderResult;
let checkbox: HTMLElement;
let indicator: HTMLElement | null;
const onCheckedChange = jest.fn();
const onCheckedChange = vi.fn();

beforeEach(() => {
rendered = render(<CheckboxTest defaultChecked onCheckedChange={onCheckedChange} />);
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('given an uncontrolled `checked` Checkbox', () => {
describe('given a controlled `checked` Checkbox', () => {
let rendered: RenderResult;
let checkbox: HTMLElement;
const onCheckedChange = jest.fn();
const onCheckedChange = vi.fn();

beforeEach(() => {
rendered = render(<CheckboxTest checked onCheckedChange={onCheckedChange} />);
Expand All @@ -122,63 +122,65 @@ describe('given a controlled `checked` Checkbox', () => {

describe('given an uncontrolled Checkbox in form', () => {
describe('when clicking the checkbox', () => {
it('should receive change event with target `defaultChecked` same as the `defaultChecked` prop of Checkbox', (done) => {
const rendered = render(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(true);
}}
>
<CheckboxTest defaultChecked />
</form>
);
const checkbox = rendered.getByRole(CHECKBOX_ROLE);
fireEvent.click(checkbox);
rendered.rerender(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(false);
done();
}}
>
<CheckboxTest defaultChecked={false} />
</form>
);
fireEvent.click(checkbox);
});
it('should receive change event with target `defaultChecked` same as the `defaultChecked` prop of Checkbox', () =>
new Promise((done) => {
const rendered = render(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(true);
}}
>
<CheckboxTest defaultChecked />
</form>
);
const checkbox = rendered.getByRole(CHECKBOX_ROLE);
fireEvent.click(checkbox);
rendered.rerender(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(false);
done(null);
}}
>
<CheckboxTest defaultChecked={false} />
</form>
);
fireEvent.click(checkbox);
}));
});
});

describe('given a controlled Checkbox in a form', () => {
describe('when clicking the checkbox', () => {
it('should receive change event with target `defaultChecked` same as initial value of `checked` of Checkbox', (done) => {
const rendered = render(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(true);
}}
>
<CheckboxTest checked />
</form>
);
const checkbox = rendered.getByRole(CHECKBOX_ROLE);
fireEvent.click(checkbox);
rendered.rerender(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(true);
done();
}}
>
<CheckboxTest checked={false} />
</form>
);
fireEvent.click(checkbox);
});
it('should receive change event with target `defaultChecked` same as initial value of `checked` of Checkbox', () =>
new Promise((done) => {
const rendered = render(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(true);
}}
>
<CheckboxTest checked />
</form>
);
const checkbox = rendered.getByRole(CHECKBOX_ROLE);
fireEvent.click(checkbox);
rendered.rerender(
<form
onChange={(event) => {
const target = event.target as HTMLInputElement;
expect(target.defaultChecked).toBe(true);
done(null);
}}
>
<CheckboxTest checked={false} />
</form>
);
fireEvent.click(checkbox);
}));
});
});

Expand Down
6 changes: 3 additions & 3 deletions packages/react/collapsible/src/Collapsible.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@radix-ui/react-collapsible';
Expand Down Expand Up @@ -53,7 +53,7 @@ describe('given a default Collapsible', () => {
describe('given an open uncontrolled Collapsible', () => {
let rendered: RenderResult;
let content: HTMLElement | null;
const onOpenChange = jest.fn();
const onOpenChange = vi.fn();

beforeEach(() => {
rendered = render(<CollapsibleTest defaultOpen onOpenChange={onOpenChange} />);
Expand All @@ -79,7 +79,7 @@ describe('given an open uncontrolled Collapsible', () => {
describe('given an open controlled Collapsible', () => {
let rendered: RenderResult;
let content: HTMLElement;
const onOpenChange = jest.fn();
const onOpenChange = vi.fn();

beforeEach(() => {
rendered = render(<CollapsibleTest open onOpenChange={onOpenChange} />);
Expand Down
19 changes: 10 additions & 9 deletions packages/react/dialog/src/Dialog.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from 'react';
import { axe } from 'jest-axe';
import { axe } from 'vitest-axe';
import type { RenderResult } from '@testing-library/react';
import { render, fireEvent, cleanup } from '@testing-library/react';
import * as Dialog from '@radix-ui/react-dialog';
import type { Mock, MockInstance } from 'vitest';

const OPEN_TEXT = 'Open';
const CLOSE_TEXT = 'Close';
Expand Down Expand Up @@ -48,19 +49,19 @@ describe('given a default Dialog', () => {
let rendered: RenderResult;
let trigger: HTMLElement;
let closeButton: HTMLElement;
let consoleWarnMock: jest.SpyInstance;
let consoleWarnMockFunction: jest.Mock;
let consoleErrorMock: jest.SpyInstance;
let consoleErrorMockFunction: jest.Mock;
let consoleWarnMock: MockInstance;
let consoleWarnMockFunction: Mock;
let consoleErrorMock: MockInstance;
let consoleErrorMockFunction: Mock;

beforeEach(() => {
// This surpresses React error boundary logs for testing intentionally
// thrown errors, like in some test cases in this suite. See discussion of
// this here: https://github.com/facebook/react/issues/11098
consoleWarnMockFunction = jest.fn();
consoleWarnMock = jest.spyOn(console, 'warn').mockImplementation(consoleWarnMockFunction);
consoleErrorMockFunction = jest.fn();
consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(consoleErrorMockFunction);
consoleWarnMockFunction = vi.fn();
consoleWarnMock = vi.spyOn(console, 'warn').mockImplementation(consoleWarnMockFunction);
consoleErrorMockFunction = vi.fn();
consoleErrorMock = vi.spyOn(console, 'error').mockImplementation(consoleErrorMockFunction);

rendered = render(<DialogTest />);
trigger = rendered.getByText(OPEN_TEXT);
Expand Down
2 changes: 1 addition & 1 deletion packages/react/focus-scope/src/FocusScope.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('FocusScope', () => {
});

describe('given a FocusScope with internal focus handlers', () => {
const handleLastFocusableElementBlur = jest.fn();
const handleLastFocusableElementBlur = vi.fn();
let rendered: RenderResult;
let tabbableFirst: HTMLInputElement;
beforeEach(() => {
Expand Down
Loading

0 comments on commit cb15185

Please sign in to comment.