Skip to content

Commit 55fd4a8

Browse files
chore(Chip): updated unit tests (#9572)
* chore(Chip): updated unit tests * Added integration test files * Updated tests per Austin feedback * Tested props get passed to Tooltip * Replaced haveBeenCalledTimes with haveBeenCalled
1 parent a5e0326 commit 55fd4a8

File tree

7 files changed

+288
-242
lines changed

7 files changed

+288
-242
lines changed

packages/react-core/src/components/Chip/Chip.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,13 @@ class Chip extends React.Component<ChipProps, ChipState> {
140140
tooltipPosition,
141141
component,
142142
ouiaId,
143+
textMaxWidth,
143144
...props
144145
} = this.props;
145146
const Component = component as any;
146147
return (
147148
<Component
148-
{...(this.props.textMaxWidth && {
149+
{...(textMaxWidth && {
149150
style: this.setChipStyle()
150151
})}
151152
className={css(styles.chip, className)}
Lines changed: 249 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,276 @@
11
import React from 'react';
2-
import { render } from '@testing-library/react';
2+
import { render, screen } from '@testing-library/react';
3+
import userEvent from '@testing-library/user-event';
34
import { Chip } from '../Chip';
5+
import styles from '@patternfly/react-styles/css/components/Chip/chip';
46

5-
describe('Chip', () => {
6-
test('overflow', () => {
7-
const { asFragment } = render(
8-
<Chip className="my-chp-cls" isOverflowChip>
9-
4 more
7+
jest.mock('../../Tooltip', () => ({
8+
Tooltip: ({ content, position }) => (
9+
<div data-testid="tooltip-mock">
10+
<p>{`content: ${content}`}</p>
11+
<p>{`position: ${position}`}</p>
12+
</div>
13+
)
14+
}));
15+
16+
['default chip', 'overflow chip'].forEach((chipType) => {
17+
const isOverflowChip = chipType === 'overflow chip';
18+
19+
test(`Renders without children for ${chipType}`, () => {
20+
render(
21+
<div data-testid="container">
22+
<Chip isOverflowChip={isOverflowChip} />
23+
</div>
24+
);
25+
26+
expect(screen.getByTestId('container').firstChild).toBeVisible();
27+
});
28+
29+
test(`Renders with class ${styles.chip} on the ${chipType} container element`, () => {
30+
render(
31+
<Chip isOverflowChip={isOverflowChip} data-testid="container">
32+
Chip text
33+
</Chip>
34+
);
35+
36+
// Only a non-overflow chip will have exactly the class "pf-v5-c-chip", we test for
37+
// additional classes on overflow chips elsewhere in the suite
38+
expect(screen.getByTestId('container')).toHaveClass(styles.chip, { exact: !isOverflowChip });
39+
});
40+
41+
test(`Renders with class ${styles.chipContent} around the ${chipType} content`, () => {
42+
render(
43+
<Chip isOverflowChip={isOverflowChip} data-testid="container">
44+
Chip text
1045
</Chip>
1146
);
12-
expect(asFragment()).toMatchSnapshot();
47+
48+
expect(screen.getByTestId('container').firstChild).toHaveClass(styles.chipContent, { exact: true });
49+
});
50+
51+
test(`Renders ${chipType} children with class ${styles.chipText}`, () => {
52+
render(<Chip isOverflowChip={isOverflowChip}>Chip text</Chip>);
53+
54+
expect(screen.getByText('Chip text')).toHaveClass(styles.chipText, { exact: true });
1355
});
1456

15-
test('closable', () => {
16-
const { asFragment } = render(
17-
<Chip className="my-chp-cls" id="chip_one">
18-
Chip
57+
test(`Renders with custom class on the ${chipType} container element`, () => {
58+
render(
59+
<Chip isOverflowChip={isOverflowChip} data-testid="container" className="custom-class">
60+
Chip text
1961
</Chip>
2062
);
21-
expect(asFragment()).toMatchSnapshot();
63+
64+
expect(screen.getByTestId('container')).toHaveClass('custom-class');
2265
});
2366

24-
test('closable with tooltip', () => {
25-
const { asFragment } = render(
26-
<Chip className="my-chp-cls" id="chip_one">
27-
1234567890123456789
67+
test(`Renders a badge when badge prop is passed to ${chipType}`, () => {
68+
render(
69+
<Chip isOverflowChip={isOverflowChip} badge={<div>Badge content</div>}>
70+
Chip text
2871
</Chip>
2972
);
30-
expect(asFragment()).toMatchSnapshot();
73+
74+
expect(screen.getByText('Badge content')).toBeVisible();
75+
});
76+
77+
test(`Renders with div container on ${chipType} by default`, () => {
78+
render(
79+
<Chip isOverflowChip={isOverflowChip} data-testid="container">
80+
Chip text
81+
</Chip>
82+
);
83+
84+
expect(screen.getByTestId('container').tagName).toBe('DIV');
3185
});
3286

33-
test('readonly', () => {
34-
const { asFragment } = render(
35-
<Chip className="my-chp-cls" isReadOnly>
36-
4 more
87+
test(`Renders with custom container on ${chipType} when component prop is passed`, () => {
88+
render(
89+
<Chip component="li" isOverflowChip={isOverflowChip}>
90+
Chip text
3791
</Chip>
3892
);
39-
expect(asFragment()).toMatchSnapshot();
93+
94+
expect(screen.getByRole('listitem')).toBeVisible();
4095
});
4196

42-
test('custom max-width text', () => {
43-
const { asFragment } = render(
44-
<Chip className="my-chp-cls" textMaxWidth="100px">
45-
4 more
97+
test(`Renders maxWidth css var in style attribute when textMaxWidth is passed for ${chipType}`, () => {
98+
render(
99+
<Chip isOverflowChip={isOverflowChip} data-testid="container" textMaxWidth="10px">
100+
Chip text
46101
</Chip>
47102
);
48-
expect(asFragment()).toMatchSnapshot();
103+
104+
expect(screen.getByTestId('container')).toHaveAttribute('style', '--pf-v5-c-chip__text--MaxWidth: 10px;');
49105
});
50106

51-
test("with role='gridcell'", () => {
52-
const { asFragment } = render(
53-
<Chip className="my-chp-cls" role="gridcell">
54-
I'm a roled chip
107+
test(`Spreads additional props to container for ${chipType}`, () => {
108+
render(
109+
<Chip isOverflowChip={isOverflowChip} data-testid="container" role="button">
110+
Chip text
55111
</Chip>
56112
);
57-
expect(asFragment()).toMatchSnapshot();
113+
114+
expect(screen.getByTestId('container')).toHaveAttribute('role', 'button');
58115
});
59116
});
117+
118+
test(`Renders id prop on ${styles.chipText} container for default chip`, () => {
119+
render(<Chip id="custom-id">Chip text</Chip>);
120+
121+
expect(screen.getByText('Chip text')).toHaveAttribute('id', 'custom-id');
122+
});
123+
124+
test(`Does not render id prop on ${styles.chipText} container for overflow chip`, () => {
125+
render(
126+
<Chip isOverflowChip id="custom-id">
127+
Chip text
128+
</Chip>
129+
);
130+
131+
expect(screen.getByText('Chip text')).not.toHaveAttribute('id');
132+
});
133+
134+
test(`Renders actions container with class ${styles.chipActions} when isReadOnly is false`, () => {
135+
render(<Chip>Chip text</Chip>);
136+
137+
expect(screen.getByRole('button').parentElement).toHaveClass(styles.chipActions);
138+
});
139+
140+
test(`Renders aria-labelledby on action close button by default`, () => {
141+
render(<Chip>Chip text</Chip>);
142+
143+
expect(screen.getByRole('button')).toHaveAccessibleName('close Chip text');
144+
});
145+
146+
test(`Renders aria-labelledby on action close button with custom id passed`, () => {
147+
render(<Chip id="custom-id">Chip text</Chip>);
148+
149+
expect(screen.getByRole('button')).toHaveAccessibleName('close Chip text');
150+
});
151+
152+
test(`Renders concatenated aria-label on action close button by default`, () => {
153+
render(<Chip>Chip text</Chip>);
154+
155+
expect(screen.getByRole('button')).toHaveAccessibleName('close Chip text');
156+
});
157+
158+
test(`Renders custom aria-label on action close button when closeBtnAriaLabel is passed`, () => {
159+
render(<Chip closeBtnAriaLabel="custom label">Chip text</Chip>);
160+
161+
expect(screen.getByRole('button')).toHaveAccessibleName('custom label Chip text');
162+
});
163+
164+
test(`Does not render close button action when isOverflowChip is true`, () => {
165+
render(<Chip isOverflowChip>Chip text</Chip>);
166+
167+
// Because overflow chip renders as a button, we need to add the accessible name to the query
168+
expect(screen.queryByRole('button', { name: 'close Chip text' })).not.toBeInTheDocument();
169+
});
170+
171+
test(`Does not render close button action when isReadOnly is true`, () => {
172+
render(<Chip isReadOnly>Chip text</Chip>);
173+
174+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
175+
});
176+
177+
test(`Does not render with class ${styles.modifiers.overflow} when isOverflowChip is not passed`, () => {
178+
render(<Chip data-testid="container">Chip text</Chip>);
179+
180+
expect(screen.getByTestId('container')).not.toHaveClass(styles.modifiers.overflow);
181+
});
182+
183+
test(`Renders with class ${styles.modifiers.overflow} when isOverflowChip is true`, () => {
184+
render(
185+
<Chip isOverflowChip data-testid="container">
186+
Chip text
187+
</Chip>
188+
);
189+
190+
expect(screen.getByTestId('container')).toHaveClass(styles.modifiers.overflow);
191+
});
192+
193+
test(`Calls onClick when close button action is clicked for default chip`, async () => {
194+
const user = userEvent.setup();
195+
const onClickMock = jest.fn();
196+
197+
render(<Chip onClick={onClickMock}>Chip text</Chip>);
198+
199+
await user.click(screen.getByRole('button', { name: 'close Chip text' }));
200+
201+
expect(onClickMock).toHaveBeenCalledTimes(1);
202+
});
203+
204+
test(`Does not call onClick when close button action is not clicked for default chip`, async () => {
205+
const user = userEvent.setup();
206+
const onClickMock = jest.fn();
207+
208+
render(
209+
<>
210+
<Chip onClick={onClickMock}>Chip text</Chip>
211+
<button>Test clicker</button>
212+
</>
213+
);
214+
215+
await user.click(screen.getByRole('button', { name: 'Test clicker' }));
216+
217+
expect(onClickMock).not.toHaveBeenCalled();
218+
});
219+
220+
test(`Calls onClick when chip is clicked for overflow chip`, async () => {
221+
const user = userEvent.setup();
222+
const onClickMock = jest.fn();
223+
224+
render(
225+
<Chip isOverflowChip component="button" onClick={onClickMock}>
226+
Chip text
227+
</Chip>
228+
);
229+
230+
await user.click(screen.getByRole('button', { name: 'Chip text' }));
231+
232+
expect(onClickMock).toHaveBeenCalledTimes(1);
233+
});
234+
235+
test(`Does not call onClick when chip is not clicked for overflow chip`, async () => {
236+
const user = userEvent.setup();
237+
const onClickMock = jest.fn();
238+
239+
render(
240+
<>
241+
<Chip isOverflowChip component="button" onClick={onClickMock}>
242+
Chip text
243+
</Chip>
244+
<button>Test clicker</button>
245+
</>
246+
);
247+
248+
await user.click(screen.getByRole('button', { name: 'Test clicker' }));
249+
250+
expect(onClickMock).not.toHaveBeenCalled();
251+
});
252+
253+
test('Passes position to Tooltip', () => {
254+
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', { configurable: true, value: 500 });
255+
render(<Chip tooltipPosition="bottom">Test chip text</Chip>);
256+
257+
expect(screen.getByText('position: bottom')).toBeVisible();
258+
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', { configurable: true, value: 0 });
259+
});
260+
261+
test('Passes content to Tooltip', () => {
262+
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', { configurable: true, value: 500 });
263+
render(<Chip>Test chip text</Chip>);
264+
265+
expect(screen.getByText(`content: Test chip text`)).toBeVisible();
266+
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', { configurable: true, value: 0 });
267+
});
268+
269+
test('Matches snapshot', () => {
270+
const { asFragment } = render(
271+
<Chip id="snapshot-test" ouiaId="snapshot-test">
272+
Chip text
273+
</Chip>
274+
);
275+
expect(asFragment()).toMatchSnapshot();
276+
});

0 commit comments

Comments
 (0)