From 269434b26826a426100f5c2d6b8b57b67d6e44f4 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Sat, 22 Nov 2025 00:01:33 -0500 Subject: [PATCH 01/29] chore: add className testing util: --- .../AnchoredOverlay/AnchoredOverlay.test.tsx | 12 +++++++++- packages/react/src/utils/testing.tsx | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 packages/react/src/utils/testing.tsx diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx index 18533837f3e..0f54bf7cea0 100644 --- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx +++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx @@ -1,16 +1,18 @@ import {act, createRef, useCallback, useRef, useState} from 'react' import {describe, expect, it, vi} from 'vitest' -import {render} from '@testing-library/react' +import {render, type RenderResult} from '@testing-library/react' import {userEvent} from 'vitest/browser' import {AnchoredOverlay} from '../AnchoredOverlay' import {Button} from '../Button' import BaseStyles from '../BaseStyles' import type {AnchorPosition} from '@primer/behaviors' +import {implementsClassNameBehavior} from '../utils/testing' type TestComponentSettings = { initiallyOpen?: boolean onOpenCallback?: (gesture: string) => void onCloseCallback?: (gesture: string) => void onPositionChange?: ({position}: {position: AnchorPosition}) => void + className?: string } const AnchoredOverlayTestComponent = ({ @@ -18,6 +20,7 @@ const AnchoredOverlayTestComponent = ({ onOpenCallback, onCloseCallback, onPositionChange, + className, }: TestComponentSettings = {}) => { const [open, setOpen] = useState(initiallyOpen) const onOpen = useCallback( @@ -42,6 +45,7 @@ const AnchoredOverlayTestComponent = ({ onClose={onClose} renderAnchor={props => } onPositionChange={onPositionChange} + className={className} > @@ -50,6 +54,12 @@ const AnchoredOverlayTestComponent = ({ } describe('AnchoredOverlay', () => { + implementsClassNameBehavior( + AnchoredOverlay, + 'prc-Overlay-Overlay-ViJgm', + component => component.container.firstChild!.childNodes[1].firstChild?.firstChild as HTMLElement, + props => , + ) it('should call onOpen when the anchor is clicked', async () => { const mockOpenCallback = vi.fn() const mockCloseCallback = vi.fn() diff --git a/packages/react/src/utils/testing.tsx b/packages/react/src/utils/testing.tsx new file mode 100644 index 00000000000..61d8b3c1b86 --- /dev/null +++ b/packages/react/src/utils/testing.tsx @@ -0,0 +1,24 @@ +import {type RenderResult, render as HTMLRender} from '@testing-library/react' +import {it, expect} from 'vitest' + +export function implementsClassNameBehavior( + Component: React.ComponentType, + baseClassName?: string, + getClassNameElement: (component: RenderResult) => HTMLElement = component => + component.container.firstChild as HTMLElement, + renderComponent: (props: any) => React.JSX.Element = props => , +) { + it('renders with the base className', () => { + const component = HTMLRender(renderComponent({})) + if (baseClassName) { + expect(getClassNameElement(component)).toHaveClass(baseClassName) + } + }) + it('renders with the custom className', () => { + const component = HTMLRender(renderComponent({className: 'test-class'})) + expect(getClassNameElement(component)).toHaveClass('test-class') + if (baseClassName) { + expect(getClassNameElement(component)).toHaveClass(baseClassName) + } + }) +} From 4034aca7db1f3f1ecf23ca3efa89638de2a7cf4c Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Mon, 24 Nov 2025 22:17:19 -0500 Subject: [PATCH 02/29] lint fixes --- packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx | 2 +- packages/react/src/utils/testing.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx index 0f54bf7cea0..f72541444d0 100644 --- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx +++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx @@ -1,6 +1,6 @@ import {act, createRef, useCallback, useRef, useState} from 'react' import {describe, expect, it, vi} from 'vitest' -import {render, type RenderResult} from '@testing-library/react' +import {render} from '@testing-library/react' import {userEvent} from 'vitest/browser' import {AnchoredOverlay} from '../AnchoredOverlay' import {Button} from '../Button' diff --git a/packages/react/src/utils/testing.tsx b/packages/react/src/utils/testing.tsx index 61d8b3c1b86..cab6111b115 100644 --- a/packages/react/src/utils/testing.tsx +++ b/packages/react/src/utils/testing.tsx @@ -1,12 +1,12 @@ import {type RenderResult, render as HTMLRender} from '@testing-library/react' import {it, expect} from 'vitest' -export function implementsClassNameBehavior( - Component: React.ComponentType, +export function implementsClassNameBehavior( + Component: React.ComponentType, baseClassName?: string, getClassNameElement: (component: RenderResult) => HTMLElement = component => component.container.firstChild as HTMLElement, - renderComponent: (props: any) => React.JSX.Element = props => , + renderComponent: (props: {className?: string}) => React.JSX.Element = props => , ) { it('renders with the base className', () => { const component = HTMLRender(renderComponent({})) From 69f163cfb7b8395a293fa92004fd1e7051828094 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Wed, 3 Dec 2025 22:12:36 -0500 Subject: [PATCH 03/29] review comments --- .../react/src/AnchoredOverlay/AnchoredOverlay.test.tsx | 9 ++++++--- packages/react/src/utils/testing.tsx | 8 +------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx index f72541444d0..25c4df5ce3e 100644 --- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx +++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx @@ -6,7 +6,10 @@ import {AnchoredOverlay} from '../AnchoredOverlay' import {Button} from '../Button' import BaseStyles from '../BaseStyles' import type {AnchorPosition} from '@primer/behaviors' -import {implementsClassNameBehavior} from '../utils/testing' +import {implementsClassName} from '../utils/testing' + +import overlayClasses from '../Overlay/Overlay.module.css' + type TestComponentSettings = { initiallyOpen?: boolean onOpenCallback?: (gesture: string) => void @@ -54,9 +57,9 @@ const AnchoredOverlayTestComponent = ({ } describe('AnchoredOverlay', () => { - implementsClassNameBehavior( + implementsClassName( AnchoredOverlay, - 'prc-Overlay-Overlay-ViJgm', + overlayClasses.Overlay, component => component.container.firstChild!.childNodes[1].firstChild?.firstChild as HTMLElement, props => , ) diff --git a/packages/react/src/utils/testing.tsx b/packages/react/src/utils/testing.tsx index cab6111b115..35ef434caab 100644 --- a/packages/react/src/utils/testing.tsx +++ b/packages/react/src/utils/testing.tsx @@ -1,19 +1,13 @@ import {type RenderResult, render as HTMLRender} from '@testing-library/react' import {it, expect} from 'vitest' -export function implementsClassNameBehavior( +export function implementsClassName( Component: React.ComponentType, baseClassName?: string, getClassNameElement: (component: RenderResult) => HTMLElement = component => component.container.firstChild as HTMLElement, renderComponent: (props: {className?: string}) => React.JSX.Element = props => , ) { - it('renders with the base className', () => { - const component = HTMLRender(renderComponent({})) - if (baseClassName) { - expect(getClassNameElement(component)).toHaveClass(baseClassName) - } - }) it('renders with the custom className', () => { const component = HTMLRender(renderComponent({className: 'test-class'})) expect(getClassNameElement(component)).toHaveClass('test-class') From 82c72dd213fbbbe0872f66f5a2faba86852de66c Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Wed, 3 Dec 2025 22:23:39 -0500 Subject: [PATCH 04/29] add CI to enforce className test --- .github/workflows/ci.yml | 2 ++ package.json | 1 + script/check-classname-tests | 27 +++++++++++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100755 script/check-classname-tests diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3a34ba35d6..aabd3bf896e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,8 @@ jobs: run: npm run lint:md - name: Lint npm packages run: npx turbo lint:npm + - name: Check className test coverage + run: npm run test:classname-coverage test: runs-on: ubuntu-latest diff --git a/package.json b/package.json index 3dd9aaa117f..144c0156f59 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "test": "vitest", "test:type-check": "tsc --noEmit", "test:update": "npm run test -- -u", + "test:classname-coverage": "script/check-classname-tests", "type-check": "tsc --noEmit && turbo type-check", "release": "npm run build && changeset publish", "reset": "script/reset", diff --git a/script/check-classname-tests b/script/check-classname-tests new file mode 100755 index 00000000000..17e34429b37 --- /dev/null +++ b/script/check-classname-tests @@ -0,0 +1,27 @@ +#!/bin/bash + +# Check for implementsClassName in component test files + +echo "Checking for implementsClassName in component test files..." + +# Find all .test.tsx files in src/ (excluding utils and __tests__ directories) +test_files=$(find packages/react/src -name "*.test.tsx" -not -path "*/utils/*" -not -path "*/__tests__/*") + +missing_tests=() + +for file in $test_files; do + # Check if file imports a component (has relative import) and doesn't have implementsClassName + if grep -q "from '\.\.\/" "$file" && ! grep -q "implementsClassName" "$file"; then + missing_tests+=("$file") + fi +done + +if [ ${#missing_tests[@]} -gt 0 ]; then + echo "❌ The following component test files are missing implementsClassName:" + printf '%s\n' "${missing_tests[@]}" + echo "" + echo "Please add implementsClassName test to ensure className prop works correctly." + exit 1 +fi + +echo "✅ All component test files include implementsClassName" \ No newline at end of file From bfe79ca5aa139cc9aa29bc1d82ab4f106fd5fde3 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Wed, 3 Dec 2025 22:35:55 -0500 Subject: [PATCH 05/29] cleanup! --- .../AnchoredOverlay/AnchoredOverlay.test.tsx | 7 +------ packages/react/src/utils/testing.tsx | 20 +++++++++---------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx index 25c4df5ce3e..279bcc112d1 100644 --- a/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx +++ b/packages/react/src/AnchoredOverlay/AnchoredOverlay.test.tsx @@ -57,12 +57,7 @@ const AnchoredOverlayTestComponent = ({ } describe('AnchoredOverlay', () => { - implementsClassName( - AnchoredOverlay, - overlayClasses.Overlay, - component => component.container.firstChild!.childNodes[1].firstChild?.firstChild as HTMLElement, - props => , - ) + implementsClassName(props => , overlayClasses.Overlay) it('should call onOpen when the anchor is clicked', async () => { const mockOpenCallback = vi.fn() const mockCloseCallback = vi.fn() diff --git a/packages/react/src/utils/testing.tsx b/packages/react/src/utils/testing.tsx index 35ef434caab..c6cb8ee01cb 100644 --- a/packages/react/src/utils/testing.tsx +++ b/packages/react/src/utils/testing.tsx @@ -1,18 +1,16 @@ -import {type RenderResult, render as HTMLRender} from '@testing-library/react' +import {render as HTMLRender} from '@testing-library/react' import {it, expect} from 'vitest' -export function implementsClassName( - Component: React.ComponentType, - baseClassName?: string, - getClassNameElement: (component: RenderResult) => HTMLElement = component => - component.container.firstChild as HTMLElement, - renderComponent: (props: {className?: string}) => React.JSX.Element = props => , -) { +export function implementsClassName(Component: React.ElementType, baseClassName?: string) { it('renders with the custom className', () => { - const component = HTMLRender(renderComponent({className: 'test-class'})) - expect(getClassNameElement(component)).toHaveClass('test-class') + const component = HTMLRender() if (baseClassName) { - expect(getClassNameElement(component)).toHaveClass(baseClassName) + const baseElement = component.container.getElementsByClassName(baseClassName) + expect(baseElement).toHaveLength(1) + expect(baseElement[0]).toHaveClass('test-class') + } else { + const classNameElement = component.container.getElementsByClassName('test-class') + expect(classNameElement).toHaveLength(1) } }) } From 42223c3c9f47fd49fff60ab4762dcd81cd6a34a5 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Tue, 9 Dec 2025 15:05:25 -0500 Subject: [PATCH 06/29] convert script to node --- package-lock.json | 2 +- package.json | 2 +- script/check-classname-tests | 27 ------------- script/check-classname-tests.mjs | 67 +++++++++++++++++++++++++++++++ script/class-name-test-status.mts | 0 5 files changed, 69 insertions(+), 29 deletions(-) delete mode 100755 script/check-classname-tests create mode 100755 script/check-classname-tests.mjs delete mode 100644 script/class-name-test-status.mts diff --git a/package-lock.json b/package-lock.json index fe53cdf279b..1ff70c92ed2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27227,7 +27227,7 @@ "@github/tab-container-element": "^4.8.2", "@lit-labs/react": "1.2.1", "@oddbird/popover-polyfill": "^0.5.2", - "@primer/behaviors": "1.9.0", + "@primer/behaviors": "^1.9.0", "@primer/live-region-element": "^0.7.1", "@primer/octicons-react": "^19.13.0", "@primer/primitives": "10.x || 11.x", diff --git a/package.json b/package.json index dfd947a149a..1848a43c52e 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "test": "vitest", "test:type-check": "tsc --noEmit", "test:update": "npm run test -- -u", - "test:classname-coverage": "script/check-classname-tests", + "test:classname-coverage": "node script/check-classname-tests.mjs", "type-check": "tsc --noEmit && turbo type-check", "release": "npm run build && changeset publish", "reset": "script/reset", diff --git a/script/check-classname-tests b/script/check-classname-tests deleted file mode 100755 index 17e34429b37..00000000000 --- a/script/check-classname-tests +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Check for implementsClassName in component test files - -echo "Checking for implementsClassName in component test files..." - -# Find all .test.tsx files in src/ (excluding utils and __tests__ directories) -test_files=$(find packages/react/src -name "*.test.tsx" -not -path "*/utils/*" -not -path "*/__tests__/*") - -missing_tests=() - -for file in $test_files; do - # Check if file imports a component (has relative import) and doesn't have implementsClassName - if grep -q "from '\.\.\/" "$file" && ! grep -q "implementsClassName" "$file"; then - missing_tests+=("$file") - fi -done - -if [ ${#missing_tests[@]} -gt 0 ]; then - echo "❌ The following component test files are missing implementsClassName:" - printf '%s\n' "${missing_tests[@]}" - echo "" - echo "Please add implementsClassName test to ensure className prop works correctly." - exit 1 -fi - -echo "✅ All component test files include implementsClassName" \ No newline at end of file diff --git a/script/check-classname-tests.mjs b/script/check-classname-tests.mjs new file mode 100755 index 00000000000..5a30466f756 --- /dev/null +++ b/script/check-classname-tests.mjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node + +import {readFileSync, readdirSync, statSync} from 'fs' +import {join, dirname} from 'path' +import {fileURLToPath} from 'url' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) + +function getAllTestFiles(dir, files = []) { + const items = readdirSync(dir) + + for (const item of items) { + const fullPath = join(dir, item) + const stat = statSync(fullPath) + + if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') { + // Skip utils and __tests__ directories + if (item !== 'utils' && item !== '__tests__') { + getAllTestFiles(fullPath, files) + } + } else if (stat.isFile() && item.endsWith('.test.tsx')) { + files.push(fullPath) + } + } + + return files +} + +function main() { + console.log('Checking for implementsClassName in component test files...') + + const projectRoot = join(__dirname, '..') + const srcDir = join(projectRoot, 'packages/react/src') + const testFiles = getAllTestFiles(srcDir) + const missingTests = [] + + for (const testFile of testFiles) { + try { + const content = readFileSync(testFile, 'utf-8') + + // Check if file imports a component (has relative import) and doesn't have implementsClassName + const hasRelativeImport = content.includes("from '../") + const hasImplementsClassName = content.includes('implementsClassName') + + if (hasRelativeImport && !hasImplementsClassName) { + // Make path relative to project root for cleaner output + const relativePath = testFile.replace(projectRoot + '/', '') + missingTests.push(relativePath) + } + } catch (error) { + console.error(`Error reading file ${testFile}:`, error.message) + } + } + + if (missingTests.length > 0) { + console.log('❌ The following component test files are missing implementsClassName:') + missingTests.forEach(file => console.log(file)) + console.log('') + console.log('Please add implementsClassName test to ensure className prop works correctly.') + process.exit(1) + } + + console.log('✅ All component test files include implementsClassName') +} + +main() diff --git a/script/class-name-test-status.mts b/script/class-name-test-status.mts deleted file mode 100644 index e69de29bb2d..00000000000 From 67216ae81aaa85dd9fdbe7c2620e379dcd69d385 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Tue, 9 Dec 2025 15:52:01 -0500 Subject: [PATCH 07/29] add more className utils --- packages/react/src/ActionList/Group.test.tsx | 13 +++++++++++++ packages/react/src/ActionList/Heading.test.tsx | 13 +++++++++++++ packages/react/src/Avatar/Avatar.test.tsx | 4 ++++ packages/react/src/Banner/Banner.test.tsx | 9 ++++----- packages/react/src/Blankslate/Blankslate.test.tsx | 7 +++---- script/check-classname-tests.mjs | 2 +- 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/packages/react/src/ActionList/Group.test.tsx b/packages/react/src/ActionList/Group.test.tsx index 2e3fcc6b9d4..77e5758b421 100644 --- a/packages/react/src/ActionList/Group.test.tsx +++ b/packages/react/src/ActionList/Group.test.tsx @@ -3,8 +3,21 @@ import {render as HTMLRender} from '@testing-library/react' import BaseStyles from '../BaseStyles' import {ActionList} from '.' import {ActionMenu} from '..' +import {implementsClassName} from '../utils/testing' +import classes from './Group.module.css' describe('ActionList.Group', () => { + implementsClassName( + props => ( + + + item + + + ), + classes.Group, + ) + it('should throw an error when ActionList.GroupHeading has an `as` prop when it is used within ActionMenu context', async () => { expect(() => HTMLRender( diff --git a/packages/react/src/ActionList/Heading.test.tsx b/packages/react/src/ActionList/Heading.test.tsx index 8227f229630..df96390c574 100644 --- a/packages/react/src/ActionList/Heading.test.tsx +++ b/packages/react/src/ActionList/Heading.test.tsx @@ -3,8 +3,21 @@ import {render as HTMLRender} from '@testing-library/react' import BaseStyles from '../BaseStyles' import {ActionList} from '.' import {ActionMenu} from '..' +import {implementsClassName} from '../utils/testing' +import classes from './Heading.module.css' describe('ActionList.Heading', () => { + implementsClassName( + props => ( + + + Heading + + + ), + classes.ActionListHeader, + ) + it('should render the ActionList.Heading component as a heading with the given heading level', async () => { const container = HTMLRender( diff --git a/packages/react/src/Avatar/Avatar.test.tsx b/packages/react/src/Avatar/Avatar.test.tsx index 113b656d470..c4aacd6ef8c 100644 --- a/packages/react/src/Avatar/Avatar.test.tsx +++ b/packages/react/src/Avatar/Avatar.test.tsx @@ -1,8 +1,12 @@ import {describe, expect, it} from 'vitest' import {render, screen} from '@testing-library/react' import Avatar from '../Avatar' +import {implementsClassName} from '../utils/testing' +import classes from './Avatar.module.css' describe('Avatar', () => { + implementsClassName(Avatar, classes.Avatar) + it('should support `className` on the outermost element', () => { const Element = () => expect(render().container.firstChild).toHaveClass('test-class-name') diff --git a/packages/react/src/Banner/Banner.test.tsx b/packages/react/src/Banner/Banner.test.tsx index bbce0ca0808..1e6bebe38ce 100644 --- a/packages/react/src/Banner/Banner.test.tsx +++ b/packages/react/src/Banner/Banner.test.tsx @@ -2,19 +2,18 @@ import {describe, expect, it, vi} from 'vitest' import {render, screen} from '@testing-library/react' import userEvent from '@testing-library/user-event' import {Banner} from '../Banner' +import {implementsClassName} from '../utils/testing' +import classes from './Banner.module.css' describe('Banner', () => { + implementsClassName(props => , classes.Banner) + it('should render as a region element', () => { render() expect(screen.getByRole('region', {name: 'Information'})).toBeInTheDocument() expect(screen.getByRole('heading', {name: 'test'})).toBeInTheDocument() }) - it('should support a custom `className` on the outermost element', () => { - const Element = () => - expect(render().container.firstChild).toHaveClass('test-class-name') - }) - it('should label the landmark element with the corresponding variant label text', () => { render() expect(screen.getByRole('region')).toEqual(screen.getByLabelText('Information')) diff --git a/packages/react/src/Blankslate/Blankslate.test.tsx b/packages/react/src/Blankslate/Blankslate.test.tsx index fef3ee49460..c55859c1478 100644 --- a/packages/react/src/Blankslate/Blankslate.test.tsx +++ b/packages/react/src/Blankslate/Blankslate.test.tsx @@ -2,12 +2,11 @@ import {describe, expect, it, vi} from 'vitest' import {render, screen} from '@testing-library/react' import userEvent from '@testing-library/user-event' import {Blankslate} from '../Blankslate' +import {implementsClassName} from '../utils/testing' +import classes from './Blankslate.module.css' describe('Blankslate', () => { - it('should support a custom `className` on the outermost, non-container element', () => { - const {container} = render(Test content) - expect(container.firstChild!.firstChild).toHaveClass('test') - }) + implementsClassName(Blankslate, classes.Blankslate) it('should render with border when border is true', () => { const {container} = render(Test content) diff --git a/script/check-classname-tests.mjs b/script/check-classname-tests.mjs index 5a30466f756..c7636e9dc48 100755 --- a/script/check-classname-tests.mjs +++ b/script/check-classname-tests.mjs @@ -19,7 +19,7 @@ function getAllTestFiles(dir, files = []) { if (item !== 'utils' && item !== '__tests__') { getAllTestFiles(fullPath, files) } - } else if (stat.isFile() && item.endsWith('.test.tsx')) { + } else if (stat.isFile() && item.endsWith('.test.tsx') && !item.endsWith('.types.test.tsx')) { files.push(fullPath) } } From ce10e92c5b6b45d8f5ccbcf678d4c900d32030b1 Mon Sep 17 00:00:00 2001 From: Marie Lucca Date: Tue, 9 Dec 2025 16:04:09 -0500 Subject: [PATCH 08/29] add more className utils --- packages/react/src/Checkbox/Checkbox.test.tsx | 9 ++++---- .../src/deprecated/DialogV1/Dialog.test.tsx | 22 +++++++++++++++---- .../UnderlineNav/UnderlineNav.test.tsx | 4 ++++ .../UnderlineNav/UnderlineNavLink.test.tsx | 4 ++++ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/react/src/Checkbox/Checkbox.test.tsx b/packages/react/src/Checkbox/Checkbox.test.tsx index 101267a08c7..253baa55b83 100644 --- a/packages/react/src/Checkbox/Checkbox.test.tsx +++ b/packages/react/src/Checkbox/Checkbox.test.tsx @@ -2,17 +2,16 @@ import {describe, expect, it, vi, beforeEach} from 'vitest' import {render} from '@testing-library/react' import userEvent from '@testing-library/user-event' import Checkbox from '../Checkbox' +import {implementsClassName} from '../utils/testing' +import classes from './Checkbox.module.css' describe('Checkbox', () => { + implementsClassName(Checkbox, classes.Checkbox) + beforeEach(() => { vi.clearAllMocks() }) - it('should support `className` on the outermost element', () => { - const Element = () => - expect(render().container.firstChild).toHaveClass('test-class-name') - }) - it('renders a valid checkbox input', () => { const {getByRole} = render() diff --git a/packages/react/src/deprecated/DialogV1/Dialog.test.tsx b/packages/react/src/deprecated/DialogV1/Dialog.test.tsx index c8ff8cb2126..1a58a596818 100644 --- a/packages/react/src/deprecated/DialogV1/Dialog.test.tsx +++ b/packages/react/src/deprecated/DialogV1/Dialog.test.tsx @@ -3,6 +3,8 @@ import {useState, useRef} from 'react' import {Text, Button} from '../..' import {Dialog} from '../DialogV1' import {render as HTMLRender, fireEvent} from '@testing-library/react' +import {implementsClassName} from '../../utils/testing' +import classes from './Dialog.module.css' /* Dialog Version 1*/ @@ -92,10 +94,22 @@ const DialogWithCustomFocusRefAndReturnFocusRef = () => { } describe('Dialog', () => { - it('should support `className` on the Dialog element', () => { - const Element = () => - expect(HTMLRender().container.children[1]).toHaveClass('test-class-name') - }) + implementsClassName( + props => ( + + Header + + ), + classes.Dialog, + ) + implementsClassName( + props => ( + + Header + + ), + classes.Header, + ) it('Toggles when you click close button', async () => { const {getByLabelText, getByTestId, queryByTestId} = HTMLRender() diff --git a/packages/react/src/deprecated/UnderlineNav/UnderlineNav.test.tsx b/packages/react/src/deprecated/UnderlineNav/UnderlineNav.test.tsx index dce28ff6462..0249c216665 100644 --- a/packages/react/src/deprecated/UnderlineNav/UnderlineNav.test.tsx +++ b/packages/react/src/deprecated/UnderlineNav/UnderlineNav.test.tsx @@ -1,8 +1,12 @@ import {render} from '@testing-library/react' import {describe, it, expect} from 'vitest' import UnderlineNav from '../UnderlineNav' +import {implementsClassName} from '../../utils/testing' +import classes from './UnderlineNav.module.css' describe('UnderlineNav', () => { + implementsClassName(UnderlineNav, classes.UnderlineNav) + it('renders a