diff --git a/package-lock.json b/package-lock.json
index 352901f6ad7..695c5cc8f69 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -82,8 +82,8 @@
"react-dom": "^18.3.1"
},
"devDependencies": {
- "@primer/react": "38.22.0",
- "@primer/styled-react": "1.0.7",
+ "@primer/react": "38.23.0",
+ "@primer/styled-react": "1.0.8",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.3",
@@ -96,8 +96,8 @@
"name": "example-nextjs",
"version": "0.0.0",
"dependencies": {
- "@primer/react": "38.22.0",
- "@primer/styled-react": "1.0.7",
+ "@primer/react": "38.23.0",
+ "@primer/styled-react": "1.0.8",
"next": "^16.1.7",
"react": "^19.2.0",
"react-dom": "^19.2.0",
@@ -139,8 +139,8 @@
"version": "0.0.0",
"dependencies": {
"@primer/octicons-react": "^19.21.0",
- "@primer/react": "38.22.0",
- "@primer/styled-react": "1.0.7",
+ "@primer/react": "38.23.0",
+ "@primer/styled-react": "1.0.8",
"clsx": "^2.1.1",
"next": "^16.1.7",
"react": "^19.2.0",
@@ -7072,6 +7072,10 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/@primer/vitest-config": {
+ "resolved": "packages/vitest-config",
+ "link": true
+ },
"node_modules/@publint/pack": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@publint/pack/-/pack-0.1.2.tgz",
@@ -11666,7 +11670,6 @@
},
"node_modules/chalk": {
"version": "5.4.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
@@ -26686,6 +26689,20 @@
}
}
},
+ "node_modules/vitest-fail-on-console": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/vitest-fail-on-console/-/vitest-fail-on-console-0.10.1.tgz",
+ "integrity": "sha512-Xjy2SpgND547qSy0s0zYVnh1G/WyGtdjAbi4PFV8mkYRmTq+6NzRUJYdc08BHrw7HJLpO2kMxHFB8PWn7FOVsg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.4.1"
+ },
+ "peerDependencies": {
+ "@vitest/utils": ">=0.26.2",
+ "vite": ">=4.5.2",
+ "vitest": ">=0.26.2"
+ }
+ },
"node_modules/vitest/node_modules/@vitest/expect": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz",
@@ -27318,6 +27335,7 @@
"@babel/plugin-transform-runtime": "^7.29.0",
"@babel/preset-env": "^7.29.0",
"@babel/preset-typescript": "^7.28.5",
+ "@primer/vitest-config": "^0.0.0",
"@rollup/plugin-babel": "^6.1.0",
"@rollup/plugin-commonjs": "^29.0.0",
"@rollup/plugin-json": "^6.1.0",
@@ -27698,6 +27716,7 @@
"postcss-preset-env": "^10.1.3"
},
"devDependencies": {
+ "@primer/vitest-config": "^0.0.0",
"@types/postcss-mixins": "9.0.5",
"cssnano": "^7.0.7",
"postcss": "^8.4.41",
@@ -27711,7 +27730,7 @@
},
"packages/react": {
"name": "@primer/react",
- "version": "38.22.0",
+ "version": "38.23.0",
"license": "MIT",
"dependencies": {
"@github/mini-throttle": "^2.1.1",
@@ -27748,6 +27767,7 @@
"@figma/code-connect": "1.3.2",
"@primer/css": "^21.5.1",
"@primer/doc-gen": "^0.0.1",
+ "@primer/vitest-config": "^0.0.0",
"@rollup/plugin-babel": "6.1.0",
"@rollup/plugin-commonjs": "29.0.0",
"@rollup/plugin-json": "6.1.0",
@@ -28084,7 +28104,7 @@
},
"packages/styled-react": {
"name": "@primer/styled-react",
- "version": "1.0.7",
+ "version": "1.0.8",
"dependencies": {
"@styled-system/css": "^5.1.5",
"@styled-system/props": "^5.1.5",
@@ -28101,7 +28121,8 @@
"@babel/preset-react": "^7.28.5",
"@babel/preset-typescript": "^7.28.5",
"@primer/primitives": "10.x || 11.x",
- "@primer/react": "^38.22.0",
+ "@primer/react": "^38.23.0",
+ "@primer/vitest-config": "^0.0.0",
"@rollup/plugin-babel": "^6.1.0",
"@storybook/react-vite": "^10.3.3",
"@types/react": "18.3.11",
@@ -28250,6 +28271,13 @@
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
+ },
+ "packages/vitest-config": {
+ "name": "@primer/vitest-config",
+ "version": "0.0.0",
+ "dependencies": {
+ "vitest-fail-on-console": "^0.10.1"
+ }
}
}
}
diff --git a/packages/doc-gen/package.json b/packages/doc-gen/package.json
index 548f56e0865..e2e261c1490 100644
--- a/packages/doc-gen/package.json
+++ b/packages/doc-gen/package.json
@@ -39,6 +39,7 @@
"@babel/plugin-transform-runtime": "^7.29.0",
"@babel/preset-env": "^7.29.0",
"@babel/preset-typescript": "^7.28.5",
+ "@primer/vitest-config": "^0.0.0",
"@rollup/plugin-babel": "^6.1.0",
"@rollup/plugin-commonjs": "^29.0.0",
"@rollup/plugin-json": "^6.1.0",
diff --git a/packages/doc-gen/vitest.config.mts b/packages/doc-gen/vitest.config.mts
index 1f571e49350..5aed29b3f45 100644
--- a/packages/doc-gen/vitest.config.mts
+++ b/packages/doc-gen/vitest.config.mts
@@ -6,6 +6,7 @@ export default defineConfig({
},
test: {
environment: 'node',
+ setupFiles: ['@primer/vitest-config/setup'],
detectAsyncLeaks: true,
},
})
diff --git a/packages/postcss-preset-primer/package.json b/packages/postcss-preset-primer/package.json
index e4cd7dfec16..bc6ade9a93c 100644
--- a/packages/postcss-preset-primer/package.json
+++ b/packages/postcss-preset-primer/package.json
@@ -19,6 +19,7 @@
"postcss-preset-env": "^10.1.3"
},
"devDependencies": {
+ "@primer/vitest-config": "^0.0.0",
"@types/postcss-mixins": "9.0.5",
"cssnano": "^7.0.7",
"postcss": "^8.4.41",
diff --git a/packages/postcss-preset-primer/vitest.config.ts b/packages/postcss-preset-primer/vitest.config.ts
index 74213f595be..c699c977ba3 100644
--- a/packages/postcss-preset-primer/vitest.config.ts
+++ b/packages/postcss-preset-primer/vitest.config.ts
@@ -3,6 +3,7 @@ import {defineConfig} from 'vitest/config'
export default defineConfig({
test: {
environment: 'node',
+ setupFiles: ['@primer/vitest-config/setup'],
detectAsyncLeaks: true,
},
})
diff --git a/packages/react/package.json b/packages/react/package.json
index 665179de202..23957c3569b 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -108,6 +108,7 @@
"@figma/code-connect": "1.3.2",
"@primer/css": "^21.5.1",
"@primer/doc-gen": "^0.0.1",
+ "@primer/vitest-config": "^0.0.0",
"@rollup/plugin-babel": "6.1.0",
"@rollup/plugin-commonjs": "29.0.0",
"@rollup/plugin-json": "6.1.0",
diff --git a/packages/react/src/ActionList/Group.test.tsx b/packages/react/src/ActionList/Group.test.tsx
index 7d282da6296..2fc32e83df0 100644
--- a/packages/react/src/ActionList/Group.test.tsx
+++ b/packages/react/src/ActionList/Group.test.tsx
@@ -1,4 +1,4 @@
-import {describe, it, expect} from 'vitest'
+import {describe, it, expect, vi} from 'vitest'
import {render as HTMLRender} from '@testing-library/react'
import {PlusIcon} from '@primer/octicons-react'
import BaseStyles from '../BaseStyles'
@@ -22,22 +22,23 @@ describe('ActionList.Group', () => {
implementsClassName(ActionList.GroupHeading, classes.GroupHeading)
it('should throw an error when ActionList.GroupHeading has an `as` prop when it is used within ActionMenu context', async () => {
- expect(() =>
- HTMLRender(
-
-
- Trigger
-
-
-
- Group Heading
-
-
-
-
- ,
- ),
- ).toThrow(
+ expect.hasAssertions()
+ expectRenderError(
+ () =>
+ HTMLRender(
+
+
+ Trigger
+
+
+
+ Group Heading
+
+
+
+
+ ,
+ ),
"Looks like you are trying to set a heading level to a menu role. Group headings for menu type action lists are for representational purposes, and rendered as divs. Therefore they don't need a heading level.",
)
})
@@ -56,17 +57,18 @@ describe('ActionList.Group', () => {
expect(heading).toHaveTextContent('Group Heading')
})
it('should throw an error if ActionList.GroupHeading is used without an `as` prop when no role is specified (for list role)', async () => {
- expect(() =>
- HTMLRender(
-
- Heading
-
- Group Heading
- Item
-
- ,
- ),
- ).toThrow(
+ expect.hasAssertions()
+ expectRenderError(
+ () =>
+ HTMLRender(
+
+ Heading
+
+ Group Heading
+ Item
+
+ ,
+ ),
"You are setting a heading for a list, that requires a heading level. Please use 'as' prop to set a proper heading level.",
)
})
@@ -191,44 +193,59 @@ describe('ActionList.Group', () => {
})
it('throws when GroupHeading.TrailingAction is used inside an ActionMenu (menu role) and the feature flag is enabled', () => {
- expect(() =>
- HTMLRender(
-
-
-
- Trigger
-
-
-
-
- Group Heading
-
-
-
-
-
-
-
- ,
- ),
- ).toThrow(/can not be used inside an ActionList with an ARIA role of "menu"/)
+ expect.hasAssertions()
+ expectRenderError(
+ () =>
+ HTMLRender(
+
+
+
+ Trigger
+
+
+
+
+ Group Heading
+
+
+
+
+
+
+
+ ,
+ ),
+ /can not be used inside an ActionList with an ARIA role of "menu"/,
+ )
})
it('throws when GroupHeading.TrailingAction is used inside a listbox role and the feature flag is enabled', () => {
- expect(() =>
- HTMLRender(
-
-
-
-
- Group Heading
-
-
-
-
- ,
- ),
- ).toThrow(/can not be used inside an ActionList with an ARIA role of "listbox"/)
+ expect.hasAssertions()
+ expectRenderError(
+ () =>
+ HTMLRender(
+
+
+
+
+ Group Heading
+
+
+
+
+ ,
+ ),
+ /can not be used inside an ActionList with an ARIA role of "listbox"/,
+ )
})
})
})
+
+function expectRenderError(callback: () => void, error: string | RegExp) {
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
+ try {
+ expect(callback).toThrow(error)
+ } finally {
+ consoleError.mockRestore()
+ }
+}
diff --git a/packages/react/src/ActionList/Heading.test.tsx b/packages/react/src/ActionList/Heading.test.tsx
index 316d4bad06d..c41a366e17a 100644
--- a/packages/react/src/ActionList/Heading.test.tsx
+++ b/packages/react/src/ActionList/Heading.test.tsx
@@ -1,4 +1,4 @@
-import {describe, it, expect} from 'vitest'
+import {describe, it, expect, vi} from 'vitest'
import {render as HTMLRender} from '@testing-library/react'
import BaseStyles from '../BaseStyles'
import {ActionList} from '.'
@@ -42,22 +42,32 @@ describe('ActionList.Heading', () => {
})
it('should throw an error when ActionList.Heading is used within ActionMenu context', async () => {
- expect(() =>
- HTMLRender(
-
-
- Trigger
-
-
- Heading
- Item
-
-
-
- ,
- ),
- ).toThrow(
+ expect.hasAssertions()
+ expectRenderError(
+ () =>
+ HTMLRender(
+
+
+ Trigger
+
+
+ Heading
+ Item
+
+
+
+ ,
+ ),
"ActionList.Heading shouldn't be used within an ActionMenu container. Menus are labelled by the menu button's name.",
)
})
})
+
+function expectRenderError(callback: () => void, error: string | RegExp) {
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
+ try {
+ expect(callback).toThrow(error)
+ } finally {
+ consoleError.mockRestore()
+ }
+}
diff --git a/packages/react/src/ActionMenu/ActionMenu.test.tsx b/packages/react/src/ActionMenu/ActionMenu.test.tsx
index 09303b7923b..2533711a6f4 100644
--- a/packages/react/src/ActionMenu/ActionMenu.test.tsx
+++ b/packages/react/src/ActionMenu/ActionMenu.test.tsx
@@ -340,9 +340,7 @@ describe('ActionMenu', () => {
const button = component.getByRole('button')
const user = userEvent.setup()
- await act(async () => {
- await user.click(button)
- })
+ await user.click(button)
expect(component.queryByRole('menu')).toBeInTheDocument()
const menuItems = component.getAllByRole('menuitem')
@@ -355,13 +353,11 @@ describe('ActionMenu', () => {
await user.keyboard('{ArrowDown}')
expect(menuItems[1]).toEqual(document.activeElement)
- await act(async () => {
- // TODO: Removed one ArrowDown to account for the focus trap starting at the second element
- // await user.keyboard('{ArrowDown}')
- await user.keyboard('{ArrowDown}')
- await user.keyboard('{ArrowDown}')
- await user.keyboard('{ArrowDown}')
- })
+ // TODO: Removed one ArrowDown to account for the focus trap starting at the second element
+ // await user.keyboard('{ArrowDown}')
+ await user.keyboard('{ArrowDown}')
+ await user.keyboard('{ArrowDown}')
+ await user.keyboard('{ArrowDown}')
expect(menuItems[menuItems.length - 1]).toEqual(document.activeElement) // last elememt
await user.keyboard('{ArrowDown}')
diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx
index 255c771c6b3..b920cc5b0b7 100644
--- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx
+++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx
@@ -1,7 +1,7 @@
import {act, createRef, useCallback, useRef, useState} from 'react'
import {describe, expect, it, vi} from 'vitest'
-import {render} from '@testing-library/react'
-import {userEvent} from 'vitest/browser'
+import {fireEvent, render} from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
import {AnchoredOverlay} from '../AnchoredOverlay'
import {Button} from '../Button'
import BaseStyles from '../BaseStyles'
@@ -104,9 +104,7 @@ describe.each([true, false])(
/>,
)
const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="true"]')!
- await act(async () => {
- await userEvent.click(anchor)
- })
+ await userEvent.click(anchor)
expect(mockOpenCallback).toHaveBeenCalledTimes(1)
expect(mockOpenCallback).toHaveBeenCalledWith('anchor-click')
@@ -124,9 +122,7 @@ describe.each([true, false])(
/>,
)
const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="true"]')!
- await act(async () => {
- await userEvent.type(anchor, '{Space}')
- })
+ fireEvent.keyDown(anchor, {key: ' ', code: 'Space'})
expect(mockOpenCallback).toHaveBeenCalledTimes(1)
expect(mockOpenCallback).toHaveBeenCalledWith('anchor-key-press')
@@ -144,9 +140,7 @@ describe.each([true, false])(
withCSSAnchorPositioningFeatureFlag={withCSSAnchorPositioningFeatureFlag}
/>,
)
- await act(async () => {
- await userEvent.click(anchoredOverlay.baseElement)
- })
+ await userEvent.click(anchoredOverlay.baseElement)
expect(mockOpenCallback).toHaveBeenCalledTimes(0)
expect(mockCloseCallback).toHaveBeenCalledTimes(1)
@@ -166,9 +160,7 @@ describe.each([true, false])(
/>,
)
- await act(async () => {
- await userEvent.keyboard('{Escape}')
- })
+ await userEvent.keyboard('{Escape}')
expect(mockOpenCallback).toHaveBeenCalledTimes(0)
expect(mockCloseCallback).toHaveBeenCalledTimes(1)
@@ -185,9 +177,7 @@ describe.each([true, false])(
/>,
)
- await act(async () => {
- await userEvent.keyboard('{Escape}')
- })
+ await userEvent.keyboard('{Escape}')
expect(mockPositionChangeCallback).toHaveBeenCalled()
expect(mockPositionChangeCallback).toHaveBeenCalledWith({
@@ -309,6 +299,7 @@ describe('AnchoredOverlay feature flag specific behavior', () => {
})
it('should set popover="manual" on overlay when renderAs is "popover"', () => {
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
const {baseElement} = render(
@@ -317,9 +308,11 @@ describe('AnchoredOverlay feature flag specific behavior', () => {
const overlay = baseElement.querySelector('[data-component="AnchoredOverlay"]')
expect(overlay).toHaveAttribute('popover', 'manual')
+ consoleError.mockRestore()
})
it('should set popovertarget on anchor when renderAs is "popover"', () => {
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
const {baseElement} = render(
@@ -330,6 +323,7 @@ describe('AnchoredOverlay feature flag specific behavior', () => {
const overlay = baseElement.querySelector('[data-component="AnchoredOverlay"]')
expect(anchor).toHaveAttribute('popovertarget')
expect(anchor!.getAttribute('popovertarget')).toBe(overlay!.getAttribute('id'))
+ consoleError.mockRestore()
})
it('should not set popover attribute on overlay when renderAs is "portal"', () => {
diff --git a/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx b/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx
index 25dcbc5f8fc..76c221ff46f 100644
--- a/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx
+++ b/packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx
@@ -1,5 +1,5 @@
import Breadcrumbs from '..'
-import {render as HTMLRender, screen, waitFor, within} from '@testing-library/react'
+import {act, render as HTMLRender, screen, waitFor, within} from '@testing-library/react'
import {describe, expect, it, vi} from 'vitest'
import userEvent from '@testing-library/user-event'
import {FeatureFlags} from '../../FeatureFlags'
@@ -243,30 +243,34 @@ describe('Breadcrumbs', () => {
)
expect(resizeCallback).toBeDefined()
+ const callback = resizeCallback
+ if (!callback) {
+ throw new Error('ResizeObserver callback was not registered')
+ }
// Initially should show overflow menu for >5 items
expect(screen.getByRole('button', {name: /more breadcrumb items/i})).toBeInTheDocument()
// Simulate a wide container resize
- if (resizeCallback) {
- resizeCallback([
+ act(() => {
+ callback([
{
contentRect: {width: 800, height: 40},
} as ResizeObserverEntry,
])
- }
+ })
// Should still have overflow menu for 6 items (>5 rule)
expect(screen.getByRole('button', {name: /more breadcrumb items/i})).toBeInTheDocument()
// Simulate a narrow container resize
- if (resizeCallback) {
- resizeCallback([
+ act(() => {
+ callback([
{
contentRect: {width: 250, height: 40},
} as ResizeObserverEntry,
])
- }
+ })
// Should maintain overflow menu for narrow container
expect(screen.getByRole('button', {name: /more breadcrumb items/i})).toBeInTheDocument()
@@ -303,6 +307,10 @@ describe('Breadcrumbs', () => {
)
expect(resizeCallback).toBeDefined()
+ const callback = resizeCallback
+ if (!callback) {
+ throw new Error('ResizeObserver callback was not registered')
+ }
// Initially should show overflow menu for >5 items
const menuButton = screen.getByRole('button', {name: /more breadcrumb items/i})
@@ -327,29 +335,29 @@ describe('Breadcrumbs', () => {
// Close menu by clicking outside
await user.click(document.body)
await waitFor(() => {
- expect
+ expect(menuButton).toHaveAttribute('aria-expanded', 'false')
})
// Simulate a very narrow container resize that would affect overflow calculation
- if (resizeCallback) {
- resizeCallback([
+ act(() => {
+ callback([
{
contentRect: {width: 200, height: 40},
} as ResizeObserverEntry,
])
- }
+ })
// Menu button should still be present
expect(screen.getByRole('button', {name: /more breadcrumb items/i})).toBeInTheDocument()
// Simulate a very wide container resize
- if (resizeCallback) {
- resizeCallback([
+ act(() => {
+ callback([
{
contentRect: {width: 1200, height: 40},
} as ResizeObserverEntry,
])
- }
+ })
// Menu button should still be present (7 items > 5)
expect(screen.getByRole('button', {name: /more breadcrumb items/i})).toBeInTheDocument()
@@ -506,7 +514,9 @@ describe('Breadcrumbs', () => {
const menuButton = screen.getByRole('button', {name: /more breadcrumb items/i})
// Focus the menu button
- menuButton.focus()
+ act(() => {
+ menuButton.focus()
+ })
expect(menuButton).toHaveFocus()
// Open menu with Enter key
@@ -521,7 +531,9 @@ describe('Breadcrumbs', () => {
await user.keyboard('{Escape}')
// Verify focus returns to button
- expect(menuButton).toHaveFocus()
+ await waitFor(() => {
+ expect(menuButton).toHaveFocus()
+ })
})
})
diff --git a/packages/react/src/CheckboxGroup/CheckboxGroup.test.tsx b/packages/react/src/CheckboxGroup/CheckboxGroup.test.tsx
index f752ae2d5c9..136b221e09f 100644
--- a/packages/react/src/CheckboxGroup/CheckboxGroup.test.tsx
+++ b/packages/react/src/CheckboxGroup/CheckboxGroup.test.tsx
@@ -6,7 +6,14 @@ import {implementsClassName} from '../utils/testing'
import classes from '../internal/components/CheckboxOrRadioGroup/CheckboxOrRadioGroup.module.css'
describe('CheckboxGroup', () => {
- implementsClassName(CheckboxGroup, classes.GroupFieldset)
+ implementsClassName(
+ props => (
+
+ Choices
+
+ ),
+ classes.GroupFieldset,
+ )
implementsClassName(CheckboxGroup.Caption, classes.CheckboxOrRadioGroupCaption)
implementsClassName(CheckboxGroup.Label, classes.RadioGroupLabel)
const mockWarningFn = vi.fn()
diff --git a/packages/react/src/CircleBadge/CircleBadge.test.tsx b/packages/react/src/CircleBadge/CircleBadge.test.tsx
index 32284a3d06d..c4b0eba81c3 100644
--- a/packages/react/src/CircleBadge/CircleBadge.test.tsx
+++ b/packages/react/src/CircleBadge/CircleBadge.test.tsx
@@ -1,7 +1,7 @@
import CircleBadge from './CircleBadge'
import {CheckIcon} from '@primer/octicons-react'
import {render as HTMLRender} from '@testing-library/react'
-import {describe, expect, it} from 'vitest'
+import {describe, expect, it, vi} from 'vitest'
import {implementsClassName} from '../utils/testing'
import classes from './CircleBadge.module.css'
@@ -16,8 +16,17 @@ describe('CircleBadge', () => {
})
it('respects the inline prop', () => {
- const {container} = HTMLRender()
- expect(container.firstChild).toMatchSnapshot()
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
+ try {
+ const {container} = HTMLRender()
+ expect(container.firstChild).toMatchSnapshot()
+ const messages = consoleError.mock.calls.map(args => args.map(String).join(' '))
+ expect(messages).toHaveLength(1)
+ expect(messages[0]).toContain('non-boolean attribute')
+ expect(messages[0]).toContain('inline')
+ } finally {
+ consoleError.mockRestore()
+ }
})
it('respects the variant prop', () => {
diff --git a/packages/react/src/ConfirmationDialog/ConfirmationDialog.test.tsx b/packages/react/src/ConfirmationDialog/ConfirmationDialog.test.tsx
index eeb91d7e9fd..748014d6944 100644
--- a/packages/react/src/ConfirmationDialog/ConfirmationDialog.test.tsx
+++ b/packages/react/src/ConfirmationDialog/ConfirmationDialog.test.tsx
@@ -152,6 +152,7 @@ describe('ConfirmationDialog', () => {
})
it('supports nested `focusTrap`s', async () => {
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
const {getByText, getByRole} = render()
fireEvent.click(getByText('Show menu'))
@@ -159,6 +160,7 @@ describe('ConfirmationDialog', () => {
expect(getByRole('button', {name: 'Primary'})).toEqual(document.activeElement)
expect(getByRole('button', {name: 'Secondary'})).not.toEqual(document.activeElement)
+ consoleError.mockRestore()
})
it('accepts a className prop', async () => {
diff --git a/packages/react/src/DataTable/__tests__/Pagination.test.tsx b/packages/react/src/DataTable/__tests__/Pagination.test.tsx
index 90432a80063..6a70cbde0b0 100644
--- a/packages/react/src/DataTable/__tests__/Pagination.test.tsx
+++ b/packages/react/src/DataTable/__tests__/Pagination.test.tsx
@@ -1,7 +1,7 @@
import {page} from 'vitest/browser'
import {beforeEach, describe, expect, it, vi} from 'vitest'
import {Pagination} from '../Pagination'
-import {render, screen} from '@testing-library/react'
+import {render, screen, waitFor} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
describe('Table.Pagination', () => {
@@ -43,6 +43,7 @@ describe('Table.Pagination', () => {
it('should warn if `defaultPageIndex` is not a valid `pageIndex`', () => {
const spy = vi.spyOn(console, 'warn').mockImplementation(() => {})
render()
+ expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(
'Warning:',
expect.stringMatching(
@@ -50,6 +51,7 @@ describe('Table.Pagination', () => {
' expected `defaultPageIndex` to be less than the total number of pages. Instead, received a `defaultPageIndex` of 4 with 4 total pages.',
),
)
+ spy.mockRestore()
})
it('should set the `id` prop on the rendered navigation landmark', () => {
@@ -103,7 +105,9 @@ describe('Table.Pagination', () => {
rerender(
,
)
- expect(getPageRange()).toEqual('11 through 15 of 300')
+ await waitFor(() => {
+ expect(getPageRange()).toEqual('11 through 15 of 300')
+ })
expect(getCurrentPage()).toEqual(getPage(2))
expect(getInvalidPages()).toHaveLength(0)
expect(onChange).toHaveBeenCalledWith({
@@ -296,7 +300,9 @@ describe('Table.Pagination', () => {
rerender(
,
)
- expect(getPageRange()).toEqual('1 through 5 of 300')
+ await waitFor(() => {
+ expect(getPageRange()).toEqual('1 through 5 of 300')
+ })
expect(getCurrentPage()).toEqual(getPage(0))
expect(getInvalidPages()).toHaveLength(0)
expect(onChange).toHaveBeenCalledWith({
@@ -361,7 +367,9 @@ describe('Table.Pagination', () => {
rerender(
,
)
- expect(getPageRange()).toEqual('1 through 5 of 300')
+ await waitFor(() => {
+ expect(getPageRange()).toEqual('1 through 5 of 300')
+ })
expect(getFirstPage()).toEqual(getCurrentPage())
expect(getInvalidPages()).toHaveLength(0)
expect(onChange).toHaveBeenCalledWith({
diff --git a/packages/react/src/DataTable/__tests__/Table.test.tsx b/packages/react/src/DataTable/__tests__/Table.test.tsx
index d7c5d126472..99e76bb43e2 100644
--- a/packages/react/src/DataTable/__tests__/Table.test.tsx
+++ b/packages/react/src/DataTable/__tests__/Table.test.tsx
@@ -219,7 +219,18 @@ describe('Table', () => {
})
describe('Table.Cell', () => {
- implementsClassName(Table.Cell, classes.TableCell)
+ implementsClassName(
+ props => (
+
+ ),
+ classes.TableCell,
+ )
it('should set the element to a when `scope` is defined', () => {
render(
diff --git a/packages/react/src/Details/__tests__/Details.test.tsx b/packages/react/src/Details/__tests__/Details.test.tsx
index 61afbccec04..964b18fff63 100644
--- a/packages/react/src/Details/__tests__/Details.test.tsx
+++ b/packages/react/src/Details/__tests__/Details.test.tsx
@@ -7,7 +7,14 @@ import {implementsClassName} from '../../utils/testing'
import classes from '../Details.module.css'
describe('Details', () => {
- implementsClassName(Details, classes.Details)
+ implementsClassName(
+ props => (
+
+ Summary
+
+ ),
+ classes.Details,
+ )
implementsClassName(Details.Summary)
it('Toggles when you click outside', async () => {
const Component = () => {
diff --git a/packages/react/src/FormControl/__tests__/FormControl.test.tsx b/packages/react/src/FormControl/__tests__/FormControl.test.tsx
index bd3141abdd6..d8324b0d8ad 100644
--- a/packages/react/src/FormControl/__tests__/FormControl.test.tsx
+++ b/packages/react/src/FormControl/__tests__/FormControl.test.tsx
@@ -59,8 +59,24 @@ const WrappedValidationComponent: FCWithSlotMarker |