Skip to content

Commit bd1f1c2

Browse files
authored
Add jest test for all components accepting className on outermost component (#5137)
* Test elements accept className * Create a test check for expectRendersWithClassname * Create three-jokes-bow.md * Check test on Avatar * Add test for AvatarPair * Add more tests * Remove duplicate test * Remove helper * Add more className tests * Add classname support to Spinner * Remove unused import * Add support to Textarea for className * Add more className tests * Fix Textarea test
1 parent 1f53e40 commit bd1f1c2

22 files changed

+431
-8
lines changed

.changeset/three-jokes-bow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/react": patch
3+
---
4+
5+
Make sure all components accept `className` as a prop on outermost component element.

packages/react/src/Banner/Banner.test.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {render, screen} from '@testing-library/react'
22
import userEvent from '@testing-library/user-event'
33
import React from 'react'
44
import {Banner} from '../Banner'
5+
import {FeatureFlags} from '../FeatureFlags'
56

67
describe('Banner', () => {
78
let spy: jest.SpyInstance
@@ -30,8 +31,22 @@ describe('Banner', () => {
3031
})
3132

3233
it('should support a custom `className` on the outermost element', () => {
33-
const {container} = render(<Banner title="test" className="test" />)
34-
expect(container.firstChild).toHaveClass('test')
34+
const Element = () => <Banner title="test" className="test-class-name" />
35+
const FeatureFlagElement = () => {
36+
return (
37+
<FeatureFlags
38+
flags={{
39+
primer_react_css_modules_team: true,
40+
primer_react_css_modules_staff: true,
41+
primer_react_css_modules_ga: true,
42+
}}
43+
>
44+
<Element />
45+
</FeatureFlags>
46+
)
47+
}
48+
expect(render(<Element />).container.firstChild).toHaveClass('test-class-name')
49+
expect(render(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
3550
})
3651

3752
it('should label the landmark element with the corresponding variant label text', () => {

packages/react/src/Breadcrumbs/__tests__/Breadcrumbs.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Breadcrumbs, {Breadcrumb} from '..'
33
import {render, behavesAsComponent, checkExports} from '../../utils/testing'
44
import {render as HTMLRender} from '@testing-library/react'
55
import axe from 'axe-core'
6+
import {FeatureFlags} from '../../FeatureFlags'
67

78
describe('Breadcrumbs', () => {
89
behavesAsComponent({Component: Breadcrumbs, options: {skipAs: true}})
@@ -12,6 +13,25 @@ describe('Breadcrumbs', () => {
1213
Breadcrumb,
1314
})
1415

16+
it('should support `className` on the outermost element', () => {
17+
const Element = () => <Breadcrumbs className={'test-class-name'} />
18+
const FeatureFlagElement = () => {
19+
return (
20+
<FeatureFlags
21+
flags={{
22+
primer_react_css_modules_team: true,
23+
primer_react_css_modules_staff: true,
24+
primer_react_css_modules_ga: true,
25+
}}
26+
>
27+
<Element />
28+
</FeatureFlags>
29+
)
30+
}
31+
expect(HTMLRender(<Element />).container.firstChild).toHaveClass('test-class-name')
32+
expect(HTMLRender(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
33+
})
34+
1535
it('should have no axe violations', async () => {
1636
const {container} = HTMLRender(<Breadcrumbs />)
1737
const results = await axe.run(container)

packages/react/src/Button/__tests__/Button.test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,25 @@ describe('Button', () => {
3131
options: {skipSx: true, skipAs: true},
3232
})
3333

34+
it('should support `className` on the outermost element', () => {
35+
const Element = () => <Button className={'test-class-name'} />
36+
const FeatureFlagElement = () => {
37+
return (
38+
<FeatureFlags
39+
flags={{
40+
primer_react_css_modules_team: true,
41+
primer_react_css_modules_staff: true,
42+
primer_react_css_modules_ga: true,
43+
}}
44+
>
45+
<Element />
46+
</FeatureFlags>
47+
)
48+
}
49+
expect(render(<Element />).container.firstChild).toHaveClass('test-class-name')
50+
expect(render(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
51+
})
52+
3453
it('renders a <button>', () => {
3554
const container = render(<Button id="test-button">Default</Button>)
3655
const button = container.getByRole('button')

packages/react/src/Checkbox/Checkbox.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event'
33
import React from 'react'
44
import Checkbox from '../Checkbox'
55
import {behavesAsComponent, checkExports} from '../utils/testing'
6+
import {FeatureFlags} from '../FeatureFlags'
67

78
describe('Checkbox', () => {
89
beforeEach(() => {
@@ -14,6 +15,25 @@ describe('Checkbox', () => {
1415
default: Checkbox,
1516
})
1617

18+
it('should support `className` on the outermost element', () => {
19+
const Element = () => <Checkbox className={'test-class-name'} />
20+
const FeatureFlagElement = () => {
21+
return (
22+
<FeatureFlags
23+
flags={{
24+
primer_react_css_modules_team: true,
25+
primer_react_css_modules_staff: true,
26+
primer_react_css_modules_ga: true,
27+
}}
28+
>
29+
<Element />
30+
</FeatureFlags>
31+
)
32+
}
33+
expect(render(<Element />).container.firstChild).toHaveClass('test-class-name')
34+
expect(render(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
35+
})
36+
1737
it('renders a valid checkbox input', () => {
1838
const {getByRole} = render(<Checkbox />)
1939

packages/react/src/CounterLabel/CounterLabel.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {CounterLabel} from '..'
33
import {behavesAsComponent, checkExports} from '../utils/testing'
44
import {render as HTMLRender} from '@testing-library/react'
55
import axe from 'axe-core'
6+
import {FeatureFlags} from '../FeatureFlags'
67

78
describe('CounterLabel', () => {
89
behavesAsComponent({Component: CounterLabel, options: {skipAs: true, skipSx: true}})
@@ -11,6 +12,25 @@ describe('CounterLabel', () => {
1112
default: CounterLabel,
1213
})
1314

15+
it('should support `className` on the outermost element', () => {
16+
const Element = () => <CounterLabel className={'test-class-name'} />
17+
const FeatureFlagElement = () => {
18+
return (
19+
<FeatureFlags
20+
flags={{
21+
primer_react_css_modules_team: true,
22+
primer_react_css_modules_staff: true,
23+
primer_react_css_modules_ga: true,
24+
}}
25+
>
26+
<Element />
27+
</FeatureFlags>
28+
)
29+
}
30+
expect(HTMLRender(<Element />).container.firstChild).toHaveClass('test-class-name')
31+
expect(HTMLRender(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
32+
})
33+
1434
it('renders a <span>', () => {
1535
const {container} = HTMLRender(<CounterLabel>1234</CounterLabel>)
1636
expect(container.firstChild?.nodeName).toEqual('SPAN')

packages/react/src/Heading/__tests__/Heading.test.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {render, behavesAsComponent, checkExports} from '../../utils/testing'
44
import {render as HTMLRender, screen} from '@testing-library/react'
55
import axe from 'axe-core'
66
import ThemeProvider from '../../ThemeProvider'
7+
import {FeatureFlags} from '../../FeatureFlags'
78

89
const theme = {
910
breakpoints: ['400px', '640px', '960px', '1280px'],
@@ -35,6 +36,25 @@ describe('Heading', () => {
3536
default: Heading,
3637
})
3738

39+
it('should support `className` on the outermost element', () => {
40+
const Element = () => <Heading className={'test-class-name'} />
41+
const FeatureFlagElement = () => {
42+
return (
43+
<FeatureFlags
44+
flags={{
45+
primer_react_css_modules_team: true,
46+
primer_react_css_modules_staff: true,
47+
primer_react_css_modules_ga: true,
48+
}}
49+
>
50+
<Element />
51+
</FeatureFlags>
52+
)
53+
}
54+
expect(HTMLRender(<Element />).container.firstChild).toHaveClass('test-class-name')
55+
expect(HTMLRender(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
56+
})
57+
3858
it('renders <h2> by default', () => {
3959
expect(render(<Heading />).type).toEqual('h2')
4060
})
@@ -149,11 +169,6 @@ describe('Heading', () => {
149169
expect(screen.getByText('test')).not.toHaveClass(/^Heading__StyledHeading/)
150170
})
151171

152-
it('should support `className` on the outermost element', () => {
153-
const {container} = HTMLRender(<Heading className="test">test</Heading>)
154-
expect(container.firstChild).toHaveClass('test')
155-
})
156-
157172
it('should support overrides with sx if provided', () => {
158173
HTMLRender(
159174
<Heading

packages/react/src/Link/__tests__/Link.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Link from '..'
33
import {render, behavesAsComponent, checkExports} from '../../utils/testing'
44
import {render as HTMLRender} from '@testing-library/react'
55
import axe from 'axe-core'
6+
import {FeatureFlags} from '../../FeatureFlags'
67

78
describe('Link', () => {
89
behavesAsComponent({Component: Link})
@@ -11,6 +12,25 @@ describe('Link', () => {
1112
default: Link,
1213
})
1314

15+
it('should support `className` on the outermost element', () => {
16+
const Element = () => <Link href="#" className={'test-class-name'} />
17+
const FeatureFlagElement = () => {
18+
return (
19+
<FeatureFlags
20+
flags={{
21+
primer_react_css_modules_team: true,
22+
primer_react_css_modules_staff: true,
23+
primer_react_css_modules_ga: true,
24+
}}
25+
>
26+
<Element />
27+
</FeatureFlags>
28+
)
29+
}
30+
expect(HTMLRender(<Element />).container.firstChild).toHaveClass('test-class-name')
31+
expect(HTMLRender(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
32+
})
33+
1434
it('should have no axe violations', async () => {
1535
const {container} = HTMLRender(<Link href="www.github.com">GitHub</Link>)
1636
const results = await axe.run(container)

packages/react/src/Spinner/Spinner.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,17 @@ export type SpinnerProps = {
1919
srText?: string | null
2020
/** @deprecated Use `srText` instead. */
2121
'aria-label'?: string
22+
className?: string
2223
} & HTMLDataAttributes &
2324
SxProp
2425

25-
function Spinner({size: sizeKey = 'medium', srText = 'Loading', 'aria-label': ariaLabel, ...props}: SpinnerProps) {
26+
function Spinner({
27+
size: sizeKey = 'medium',
28+
srText = 'Loading',
29+
'aria-label': ariaLabel,
30+
className,
31+
...props
32+
}: SpinnerProps) {
2633
const size = sizeMap[sizeKey]
2734
const hasHiddenLabel = srText !== null && ariaLabel === undefined
2835
const labelId = useId()
@@ -38,6 +45,7 @@ function Spinner({size: sizeKey = 'medium', srText = 'Loading', 'aria-label': ar
3845
aria-hidden
3946
aria-label={ariaLabel ?? undefined}
4047
aria-labelledby={hasHiddenLabel ? labelId : undefined}
48+
className={className}
4149
{...props}
4250
>
4351
<circle

packages/react/src/__tests__/Avatar.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import theme from '../theme'
44
import {px, render, behavesAsComponent, checkExports} from '../utils/testing'
55
import {render as HTMLRender} from '@testing-library/react'
66
import axe from 'axe-core'
7+
import {FeatureFlags} from '../FeatureFlags'
78

89
describe('Avatar', () => {
910
behavesAsComponent({Component: Avatar})
@@ -12,6 +13,25 @@ describe('Avatar', () => {
1213
default: Avatar,
1314
})
1415

16+
it('should support `className` on the outermost element', () => {
17+
const Element = () => <Avatar src="primer.png" className={'test-class-name'} />
18+
const FeatureFlagElement = () => {
19+
return (
20+
<FeatureFlags
21+
flags={{
22+
primer_react_css_modules_team: true,
23+
primer_react_css_modules_staff: true,
24+
primer_react_css_modules_ga: true,
25+
}}
26+
>
27+
<Element />
28+
</FeatureFlags>
29+
)
30+
}
31+
expect(HTMLRender(<Element />).container.firstChild).toHaveClass('test-class-name')
32+
expect(HTMLRender(<FeatureFlagElement />).container.firstChild).toHaveClass('test-class-name')
33+
})
34+
1535
it('should have no axe violations', async () => {
1636
const {container} = HTMLRender(<Avatar src="primer.png" />)
1737
const results = await axe.run(container)

0 commit comments

Comments
 (0)