mirror of
https://github.com/aphrody-labs/base-ui.git
synced 2026-10-17 12:46:28 +00:00
[checkbox][switch][slider] Fix extra validate fn calls (#4911)
This commit is contained in:
1 parent
e18d788327
commit
2b68bf3efc
6 files changed
+80
-6
No files matched your search
@@ -1202,6 +1202,21 @@ describe('<Checkbox.Root />', () => {
|
||||
expect(button).toHaveAttribute('aria-invalid', 'true');
|
||||
});
|
||||
|
||||
it('validates once when changed by the user', async () => {
|
||||
const validate = vi.fn();
|
||||
|
||||
const { user } = await render(
|
||||
<Field.Root validationMode="onChange" validate={validate}>
|
||||
<Checkbox.Root />
|
||||
</Field.Root>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole('checkbox'));
|
||||
|
||||
expect(validate).toHaveBeenCalledTimes(1);
|
||||
expect(validate.mock.lastCall?.[0]).toBe(true);
|
||||
});
|
||||
|
||||
it('revalidates when a controlled value changes externally', async () => {
|
||||
const validateSpy = vi.fn((value: unknown) => ((value as boolean) ? 'error' : null));
|
||||
|
||||
|
||||
@@ -259,10 +259,7 @@ export const CheckboxRoot = React.forwardRef(function CheckboxRoot(
|
||||
? { value: (groupContext ? checked && valueProp : valueProp) || '' }
|
||||
: EMPTY_OBJECT,
|
||||
getDescriptionProps,
|
||||
(props) =>
|
||||
groupContext
|
||||
? validation.getValidationProps(disabled, props)
|
||||
: validation.getInputValidationProps(disabled, props),
|
||||
(props) => validation.getValidationProps(disabled, props),
|
||||
);
|
||||
|
||||
const computedChecked = isGroupedWithParent ? Boolean(groupChecked) : checked;
|
||||
|
||||
@@ -2459,6 +2459,53 @@ describe.skipIf(typeof Touch === 'undefined')('<Slider.Root />', () => {
|
||||
expect(input).toHaveAttribute('aria-invalid', 'true');
|
||||
});
|
||||
|
||||
it('validates once when changed by the user', async () => {
|
||||
const validate = vi.fn();
|
||||
|
||||
const { user } = await render(
|
||||
<Field.Root validationMode="onChange" validate={validate}>
|
||||
<Slider.Root defaultValue={0}>
|
||||
<Slider.Control>
|
||||
<Slider.Thumb />
|
||||
</Slider.Control>
|
||||
</Slider.Root>
|
||||
</Field.Root>,
|
||||
);
|
||||
|
||||
await user.keyboard('[Tab]');
|
||||
expect(screen.getByRole('slider')).toHaveFocus();
|
||||
|
||||
await user.keyboard(`[${ARROW_RIGHT}]`);
|
||||
await flushMicrotasks();
|
||||
|
||||
expect(validate).toHaveBeenCalledTimes(1);
|
||||
expect(validate.mock.lastCall?.[0]).toBe(1);
|
||||
});
|
||||
|
||||
it('validates once with an array value for range sliders when changed by the user', async () => {
|
||||
const validate = vi.fn();
|
||||
|
||||
const { user } = await render(
|
||||
<Field.Root validationMode="onChange" validate={validate}>
|
||||
<Slider.Root defaultValue={[0, 5]}>
|
||||
<Slider.Control>
|
||||
<Slider.Thumb index={0} />
|
||||
<Slider.Thumb index={1} />
|
||||
</Slider.Control>
|
||||
</Slider.Root>
|
||||
</Field.Root>,
|
||||
);
|
||||
|
||||
await user.keyboard('[Tab]');
|
||||
expect(screen.getAllByRole('slider')[0]).toHaveFocus();
|
||||
|
||||
await user.keyboard(`[${ARROW_RIGHT}]`);
|
||||
await flushMicrotasks();
|
||||
|
||||
expect(validate).toHaveBeenCalledTimes(1);
|
||||
expect(validate.mock.lastCall?.[0]).toEqual([1, 5]);
|
||||
});
|
||||
|
||||
it('revalidates when the controlled value changes externally', async () => {
|
||||
const validateSpy = vi.fn((value: unknown) => (Number(value) === 5 ? 'error' : null));
|
||||
|
||||
|
||||
@@ -452,7 +452,7 @@ export const SliderThumb = React.forwardRef(function SliderThumb(
|
||||
type: 'range',
|
||||
value: thumbValue ?? '',
|
||||
},
|
||||
(props) => validation.getInputValidationProps(disabled, props),
|
||||
(props) => validation.getValidationProps(disabled, props),
|
||||
);
|
||||
|
||||
const mergedInputRef = useMergedRefs(inputRef, validation.inputRef, inputRefProp);
|
||||
|
||||
@@ -831,6 +831,21 @@ describe('<Switch.Root />', () => {
|
||||
expect(button).toHaveAttribute('aria-invalid', 'true');
|
||||
});
|
||||
|
||||
it('validates once when changed by the user', async () => {
|
||||
const validate = vi.fn();
|
||||
|
||||
const { user } = await render(
|
||||
<Field.Root validationMode="onChange" validate={validate}>
|
||||
<Switch.Root />
|
||||
</Field.Root>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole('switch'));
|
||||
|
||||
expect(validate).toHaveBeenCalledTimes(1);
|
||||
expect(validate.mock.lastCall?.[0]).toBe(true);
|
||||
});
|
||||
|
||||
it('revalidates when a controlled value changes externally', async () => {
|
||||
const validateSpy = vi.fn((value: unknown) => ((value as boolean) ? 'error' : null));
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ export const SwitchRoot = React.forwardRef(function SwitchRoot(
|
||||
switchRef.current?.focus();
|
||||
},
|
||||
},
|
||||
(props) => validation.getInputValidationProps(disabled, props),
|
||||
(props) => validation.getValidationProps(disabled, props),
|
||||
// React <19 sets an empty value if `undefined` is passed explicitly
|
||||
// To avoid this, we only set the value if it's defined
|
||||
value !== undefined ? { value } : EMPTY_OBJECT,
|
||||
|
||||
Reference in new issue
Block a user