mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(time-input): minValue and maxValue validation (#3426)
* fix(time-input): minValue and maxValue validation (#3424) * test(time-input): update * refactor(time-input): simplify `isInvalid` logic
This commit is contained in:
parent
2333c39870
commit
c1f05ecb46
5
.changeset/good-feet-drive.md
Normal file
5
.changeset/good-feet-drive.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@nextui-org/date-input": patch
|
||||
---
|
||||
|
||||
Fix minValue and maxValue validation (#3424)
|
||||
@ -180,6 +180,32 @@ describe("TimeInput", () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("should support error message (with isInvalid)", function () {
|
||||
const {getAllByRole, getByRole} = render(
|
||||
<TimeInput isInvalid errorMessage="Error message" label="Time" />,
|
||||
);
|
||||
|
||||
const group = getByRole("group");
|
||||
|
||||
expect(group).toHaveAttribute("aria-describedby");
|
||||
|
||||
if (group) {
|
||||
const descById = group.getAttribute("aria-describedby");
|
||||
const description = descById && document.getElementById(descById);
|
||||
|
||||
expect(description).toHaveTextContent("Error message");
|
||||
|
||||
const segments = getAllByRole("spinbutton");
|
||||
|
||||
for (const segment of segments) {
|
||||
expect(segment).toHaveAttribute(
|
||||
"aria-describedby",
|
||||
group.getAttribute("aria-describedby"),
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Events", function () {
|
||||
@ -354,4 +380,54 @@ describe("TimeInput", () => {
|
||||
expect(input).toHaveValue("08:30:00");
|
||||
});
|
||||
});
|
||||
|
||||
describe(`Validation (validationBehavior="aria")`, () => {
|
||||
it("should display errorMessage when timeValue is less than the minimum (controlled)", () => {
|
||||
render(<TimeInput label="Time" minValue={new Time(9)} value={new Time(8)} />);
|
||||
|
||||
expect(document.querySelector("[data-slot=error-message]")).toBeVisible();
|
||||
});
|
||||
|
||||
it("should display errorMessage when timeValue is less than the minimum (uncontrolled)", async () => {
|
||||
const {getAllByRole} = render(
|
||||
<TimeInput defaultValue={new Time(9)} label="Time" minValue={new Time(9)} name="time" />,
|
||||
);
|
||||
|
||||
const input = document.querySelector("input[name=time]");
|
||||
const segments = getAllByRole("spinbutton");
|
||||
|
||||
await user.tab();
|
||||
expect(input).toHaveValue("09:00:00");
|
||||
expect(segments[0]).toHaveFocus();
|
||||
expect(document.querySelector("[data-slot=error-message]")).toBeNull();
|
||||
|
||||
await user.keyboard("[ArrowDown]");
|
||||
expect(input).toHaveValue("08:00:00");
|
||||
expect(document.querySelector("[data-slot=error-message]")).toBeVisible();
|
||||
});
|
||||
|
||||
it("should display errorMessage when timeValue is greater than the maximum (controlled)", () => {
|
||||
render(<TimeInput label="Time" maxValue={new Time(17)} value={new Time(18)} />);
|
||||
|
||||
expect(document.querySelector("[data-slot=error-message]")).toBeVisible();
|
||||
});
|
||||
|
||||
it("should display errorMessage when timeValue is greater than the maximum (uncontrolled)", async () => {
|
||||
const {getAllByRole} = render(
|
||||
<TimeInput defaultValue={new Time(17)} label="Time" maxValue={new Time(17)} name="time" />,
|
||||
);
|
||||
|
||||
const input = document.querySelector("input[name=time]");
|
||||
const segments = getAllByRole("spinbutton");
|
||||
|
||||
await user.tab();
|
||||
expect(input).toHaveValue("17:00:00");
|
||||
expect(segments[0]).toHaveFocus();
|
||||
expect(document.querySelector("[data-slot=error-message]")).toBeNull();
|
||||
|
||||
await user.keyboard("[ArrowUp]");
|
||||
expect(input).toHaveValue("18:00:00");
|
||||
expect(document.querySelector("[data-slot=error-message]")).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -87,7 +87,6 @@ export function useTimeInput<T extends TimeValue>(originalProps: UseTimeInputPro
|
||||
endContent,
|
||||
className,
|
||||
classNames,
|
||||
validationState,
|
||||
groupProps = {},
|
||||
labelProps: labelPropsProp,
|
||||
fieldProps: fieldPropsProp,
|
||||
@ -97,7 +96,7 @@ export function useTimeInput<T extends TimeValue>(originalProps: UseTimeInputPro
|
||||
shouldForceLeadingZeros = true,
|
||||
minValue,
|
||||
maxValue,
|
||||
isInvalid: isInvalidProp = validationState ? validationState === "invalid" : false,
|
||||
isInvalid: isInvalidProp,
|
||||
errorMessage,
|
||||
} = props;
|
||||
|
||||
@ -127,13 +126,11 @@ export function useTimeInput<T extends TimeValue>(originalProps: UseTimeInputPro
|
||||
validationDetails,
|
||||
descriptionProps,
|
||||
errorMessageProps,
|
||||
isInvalid: ariaIsInvalid,
|
||||
isInvalid,
|
||||
} = useAriaTimeField({...originalProps, label, validationBehavior, inputRef}, state, domRef);
|
||||
|
||||
const baseStyles = clsx(classNames?.base, className);
|
||||
|
||||
const isInvalid = isInvalidProp || ariaIsInvalid;
|
||||
|
||||
const labelPlacement = useMemo<DateInputVariantProps["labelPlacement"]>(() => {
|
||||
if (
|
||||
(!originalProps.labelPlacement || originalProps.labelPlacement === "inside") &&
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user