Skip to content

Commit 28ea293

Browse files
committed
add tests
1 parent d50ed5f commit 28ea293

4 files changed

Lines changed: 271 additions & 4 deletions

File tree

packages/react/radio-group/src/radio-group.test.tsx

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,78 @@ describe('RadioGroup', () => {
294294
expect(form.checkValidity()).toBe(true);
295295
});
296296
});
297+
298+
describe('given a RadioGroup in a form that is reset', () => {
299+
describe('uncontrolled', () => {
300+
it('should restore its `defaultValue` selection when the form is reset', () => {
301+
render(
302+
<form>
303+
<ClassicRadioGroup name="pet" defaultValue="1" />
304+
<button type="reset">Reset</button>
305+
</form>,
306+
);
307+
308+
const radios = screen.getAllByRole(RADIO_ROLE);
309+
expect(radios[0]).toHaveAttribute('aria-checked', 'true');
310+
311+
act(() => fireEvent.click(radios[1]!));
312+
expect(radios[0]).toHaveAttribute('aria-checked', 'false');
313+
expect(radios[1]).toHaveAttribute('aria-checked', 'true');
314+
315+
act(() => fireEvent.click(screen.getByText('Reset')));
316+
expect(radios[0]).toHaveAttribute('aria-checked', 'true');
317+
expect(radios[1]).toHaveAttribute('aria-checked', 'false');
318+
});
319+
320+
it('should restore an empty selection when there is no `defaultValue`', () => {
321+
render(
322+
<form>
323+
<ClassicRadioGroup name="pet" />
324+
<button type="reset">Reset</button>
325+
</form>,
326+
);
327+
328+
const radios = screen.getAllByRole(RADIO_ROLE);
329+
act(() => fireEvent.click(radios[1]!));
330+
expect(radios[1]).toHaveAttribute('aria-checked', 'true');
331+
332+
act(() => fireEvent.click(screen.getByText('Reset')));
333+
radios.forEach((radio) => expect(radio).toHaveAttribute('aria-checked', 'false'));
334+
});
335+
});
336+
337+
describe('controlled', () => {
338+
it('should restore its initial `value` selection when the form is reset', () => {
339+
function ControlledRadioGroup() {
340+
const [value, setValue] = React.useState<string | null>('1');
341+
return (
342+
<form>
343+
<RadioGroup.Root aria-label="pets" name="pet" value={value} onValueChange={setValue}>
344+
{VALUES.map((v) => (
345+
<RadioGroup.Item key={v} value={v} aria-label={LABELS[v]}>
346+
<RadioGroup.Indicator data-testid={`${INDICATOR_TEST_ID}-${v}`} />
347+
</RadioGroup.Item>
348+
))}
349+
</RadioGroup.Root>
350+
<button type="reset">Reset</button>
351+
</form>
352+
);
353+
}
354+
355+
render(<ControlledRadioGroup />);
356+
357+
const radios = screen.getAllByRole(RADIO_ROLE);
358+
expect(radios[0]).toHaveAttribute('aria-checked', 'true');
359+
360+
act(() => fireEvent.click(radios[2]!));
361+
expect(radios[2]).toHaveAttribute('aria-checked', 'true');
362+
363+
act(() => fireEvent.click(screen.getByText('Reset')));
364+
expect(radios[0]).toHaveAttribute('aria-checked', 'true');
365+
expect(radios[2]).toHaveAttribute('aria-checked', 'false');
366+
});
367+
});
368+
});
297369
});
298370

299371
describe('Composable RadioGroup', () => {

packages/react/select/src/select.test.tsx

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { cleanup, render, screen, waitFor } from '@testing-library/react';
2+
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
33
import { afterEach, describe, it, expect } from 'vitest';
44
import * as Select from './select';
55

@@ -13,10 +13,10 @@ const SelectTest = (props: React.ComponentProps<typeof Select.Root>) => (
1313
<Select.Portal>
1414
<Select.Content position="popper">
1515
<Select.Viewport>
16-
<Select.Item value="apple">
16+
<Select.Item value="apple" data-testid="item-apple">
1717
<Select.ItemText>Apple</Select.ItemText>
1818
</Select.Item>
19-
<Select.Item value="banana">
19+
<Select.Item value="banana" data-testid="item-banana">
2020
<Select.ItemText>Banana</Select.ItemText>
2121
</Select.Item>
2222
</Select.Viewport>
@@ -47,3 +47,87 @@ describe('aria-controls', () => {
4747
expect(document.getElementById(content.id)).toBe(content);
4848
});
4949
});
50+
51+
describe('given a Select in a form that is reset', () => {
52+
afterEach(cleanup);
53+
54+
describe('uncontrolled', () => {
55+
it('should restore its `defaultValue` when the form is reset', async () => {
56+
render(
57+
<form>
58+
{/* Keep the content open so the items (and their selection state) stay mounted. */}
59+
<SelectTest name="fruit" defaultValue="apple" open onOpenChange={() => {}} />
60+
<button type="reset">Reset</button>
61+
</form>,
62+
);
63+
64+
const apple = await screen.findByTestId('item-apple');
65+
const banana = screen.getByTestId('item-banana');
66+
expect(apple).toHaveAttribute('data-state', 'checked');
67+
68+
act(() => fireEvent.click(banana));
69+
expect(banana).toHaveAttribute('data-state', 'checked');
70+
expect(apple).toHaveAttribute('data-state', 'unchecked');
71+
72+
act(() => fireEvent.click(screen.getByText('Reset')));
73+
expect(apple).toHaveAttribute('data-state', 'checked');
74+
expect(banana).toHaveAttribute('data-state', 'unchecked');
75+
});
76+
77+
it('should restore the placeholder when reset with no initial value', async () => {
78+
render(
79+
<form>
80+
{/* Keep the content open so the items (and their selection state) stay mounted. */}
81+
<SelectTest name="fruit" open onOpenChange={() => {}} />
82+
<button type="reset">Reset</button>
83+
</form>,
84+
);
85+
86+
const banana = await screen.findByTestId('item-banana');
87+
// No value selected initially, so the placeholder is shown.
88+
expect(screen.getByText(PLACEHOLDER_TEXT)).toBeInTheDocument();
89+
90+
act(() => fireEvent.click(banana));
91+
expect(banana).toHaveAttribute('data-state', 'checked');
92+
expect(screen.queryByText(PLACEHOLDER_TEXT)).not.toBeInTheDocument();
93+
94+
act(() => fireEvent.click(screen.getByText('Reset')));
95+
expect(banana).toHaveAttribute('data-state', 'unchecked');
96+
expect(screen.getByText(PLACEHOLDER_TEXT)).toBeInTheDocument();
97+
});
98+
});
99+
100+
describe('controlled', () => {
101+
it('should restore its initial `value` when the form is reset', async () => {
102+
function ControlledSelect() {
103+
const [value, setValue] = React.useState('apple');
104+
return (
105+
<form>
106+
<SelectTest
107+
name="fruit"
108+
value={value}
109+
onValueChange={setValue}
110+
open
111+
onOpenChange={() => {}}
112+
/>
113+
<button type="reset">Reset</button>
114+
</form>
115+
);
116+
}
117+
118+
render(<ControlledSelect />);
119+
120+
const apple = await screen.findByTestId('item-apple');
121+
const banana = screen.getByTestId('item-banana');
122+
expect(apple).toHaveAttribute('data-state', 'checked');
123+
124+
act(() => fireEvent.click(banana));
125+
expect(banana).toHaveAttribute('data-state', 'checked');
126+
expect(apple).toHaveAttribute('data-state', 'unchecked');
127+
128+
act(() => fireEvent.click(screen.getByText('Reset')));
129+
expect(apple).toHaveAttribute('data-state', 'checked');
130+
expect(banana).toHaveAttribute('data-state', 'unchecked');
131+
});
132+
});
133+
});

packages/react/slider/src/slider.test.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,59 @@ describe('Slider', () => {
5454

5555
expect(getThumbValue()).toBeCloseTo(1.5e-7, 12);
5656
});
57+
58+
describe('within a form that is reset', () => {
59+
function renderSliderInForm(props: React.ComponentProps<typeof Slider.Root>) {
60+
return render(
61+
<form>
62+
<Slider.Root {...props}>
63+
<Slider.Track>
64+
<Slider.Range />
65+
</Slider.Track>
66+
<Slider.Thumb />
67+
</Slider.Root>
68+
<button type="reset">Reset</button>
69+
</form>,
70+
);
71+
}
72+
73+
it('should restore its `defaultValue` when the form is reset (uncontrolled)', async () => {
74+
const user = userEvent.setup();
75+
renderSliderInForm({ name: 'volume', defaultValue: [20], min: 0, max: 100 });
76+
77+
await user.tab();
78+
await user.keyboard('{ArrowRight}');
79+
expect(getThumbValue()).toBe(21);
80+
81+
await user.click(screen.getByText('Reset'));
82+
expect(getThumbValue()).toBe(20);
83+
});
84+
85+
it('should restore its initial `value` when the form is reset (controlled)', async () => {
86+
function ControlledSlider() {
87+
const [value, setValue] = React.useState([20]);
88+
return (
89+
<form>
90+
<Slider.Root name="volume" value={value} onValueChange={setValue} min={0} max={100}>
91+
<Slider.Track>
92+
<Slider.Range />
93+
</Slider.Track>
94+
<Slider.Thumb />
95+
</Slider.Root>
96+
<button type="reset">Reset</button>
97+
</form>
98+
);
99+
}
100+
101+
const user = userEvent.setup();
102+
render(<ControlledSlider />);
103+
104+
await user.tab();
105+
await user.keyboard('{ArrowRight}');
106+
expect(getThumbValue()).toBe(21);
107+
108+
await user.click(screen.getByText('Reset'));
109+
expect(getThumbValue()).toBe(20);
110+
});
111+
});
57112
});

packages/react/switch/src/switch.test.tsx

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import * as React from 'react';
12
import * as Switch from './switch';
2-
import { cleanup, render } from '@testing-library/react';
3+
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react';
34
import { afterEach, describe, it, expect } from 'vitest';
45

6+
const SWITCH_ROLE = 'switch';
7+
58
describe('given a default Switch', () => {
69
afterEach(cleanup);
710

@@ -25,3 +28,56 @@ describe('given a default Switch', () => {
2528
expect(cleanedUp).toBe(true);
2629
});
2730
});
31+
32+
describe('given a Switch in a form', () => {
33+
afterEach(cleanup);
34+
35+
describe('uncontrolled', () => {
36+
it('should restore its `defaultChecked` value when the form is reset', () => {
37+
render(
38+
<form>
39+
<Switch.Root name="notifications" defaultChecked>
40+
<Switch.Thumb />
41+
</Switch.Root>
42+
<button type="reset">Reset</button>
43+
</form>,
44+
);
45+
46+
const switchControl = screen.getByRole(SWITCH_ROLE);
47+
expect(switchControl).toHaveAttribute('aria-checked', 'true');
48+
49+
act(() => fireEvent.click(switchControl));
50+
expect(switchControl).toHaveAttribute('aria-checked', 'false');
51+
52+
act(() => fireEvent.click(screen.getByText('Reset')));
53+
expect(switchControl).toHaveAttribute('aria-checked', 'true');
54+
});
55+
});
56+
57+
describe('controlled', () => {
58+
it('should restore its initial `checked` value when the form is reset', () => {
59+
function ControlledSwitch() {
60+
const [checked, setChecked] = React.useState(true);
61+
return (
62+
<form>
63+
<Switch.Root name="notifications" checked={checked} onCheckedChange={setChecked}>
64+
<Switch.Thumb />
65+
</Switch.Root>
66+
<button type="reset">Reset</button>
67+
</form>
68+
);
69+
}
70+
71+
render(<ControlledSwitch />);
72+
73+
const switchControl = screen.getByRole(SWITCH_ROLE);
74+
expect(switchControl).toHaveAttribute('aria-checked', 'true');
75+
76+
act(() => fireEvent.click(switchControl));
77+
expect(switchControl).toHaveAttribute('aria-checked', 'false');
78+
79+
act(() => fireEvent.click(screen.getByText('Reset')));
80+
expect(switchControl).toHaveAttribute('aria-checked', 'true');
81+
});
82+
});
83+
});

0 commit comments

Comments
 (0)