Skip to content

Update tests from Jest to Vitest #6112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
03c713c
refactor(test): update Textarea tests from Jest to Vitest
joshblack May 22, 2025
4b7d768
refactor(test): update ScrollableRegion tests from Jest to Vitest
joshblack May 22, 2025
63f9d68
refactor(test): update RelativeTime test files from Jest to Vitest
joshblack May 22, 2025
c4bc8f4
refactor(test): update RadioGroup tests from Jest to Vitest
joshblack May 22, 2025
4d98135
refactor(test): update Radio tests from Jest to Vitest
joshblack May 22, 2025
9a4fc31
chore: update test setup for React act()
joshblack May 22, 2025
f621f48
refactor(test): update ProgressBar tests from Jest to Vitest
joshblack May 22, 2025
86badc1
chore: update textarea tests
joshblack May 22, 2025
3b68619
Merge branch 'main' into refactor/update-tests-to-vitest-may-22-2025
joshblack May 22, 2025
8c3f9d2
chore: fix eslint error
joshblack May 23, 2025
bdf4e72
Update packages/react/src/Textarea/Textarea.test.tsx
joshblack May 27, 2025
bf3b9cd
refactor: update name of module.css
joshblack May 27, 2025
d349619
chore: update casing for textarea.module.css
joshblack May 27, 2025
6f99c60
Merge branch 'main' into refactor/update-tests-to-vitest-may-22-2025
joshblack May 27, 2025
d13e9e8
Revert " chore: update casing for textarea.module.css"
joshblack May 27, 2025
91d4920
Revert "refactor: update name of module.css"
joshblack May 27, 2025
89c0ae5
Revert "Update packages/react/src/Textarea/Textarea.test.tsx"
joshblack May 27, 2025
a0cc40e
Merge branch 'main' into refactor/update-tests-to-vitest-may-22-2025
primer[bot] May 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/react/config/vitest/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ import '@testing-library/jest-dom/vitest'
afterEach(() => {
cleanup()
})

// @ts-expect-error this is needed for act() from React
// @see https://react.dev/reference/react/act#error-the-current-testing-environment-is-not-configured-to-support-act
globalThis.IS_REACT_ACT_ENVIRONMENT = true
6 changes: 6 additions & 0 deletions packages/react/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ module.exports = {
'<rootDir>/src/CircleOcticon/',
'<rootDir>/src/DataTable/',
'<rootDir>/src/FeatureFlags/',
'<rootDir>/src/ProgressBar/',
'<rootDir>/src/Radio/',
'<rootDir>/src/RadioGroup/',
'<rootDir>/src/RelativeTime/',
'<rootDir>/src/ScrollableRegion/',
'<rootDir>/src/Select/',
'<rootDir>/src/Skeleton/',
'<rootDir>/src/Spinner/',
Expand All @@ -41,6 +46,7 @@ module.exports = {
'<rootDir>/src/TooltipV2/',
'<rootDir>/src/Truncate/',
'<rootDir>/src/UnderlineNav/',
'<rootDir>/src/Textarea/',
],
transformIgnorePatterns: ['node_modules/(?!@github/[a-z-]+-element|@lit-labs/react|@oddbird/popover-polyfill)'],
}
42 changes: 14 additions & 28 deletions packages/react/src/ProgressBar/ProgressBar.test.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,28 @@
import {describe, expect, it} from 'vitest'
import {ProgressBar} from '..'
import {render, behavesAsComponent, checkExports} from '../utils/testing'
import {render as HTMLRender} from '@testing-library/react'
import axe from 'axe-core'
import {render} from '@testing-library/react'

describe('ProgressBar', () => {
behavesAsComponent({Component: ProgressBar, toRender: () => <ProgressBar aria-valuenow={10} progress={0} />})

checkExports('ProgressBar', {
default: undefined,
ProgressBar,
})

it('should support `className` on the outermost element', () => {
const Element = () => (
<ProgressBar progress={80} barSize="small" aria-label="Upload test.png" className={'test-class-name'} />
)
expect(HTMLRender(<Element />).container.firstChild).toHaveClass('test-class-name')
})

it('should have no axe violations', async () => {
const {container} = HTMLRender(<ProgressBar progress={80} barSize="small" aria-label="Upload test.png" />)
const results = await axe.run(container)
expect(results).toHaveNoViolations()
expect(render(<Element />).container.firstChild).toHaveClass('test-class-name')
})

it('respects the "barSize" prop', () => {
const barSizeSmall = HTMLRender(<ProgressBar progress={80} barSize="small" aria-label="Upload test.png" />)
const barSizeSmall = render(<ProgressBar progress={80} barSize="small" aria-label="Upload test.png" />)
expect(barSizeSmall.container.firstChild).toHaveAttribute('data-progress-bar-size', 'small')

const barSizeDefault = HTMLRender(<ProgressBar progress={80} barSize="default" aria-label="Upload test.png" />)
const barSizeDefault = render(<ProgressBar progress={80} barSize="default" aria-label="Upload test.png" />)
expect(barSizeDefault.container.firstChild).toHaveAttribute('data-progress-bar-size', 'default')

const barSizeLarge = HTMLRender(<ProgressBar progress={80} barSize="large" aria-label="Upload test.png" />)
const barSizeLarge = render(<ProgressBar progress={80} barSize="large" aria-label="Upload test.png" />)
expect(barSizeLarge.container.firstChild).toHaveAttribute('data-progress-bar-size', 'large')
})

it('respects the "inline" prop', () => {
const {container} = HTMLRender(<ProgressBar progress={80} barSize="small" aria-label="Upload test.png" inline />)
const {container} = render(<ProgressBar progress={80} barSize="small" aria-label="Upload test.png" inline />)

expect(container.firstChild).toHaveAttribute('data-progress-display', 'inline')
})
Expand All @@ -46,23 +32,23 @@ describe('ProgressBar', () => {
})

it('passed the `aria-label` down to the progress bar', () => {
const {getByRole, getByLabelText} = HTMLRender(<ProgressBar progress={80} aria-label="Upload test.png" />)
const {getByRole, getByLabelText} = render(<ProgressBar progress={80} aria-label="Upload test.png" />)
expect(getByRole('progressbar')).toHaveAttribute('aria-label', 'Upload test.png')
expect(getByLabelText('Upload test.png')).toBeInTheDocument()
})

it('passed the `aria-valuenow` down to the progress bar', () => {
const {getByRole} = HTMLRender(<ProgressBar progress={80} aria-valuenow={80} />)
const {getByRole} = render(<ProgressBar progress={80} aria-valuenow={80} />)
expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '80')
})

it('passed the `aria-valuetext` down to the progress bar', () => {
const {getByRole} = HTMLRender(<ProgressBar aria-valuetext="80 percent" />)
const {getByRole} = render(<ProgressBar aria-valuetext="80 percent" />)
expect(getByRole('progressbar')).toHaveAttribute('aria-valuetext', '80 percent')
})

it('does not pass the `aria-label` down to the progress bar if there are multiple items', () => {
const {getByRole} = HTMLRender(
const {getByRole} = render(
<ProgressBar aria-label="Upload test.png">
<ProgressBar.Item progress={80} />
</ProgressBar>,
Expand All @@ -71,7 +57,7 @@ describe('ProgressBar', () => {
})

it('passes aria attributes to the progress bar item', () => {
const {getByRole} = HTMLRender(
const {getByRole} = render(
<ProgressBar>
<ProgressBar.Item progress={50} aria-label="Progress" ria-valuenow="50"></ProgressBar.Item>
</ProgressBar>,
Expand All @@ -81,12 +67,12 @@ describe('ProgressBar', () => {
})

it('provides `aria-valuenow` to the progress bar item if it is not already provided', () => {
const {getByRole} = HTMLRender(<ProgressBar progress={50} />)
const {getByRole} = render(<ProgressBar progress={50} />)
expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '50')
})

it('applies `0` as a value for `aria-valuenow`', () => {
const {getByRole} = HTMLRender(<ProgressBar progress={0} aria-valuenow={0} aria-label="Upload text.png" />)
const {getByRole} = render(<ProgressBar progress={0} aria-valuenow={0} aria-label="Upload text.png" />)

expect(getByRole('progressbar')).toHaveAttribute('aria-valuenow', '0')
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,98 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`ProgressBar > respects the "progress" prop 1`] = `
{
"asFragment": [Function],
"baseElement": <body>



exports[`ProgressBar respects the "progress" prop 1`] = `
.c0 {
background-color: var(--bgColor-success-emphasis,var(--color-success-emphasis,#1f883d));
}

<span
className="ProgressBarContainer"
data-progress-bar-size="default"
data-progress-display="block"
>
<span
aria-label="Upload test.png"
aria-valuemax={100}
aria-valuemin={0}
aria-valuenow={80}
className="c0 ProgressBarItem"
role="progressbar"
style={
{
"--progress-bg": "var(--bgColor-success-emphasis)",
"--progress-width": "80%",
}
}
/>
</span>
<div>
<span
class="_ProgressBarContainer_1bos7_27"
data-progress-bar-size="default"
data-progress-display="block"
>
<span
aria-label="Upload test.png"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="80"
class="sc-aXZVg lfjCwU _ProgressBarItem_1bos7_11"
role="progressbar"
style="--progress-width: 80%; --progress-bg: var(--bgColor-success-emphasis);"
/>
</span>
</div>
</body>,
"container": <div>
<span
Comment on lines +4 to +29
Copy link
Preview

Copilot AI May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The snapshot includes the full Testing Library API, making it very verbose. Consider switching to a DOM-only snapshot (e.g. via asFragment() or toJSON()) to keep snapshots concise and easier to review.

Copilot uses AI. Check for mistakes.

class="_ProgressBarContainer_1bos7_27"
data-progress-bar-size="default"
data-progress-display="block"
>
<span
aria-label="Upload test.png"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="80"
class="sc-aXZVg lfjCwU _ProgressBarItem_1bos7_11"
role="progressbar"
style="--progress-width: 80%; --progress-bg: var(--bgColor-success-emphasis);"
/>
</span>
</div>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
20 changes: 7 additions & 13 deletions packages/react/src/Radio/Radio.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {describe, it, expect, beforeEach, vi} from 'vitest'
import {Radio} from '..'
import {behavesAsComponent, checkExports} from '../utils/testing'
import {render, fireEvent} from '@testing-library/react'

describe('Radio', () => {
Expand All @@ -9,13 +9,7 @@ describe('Radio', () => {
}

beforeEach(() => {
jest.resetAllMocks()
})

behavesAsComponent({options: {skipAs: true}, Component: Radio, toRender: () => <Radio {...defaultProps} />})

checkExports('Radio', {
default: Radio,
vi.resetAllMocks()
})

it('should support `className` on the outermost element', () => {
Expand Down Expand Up @@ -49,7 +43,7 @@ describe('Radio', () => {
})

it('renders an active radio when checked attribute is passed', () => {
const handleChange = jest.fn()
const handleChange = vi.fn()
const {getByRole} = render(<Radio {...defaultProps} checked onChange={handleChange} />)

const radio = getByRole('radio') as HTMLInputElement
Expand All @@ -58,7 +52,7 @@ describe('Radio', () => {
})

it('accepts a change handler that can alter a single radio state', () => {
const handleChange = jest.fn()
const handleChange = vi.fn()
const {getByRole} = render(<Radio {...defaultProps} onChange={handleChange} />)

const radio = getByRole('radio') as HTMLInputElement
Expand All @@ -71,7 +65,7 @@ describe('Radio', () => {
})

it('renders correct behavior for multiple radio buttons in a group', () => {
const handleChange = jest.fn()
const handleChange = vi.fn()
const RadioGroup = () => (
<form>
<Radio {...defaultProps} value="radio-one" onChange={handleChange} />
Expand All @@ -98,7 +92,7 @@ describe('Radio', () => {
})

it('renders an inactive radio state correctly', () => {
const handleChange = jest.fn()
const handleChange = vi.fn()
const {getByRole, rerender} = render(<Radio {...defaultProps} disabled onChange={handleChange} />)

const radio = getByRole('radio') as HTMLInputElement
Expand All @@ -124,7 +118,7 @@ describe('Radio', () => {
})

it('renders an aria-checked attribute correctly', () => {
const handleChange = jest.fn()
const handleChange = vi.fn()
const {getByRole, rerender} = render(<Radio {...defaultProps} checked={false} onChange={handleChange} />)

const radio = getByRole('radio') as HTMLInputElement
Expand Down
42 changes: 7 additions & 35 deletions packages/react/src/RadioGroup/RadioGroup.test.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,17 @@
import {describe, it, expect, beforeAll, afterAll, vi} from 'vitest'
import {render} from '@testing-library/react'
import {RadioGroup, FormControl, Radio} from '..'
import {behavesAsComponent, checkExports} from '../utils/testing'
import userEvent from '@testing-library/user-event'
import {RadioGroupContext} from '../RadioGroup'

describe('RadioGroup', () => {
const mockWarningFn = jest.fn()
const mockWarningFn = vi.fn()

beforeAll(() => {
jest.spyOn(global.console, 'warn').mockImplementation(mockWarningFn)
vi.spyOn(console, 'warn').mockImplementation(mockWarningFn)
})

afterAll(() => {
jest.clearAllMocks()
})

behavesAsComponent({
Component: RadioGroup,
options: {skipAs: true, skipSx: true},
toRender: () => (
<RadioGroup name="choices">
<RadioGroup.Label>Choices</RadioGroup.Label>
<FormControl>
<Radio value="one" />
<FormControl.Label>Choice one</FormControl.Label>
</FormControl>
<FormControl>
<Radio value="two" />
<FormControl.Label>Choice two</FormControl.Label>
</FormControl>
<FormControl>
<Radio value="three" />
<FormControl.Label>Choice three</FormControl.Label>
</FormControl>
</RadioGroup>
),
})

checkExports('RadioGroup', {
default: RadioGroup,
RadioGroupContext,
vi.clearAllMocks()
Copy link
Preview

Copilot AI May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The afterAll block clears mock calls but does not restore the original console.warn implementation. Consider using vi.restoreAllMocks() or calling mockRestore() on the spy to prevent stubbing console.warn in other tests.

Suggested change
vi.clearAllMocks()
vi.restoreAllMocks()

Copilot uses AI. Check for mistakes.

})

it('renders a disabled group of inputs', () => {
Expand Down Expand Up @@ -95,8 +67,8 @@ describe('RadioGroup', () => {

it('calls onChange handlers passed to RadioGroup and Radio', async () => {
const user = userEvent.setup()
const handleParentChange = jest.fn()
const handleRadioChange = jest.fn()
const handleParentChange = vi.fn()
const handleRadioChange = vi.fn()
const {getByLabelText} = render(
<RadioGroup name="choices" onChange={handleParentChange}>
<RadioGroup.Label>Choices</RadioGroup.Label>
Expand Down Expand Up @@ -125,7 +97,7 @@ describe('RadioGroup', () => {

it('calls onChange handler on RadioGroup with selected value', async () => {
const user = userEvent.setup()
const handleParentChange = jest.fn()
const handleParentChange = vi.fn()
const {getByLabelText} = render(
<RadioGroup name="choices" onChange={handleParentChange}>
<RadioGroup.Label>Choices</RadioGroup.Label>
Expand Down
Loading
Loading