Skip to content

Update vitest config and TreeView tests to Vitest #6236

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 15 commits into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ docs/public/**/*.css
**/lib/**/*.css
**/dist/**/*.css
**/.next/**/*.css
**/storybook-static/**
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 73 additions & 0 deletions packages/react/config/vitest/browser/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* stylelint-disable selector-pseudo-class-no-unknown */

@import '@primer/primitives/dist/css/base/motion/motion.css';
@import '@primer/primitives/dist/css/base/size/size.css';
@import '@primer/primitives/dist/css/base/typography/typography.css';
@import '@primer/primitives/dist/css/functional/size/border.css';
@import '@primer/primitives/dist/css/functional/size/breakpoints.css';
@import '@primer/primitives/dist/css/functional/size/size-coarse.css';
@import '@primer/primitives/dist/css/functional/size/size-fine.css';
@import '@primer/primitives/dist/css/functional/size/size.css';
@import '@primer/primitives/dist/css/functional/size/viewport.css';
@import '@primer/primitives/dist/css/functional/themes/dark-colorblind.css';
@import '@primer/primitives/dist/css/functional/themes/dark-dimmed.css';
@import '@primer/primitives/dist/css/functional/themes/dark-high-contrast.css';
@import '@primer/primitives/dist/css/functional/themes/dark-tritanopia.css';
@import '@primer/primitives/dist/css/functional/themes/dark.css';
@import '@primer/primitives/dist/css/functional/themes/light-colorblind.css';
@import '@primer/primitives/dist/css/functional/themes/light-high-contrast.css';
@import '@primer/primitives/dist/css/functional/themes/light-tritanopia.css';
@import '@primer/primitives/dist/css/functional/themes/light.css';
@import '@primer/primitives/dist/css/functional/typography/typography.css';

* {
box-sizing: border-box;
}

body {
color: var(--fgColor-default);
background-color: var(--bgColor-default);
font-family: var(--fontStack-system);
line-height: var(--text-body-lineHeight-large);
margin: 0;
}

table {
/* stylelint-disable-next-line primer/borders */
border-collapse: collapse;
}

[data-color-mode='light'] input {
color-scheme: light;
}

[data-color-mode='dark'] input {
color-scheme: dark;
}

@media (prefers-color-scheme: light) {
[data-color-mode='auto'][data-light-theme*='light'] {
color-scheme: light;
}
}

@media (prefers-color-scheme: dark) {
[data-color-mode='auto'][data-dark-theme*='dark'] {
color-scheme: dark;
}
}

[role='button']:focus:not(:focus-visible):not(:global(.focus-visible)),
/* stylelint-disable-next-line selector-max-specificity */
[role='tabpanel'][tabindex='0']:focus:not(:focus-visible):not(:global(.focus-visible)),
button:focus:not(:focus-visible):not(:global(.focus-visible)),
summary:focus:not(:focus-visible):not(:global(.focus-visible)),
a:focus:not(:focus-visible):not(:global(.focus-visible)) {
outline: none;
box-shadow: none;
}

[tabindex='0']:focus:not(:focus-visible):not(:global(.focus-visible)),
details-dialog:focus:not(:focus-visible):not(:global(.focus-visible)) {
outline: none;
}
39 changes: 39 additions & 0 deletions packages/react/config/vitest/browser/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import '@primer/primitives/dist/css/base/motion/motion.css'
import '@primer/primitives/dist/css/base/size/size.css'
import '@primer/primitives/dist/css/base/typography/typography.css'
import '@primer/primitives/dist/css/functional/size/border.css'
import '@primer/primitives/dist/css/functional/size/breakpoints.css'
import '@primer/primitives/dist/css/functional/size/size-coarse.css'
import '@primer/primitives/dist/css/functional/size/size-fine.css'
import '@primer/primitives/dist/css/functional/size/size.css'
import '@primer/primitives/dist/css/functional/size/viewport.css'
import '@primer/primitives/dist/css/functional/themes/dark-colorblind.css'
import '@primer/primitives/dist/css/functional/themes/dark-dimmed.css'
import '@primer/primitives/dist/css/functional/themes/dark-high-contrast.css'
import '@primer/primitives/dist/css/functional/themes/dark-tritanopia.css'
import '@primer/primitives/dist/css/functional/themes/dark.css'
import '@primer/primitives/dist/css/functional/themes/light-colorblind.css'
import '@primer/primitives/dist/css/functional/themes/light-high-contrast.css'
import '@primer/primitives/dist/css/functional/themes/light-tritanopia.css'
import '@primer/primitives/dist/css/functional/themes/light.css'
import '@primer/primitives/dist/css/functional/typography/typography.css'
import './global.css'

import {beforeEach} from 'vitest'
import {cleanup} from '@testing-library/react'
import '@testing-library/jest-dom/vitest'

beforeEach(() => {
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

// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
document.documentElement.setAttribute('data-color-mode', 'auto')
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
document.documentElement.setAttribute('data-light-theme', 'light')
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
document.documentElement.setAttribute('data-dark-theme', 'dark')
19 changes: 10 additions & 9 deletions packages/react/config/vitest/setup.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {afterEach} from 'vitest'
import {cleanup} from '@testing-library/react'
import '@testing-library/jest-dom/vitest'
import failOnConsole from 'vitest-fail-on-console'

afterEach(() => {
cleanup()
})
const failConsoleMessages = process.env.CI === 'true'

// @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
failOnConsole({
shouldFailOnAssert: failConsoleMessages,
shouldFailOnDebug: failConsoleMessages,
shouldFailOnError: failConsoleMessages,
shouldFailOnInfo: failConsoleMessages,
shouldFailOnLog: failConsoleMessages,
shouldFailOnWarn: failConsoleMessages,
})
1 change: 1 addition & 0 deletions packages/react/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ module.exports = {
'<rootDir>/src/ToggleSwitch/',
'<rootDir>/src/Tooltip/',
'<rootDir>/src/TooltipV2/',
'<rootDir>/src/TreeView/',
'<rootDir>/src/Truncate/',
'<rootDir>/src/UnderlineNav/',
'<rootDir>/src/__tests__/BaseStyles.test.tsx',
Expand Down
1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@
"unist-util-find": "3.0.0",
"unist-util-find-before": "4.0.0",
"unist-util-flat-filter": "2.0.0",
"vitest-fail-on-console": "^0.7.1",
"yaml": "2.7.0"
},
"peerDependencies": {
Expand Down
48 changes: 29 additions & 19 deletions packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {useCallback, useState} from 'react'
import {act, useCallback, useState} from 'react'
import {describe, expect, it, vi} from 'vitest'
import {render, fireEvent} from '@testing-library/react'
import {render} from '@testing-library/react'
import {userEvent} from '@vitest/browser/context'
import {AnchoredOverlay} from '../AnchoredOverlay'
import {Button} from '../Button'
import theme from '../theme'
Expand Down Expand Up @@ -53,35 +54,39 @@ const AnchoredOverlayTestComponent = ({
}

describe('AnchoredOverlay', () => {
it('should call onOpen when the anchor is clicked', () => {
it('should call onOpen when the anchor is clicked', async () => {
const mockOpenCallback = vi.fn()
const mockCloseCallback = vi.fn()
const anchoredOverlay = render(
<AnchoredOverlayTestComponent onOpenCallback={mockOpenCallback} onCloseCallback={mockCloseCallback} />,
)
const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="true"]')!
fireEvent.click(anchor)
await act(async () => {
await userEvent.click(anchor)
})

expect(mockOpenCallback).toHaveBeenCalledTimes(1)
expect(mockOpenCallback).toHaveBeenCalledWith('anchor-click')
expect(mockCloseCallback).toHaveBeenCalledTimes(0)
})

it('should call onOpen when the anchor activated by a key press', () => {
it('should call onOpen when the anchor activated by a key press', async () => {
const mockOpenCallback = vi.fn()
const mockCloseCallback = vi.fn()
const anchoredOverlay = render(
<AnchoredOverlayTestComponent onOpenCallback={mockOpenCallback} onCloseCallback={mockCloseCallback} />,
)
const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="true"]')!
fireEvent.keyDown(anchor, {key: ' '})
await act(async () => {
await userEvent.type(anchor, '{Space}')
})

expect(mockOpenCallback).toHaveBeenCalledTimes(1)
expect(mockOpenCallback).toHaveBeenCalledWith('anchor-key-press')
expect(mockCloseCallback).toHaveBeenCalledTimes(0)
})

it('should call onClose when the user clicks off of the overlay', () => {
it('should call onClose when the user clicks off of the overlay', async () => {
const mockOpenCallback = vi.fn()
const mockCloseCallback = vi.fn()
const anchoredOverlay = render(
Expand All @@ -91,7 +96,9 @@ describe('AnchoredOverlay', () => {
onCloseCallback={mockCloseCallback}
/>,
)
fireEvent.mouseDown(anchoredOverlay.baseElement)
await act(async () => {
await userEvent.click(anchoredOverlay.baseElement)
})

expect(mockOpenCallback).toHaveBeenCalledTimes(0)
expect(mockCloseCallback).toHaveBeenCalledTimes(1)
Expand All @@ -101,15 +108,18 @@ describe('AnchoredOverlay', () => {
it('should call onClose when the escape key is pressed', async () => {
const mockOpenCallback = vi.fn()
const mockCloseCallback = vi.fn()
const anchoredOverlay = render(

render(
<AnchoredOverlayTestComponent
initiallyOpen={true}
onOpenCallback={mockOpenCallback}
onCloseCallback={mockCloseCallback}
/>,
)
const overlay = await anchoredOverlay.findByRole('none')
fireEvent.keyDown(overlay, {key: 'Escape'})

await act(async () => {
await userEvent.keyboard('{Escape}')
})

expect(mockOpenCallback).toHaveBeenCalledTimes(0)
expect(mockCloseCallback).toHaveBeenCalledTimes(1)
Expand All @@ -121,21 +131,21 @@ describe('AnchoredOverlay', () => {
expect(container).toMatchSnapshot()
})

it('should call onPositionChange when provided', () => {
it('should call onPositionChange when provided', async () => {
const mockPositionChangeCallback = vi.fn(({position}: {position: AnchorPosition}) => position)
const anchoredOverlay = render(
<AnchoredOverlayTestComponent initiallyOpen={true} onPositionChange={mockPositionChangeCallback} />,
)
const overlay = anchoredOverlay.baseElement.querySelector('[role="none"]')!
fireEvent.keyDown(overlay, {key: 'Escape'})
render(<AnchoredOverlayTestComponent initiallyOpen={true} onPositionChange={mockPositionChangeCallback} />)

await act(async () => {
await userEvent.keyboard('{Escape}')
})

expect(mockPositionChangeCallback).toHaveBeenCalledTimes(1)
expect(mockPositionChangeCallback).toHaveBeenCalled()
expect(mockPositionChangeCallback).toHaveBeenCalledWith({
position: {
anchorAlign: 'start',
anchorSide: 'outside-bottom',
left: 0,
top: 26.84375,
top: 36,
},
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`AnchoredOverlay > should render consistently when open 1`] = `
<div>
<div
class="_BaseStyles_1n09d_56"
class="prc-src-BaseStyles-9LBd2"
data-color-mode="light"
data-dark-theme="dark"
data-light-theme="light"
Expand All @@ -13,7 +13,7 @@ exports[`AnchoredOverlay > should render consistently when open 1`] = `
aria-describedby=":rd:-loading-announcement"
aria-expanded="true"
aria-haspopup="true"
class="_ButtonBase_1h0a3_2"
class="prc-Button-ButtonBase-Eb8-K"
data-loading="false"
data-no-visuals="true"
data-size="medium"
Expand All @@ -23,12 +23,12 @@ exports[`AnchoredOverlay > should render consistently when open 1`] = `
type="button"
>
<span
class="_ButtonContent_1h0a3_101"
class="prc-Button-ButtonContent-KZ5Bz"
data-align="center"
data-component="buttonContent"
>
<span
class="_Label_1h0a3_128"
class="prc-Button-Label-B1e2-"
data-component="text"
>
Anchor Button
Expand All @@ -43,14 +43,14 @@ exports[`AnchoredOverlay > should render consistently when open 1`] = `
style="position: relative; z-index: 1;"
>
<div
class="_Overlay_1a2ug_11"
class="prc-Overlay-Overlay-ViJgm"
data-focus-trap="active"
data-height-auto=""
data-variant="anchored"
data-visibility-visible=""
data-width-auto=""
role="none"
style="left: 0px; top: 26.8438px;"
style="left: 0px; top: 36px;"
>
<span
aria-hidden="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
exports[`Breadcrumbs.Item > respects the "selected" prop 1`] = `
<a
aria-current="page"
class="_Item_tg8iv_12 selected _ItemSelected_tg8iv_53"
class="prc-Breadcrumbs-Item-V05wG selected prc-Breadcrumbs-ItemSelected-gKthY"
/>
`;
Loading
Loading