diff --git a/packages/components/select/__tests__/select.test.tsx b/packages/components/select/__tests__/select.test.tsx
index 13b90369a4..fe1c82ea23 100644
--- a/packages/components/select/__tests__/select.test.tsx
+++ b/packages/components/select/__tests__/select.test.tsx
@@ -1180,30 +1180,136 @@ describe("validation", () => {
});
describe("validationBehavior=aria", () => {
- it("supports isRequired", async () => {
+ it("supports validate function", async () => {
+ const onSubmit = jest.fn((e) => e.preventDefault());
+
+ const {getByTestId} = render(
+
,
+ );
+
+ const trigger = getByTestId("trigger") as HTMLButtonElement;
+ const select = document.querySelector("select");
+ const submit = getByTestId("submit-button");
+
+ // aria validation is always valid
+ expect(select?.validity.valid).toBe(true);
+ // aria validation validates on initial render
+ expect(trigger).toHaveAttribute("aria-describedby");
+ expect(select).toHaveAttribute("aria-invalid", "true");
+ expect(document.getElementById(trigger.getAttribute("aria-describedby")!)).toHaveTextContent(
+ "Invalid value",
+ );
+
+ await user.click(trigger);
+
+ let listboxItems = document.querySelectorAll("[role='option']");
+
+ await user.click(listboxItems[1]); // zebra
+
+ await user.click(submit);
+
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).not.toHaveAttribute("aria-describedby");
+ expect(select).not.toHaveAttribute("aria-invalid");
+ });
+
+ it("supports server validation", async () => {
function FormRender() {
- const [serverErrors, setServerErrors] = React.useState({});
+ const [serverErrors, setServerErrors] = React.useState({animal: "initial error"});
const onSubmit = (e) => {
e.preventDefault();
- const formData = new FormData(e.target as HTMLFormElement);
- const value = formData.get("animal");
-
- if (!value || (value !== "cat" && value !== "dog")) {
- setServerErrors({
- animal: "Please select a cat or dog",
- });
- } else {
- setServerErrors({});
- }
+
+ setServerErrors({
+ animal: "new error",
+ });
};
return (
-
+ );
+ }
+
+ const {getByTestId} = render();
+
+ const trigger = getByTestId("trigger") as HTMLButtonElement;
+ const select = document.querySelector("select");
+ const submit = getByTestId("submit-button");
+
+ // aria validation is always valid
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).toHaveAttribute("aria-describedby");
+ expect(select).toHaveAttribute("aria-invalid", "true");
+ expect(document.getElementById(trigger.getAttribute("aria-describedby")!)).toHaveTextContent(
+ "initial error",
+ );
+
+ await user.click(trigger);
+
+ let listboxItems = document.querySelectorAll("[role='option']");
+
+ await user.click(listboxItems[1]); // zebra
+
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).not.toHaveAttribute("aria-describedby");
+ expect(select).not.toHaveAttribute("aria-invalid");
+
+ await user.click(submit);
+
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).toHaveAttribute("aria-describedby");
+ expect(select).toHaveAttribute("aria-invalid");
+ expect(document.getElementById(trigger.getAttribute("aria-describedby")!)).toHaveTextContent(
+ "new error",
+ );
+ });
+ });
+
+ describe("validationBehavior=native", () => {
+ it("supports isRequired", async () => {
+ function FormRender() {
+ const onSubmit = jest.fn((e) => e.preventDefault());
+
+ return (
+
@@ -1222,75 +1328,158 @@ describe("validation", () => {
const {getByTestId} = render();
- const select = getByTestId("select");
- const input = document.querySelector("input");
+ const trigger = getByTestId("trigger") as HTMLButtonElement;
+ const select = document.querySelector("select");
+ const submit = getByTestId("submit-button");
- expect(select).not.toHaveAttribute("aria-describedby");
- const button = getByTestId("button");
+ expect(select?.validity.valid).toBe(false);
+ expect(select?.validity.valueMissing).toBe(true);
+ // native validation does not validate until submit
+ expect(select).toHaveAttribute("required");
+ expect(trigger).not.toHaveAttribute("aria-describedby");
- await user.click(button);
+ await user.click(submit);
- expect(select).toHaveAttribute("aria-describedby");
- expect(input).toHaveAttribute("aria-required");
+ expect(select?.validity.valid).toBe(false);
+ expect(select?.validity.valueMissing).toBe(true);
+ expect(trigger).toHaveAttribute("aria-describedby");
- expect(document.getElementById(select.getAttribute("aria-describedby")!)).toHaveTextContent(
- "Please select a cat or dog",
- );
+ await user.click(trigger);
- await user.click(select);
let listboxItems = document.querySelectorAll("[role='option']");
await user.click(listboxItems[0]);
- await user.click(button);
+ await user.click(submit);
- expect(select).not.toHaveAttribute("aria-describedby");
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).not.toHaveAttribute("aria-describedby");
});
it("supports validate function", async () => {
+ const onSubmit = jest.fn((e) => e.preventDefault());
+
const {getByTestId} = render(
- ,
);
- const select = getByTestId("select");
- const input = document.querySelector("input");
- const button = getByTestId("button");
+ const trigger = getByTestId("trigger") as HTMLButtonElement;
+ const select = document.querySelector("select");
+ const submit = getByTestId("submit-button");
+
+ expect(select?.validity.valid).toBe(false);
+ expect(select?.validity.customError).toBe(true);
+ // native validation does not validate until submit
+ expect(trigger).not.toHaveAttribute("aria-describedby");
+ expect(select).not.toHaveAttribute("aria-invalid", "true");
- expect(select).toHaveAttribute("aria-describedby");
- expect(input).toHaveAttribute("aria-invalid", "true");
+ await user.click(submit);
- expect(document.getElementById(select.getAttribute("aria-describedby")!)).toHaveTextContent(
+ expect(select?.validity.valid).toBe(false);
+ expect(select?.validity.customError).toBe(true);
+ expect(trigger).toHaveAttribute("aria-describedby");
+ expect(select).toHaveAttribute("aria-invalid", "true");
+ expect(document.getElementById(trigger.getAttribute("aria-describedby")!)).toHaveTextContent(
"Invalid value",
);
- expect(input?.validity.valid).toBe(true);
-
- await user.click(select);
+ await user.click(trigger);
let listboxItems = document.querySelectorAll("[role='option']");
- await user.click(listboxItems[1]); // Select "Zebra"
+ await user.click(listboxItems[1]); // zebra
- await user.click(button);
+ await user.click(submit);
- expect(select).not.toHaveAttribute("aria-describedby");
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).not.toHaveAttribute("aria-describedby");
expect(select).not.toHaveAttribute("aria-invalid");
});
+
+ it("supports server validation", async () => {
+ function FormRender() {
+ const [serverErrors, setServerErrors] = React.useState({animal: "initial error"});
+
+ const onSubmit = (e) => {
+ e.preventDefault();
+
+ setServerErrors({
+ animal: "new error",
+ });
+ };
+
+ return (
+
+ );
+ }
+
+ const {getByTestId} = render();
+
+ const trigger = getByTestId("trigger") as HTMLButtonElement;
+ const select = document.querySelector("select");
+ const submit = getByTestId("submit-button");
+
+ expect(select?.validity.valid).toBe(false);
+ expect(select?.validity.customError).toBe(true);
+ expect(trigger).toHaveAttribute("aria-describedby");
+ expect(select).toHaveAttribute("aria-invalid", "true");
+ expect(document.getElementById(trigger.getAttribute("aria-describedby")!)).toHaveTextContent(
+ "initial error",
+ );
+
+ await user.click(trigger);
+
+ let listboxItems = document.querySelectorAll("[role='option']");
+
+ await user.click(listboxItems[1]); // zebra
+
+ expect(select?.validity.valid).toBe(true);
+ expect(trigger).not.toHaveAttribute("aria-describedby");
+ expect(select).not.toHaveAttribute("aria-invalid");
+
+ await user.click(submit);
+
+ expect(select?.validity.valid).toBe(false);
+ expect(select?.validity.customError).toBe(true);
+ expect(trigger).toHaveAttribute("aria-describedby");
+ expect(select).toHaveAttribute("aria-invalid");
+ expect(document.getElementById(trigger.getAttribute("aria-describedby")!)).toHaveTextContent(
+ "new error",
+ );
+ });
});
});