PettyUI/packages/core/tests/form.test.ts
Mats Bosson bf576905a7
Some checks are pending
CI / check (push) Waiting to run
All components, schemas, tests, MCP, and showcase
- 51 headless Web Components (45 core + 6 animation)
- Shared helpers: emit(), part(), listen(), wireLabel(), initialValue()
- Zero `new CustomEvent` or `static #counter` — all use shared utils
- Zod schemas for all 44 core components
- MCP package with discover, inspect, compose, validate tools
- Showcase with Aperture Science theme, M3 Expressive motion
- 81 tests passing, TypeScript strict mode clean
- Signals (~500B), SPA router (~400B), zero dependencies
2026-03-31 20:21:41 +07:00

62 lines
2.4 KiB
TypeScript

import { describe, it, expect, beforeEach } from "vitest";
import { PettyForm } from "../src/components/form/index";
import { h } from "./helpers";
describe("petty-form", () => {
let el: PettyForm;
beforeEach(() => {
document.body.textContent = "";
el = document.createElement("petty-form") as PettyForm;
const label = h("label", { "data-part": "label" }, "Email");
const input = h("input", { "data-part": "control", type: "email", name: "email" });
const error = h("span", { "data-part": "error" });
const field = h("petty-form-field", { name: "email" }, label, input, error);
const submit = h("button", { type: "submit" }, "Submit");
const form = h("form", {}, field, submit);
el.appendChild(form);
document.body.appendChild(el);
});
it("registers the custom elements", () => {
expect(customElements.get("petty-form")).toBe(PettyForm);
expect(customElements.get("petty-form-field")).toBeDefined();
});
it("sets novalidate on the form", () => {
const form = el.querySelector("form")!;
expect(form.hasAttribute("novalidate")).toBe(true);
});
it("dispatches petty-submit with form data when no schema set", () => {
let detail: { data: Record<string, unknown> } | null = null;
el.addEventListener("petty-submit", ((e: CustomEvent) => {
detail = e.detail;
}) as EventListener);
const input = el.querySelector("input") as HTMLInputElement;
input.value = "test@example.com";
const form = el.querySelector("form")!;
form.dispatchEvent(new Event("submit", { cancelable: true }));
expect(detail!.data.email).toBe("test@example.com");
});
it("dispatches petty-invalid on schema failure and shows error", () => {
const mockSchema = {
safeParse: () => ({
success: false,
error: { issues: [{ path: ["email"], message: "Invalid email" }] },
}),
};
el.setSchema(mockSchema);
let detail: { errors: Array<{ path: Array<string | number>; message: string }> } | null = null;
el.addEventListener("petty-invalid", ((e: CustomEvent) => {
detail = e.detail;
}) as EventListener);
const form = el.querySelector("form")!;
form.dispatchEvent(new Event("submit", { cancelable: true }));
expect(detail!.errors[0].message).toBe("Invalid email");
expect(el.querySelector("[data-part=error]")!.textContent).toBe("Invalid email");
expect(el.querySelector("[data-part=control]")!.getAttribute("aria-invalid")).toBe("true");
});
});