import { fireEvent, render } from "@testing-library/vue"; import { h } from "vue"; import { describe, expect, it } from "vitest"; import DsCheckbox from "../src/components/forms/DsCheckbox.vue"; import DsRadioGroup from "../src/components/forms/DsRadioGroup.vue"; import DsTextInput from "../src/components/forms/DsTextInput.vue"; describe("form controls", () => { it("associates labels, help, errors and updates v-model", async () => { const view = render(DsTextInput, { props: { label: "Correo", description: "Usaremos tu correo de trabajo.", error: "El correo no es válido.", modelValue: "", }, }); const input = view.getByLabelText("Correo (Opcional)") as HTMLInputElement; expect(input.getAttribute("aria-invalid")).toBe("true"); expect(input.getAttribute("aria-describedby")).toContain("description"); expect(input.getAttribute("aria-describedby")).toContain("error"); await fireEvent.update(input, "omar@example.com"); expect(view.emitted()["update:modelValue"]?.[0]).toEqual([ "omar@example.com", ]); }); it("supports a boolean v-model and disabled state", async () => { const view = render(DsCheckbox, { props: { label: "Acepto", modelValue: false }, }); await fireEvent.click(view.getByRole("checkbox", { name: "Acepto" })); expect(view.emitted()["update:modelValue"]?.[0]).toEqual([true]); await view.rerender({ disabled: true }); expect((view.getByRole("checkbox") as HTMLInputElement).disabled).toBe( true, ); }); it("associates checkbox descriptions and errors at the same time", () => { const view = render(DsCheckbox, { props: { label: "Acepto", description: "Lee las condiciones.", error: "Debes aceptar.", }, }); const checkbox = view.getByRole("checkbox"); const describedBy = checkbox.getAttribute("aria-describedby") ?? ""; expect(describedBy).toContain("description"); expect(describedBy).toContain("error"); expect(checkbox.getAttribute("aria-invalid")).toBe("true"); }); it("gives radio groups unique descriptions and exposes invalid state", () => { const props = { legend: "Plan", name: "plan", options: [{ label: "Profesional", value: "pro" }], description: "Elige un plan.", error: "Selecciona una opción.", }; const view = render({ setup: () => () => h("div", [h(DsRadioGroup, props), h(DsRadioGroup, props)]), }); const groups = view.getAllByRole("group"); const describedBy = groups.map((group) => group.getAttribute("aria-describedby"), ); expect(describedBy[0]).not.toBe(describedBy[1]); expect(describedBy[0]).toContain("description"); expect(describedBy[0]).toContain("error"); expect(view.getAllByRole("radio")[0]?.getAttribute("aria-invalid")).toBe( "true", ); }); });