Mats Bosson 894df74d7f DatePicker component
Composes Calendar inside a floating dropdown anchored to an input, with Intl locale formatting, controlled/uncontrolled date+open state, createDismiss for outside-click handling, and hidden input for form submission.
2026-03-29 21:20:09 +07:00

101 lines
3.3 KiB
TypeScript

import { fireEvent, render, screen } from "@solidjs/testing-library";
import { describe, expect, it, vi } from "vitest";
import { DatePicker } from "../../../src/components/date-picker/index";
import { DatePickerRootPropsSchema, DatePickerMeta } from "../../../src/components/date-picker/index";
function renderPicker(props: Record<string, unknown> = {}) {
return render(() => (
<DatePicker {...props}>
<DatePicker.Input data-testid="input" />
<DatePicker.Trigger data-testid="trigger">Open</DatePicker.Trigger>
<DatePicker.Content data-testid="content">
<span>Calendar goes here</span>
</DatePicker.Content>
</DatePicker>
));
}
describe("DatePicker — rendering", () => {
it("renders input with placeholder", () => {
renderPicker();
const input = screen.getByTestId("input") as HTMLInputElement;
expect(input.placeholder).toBe("Select date");
});
it("renders custom placeholder", () => {
renderPicker({ placeholder: "Pick a date" });
const input = screen.getByTestId("input") as HTMLInputElement;
expect(input.placeholder).toBe("Pick a date");
});
it("shows formatted date when value set", () => {
renderPicker({ value: "2024-01-15" });
const input = screen.getByTestId("input") as HTMLInputElement;
expect(input.value).toMatch(/january/i);
expect(input.value).toMatch(/15/);
expect(input.value).toMatch(/2024/);
});
it("content hidden when closed", () => {
renderPicker();
expect(screen.queryByTestId("content")).toBeNull();
});
});
describe("DatePicker — open/close", () => {
it("trigger click opens content", () => {
renderPicker();
fireEvent.click(screen.getByTestId("trigger"));
expect(screen.getByTestId("content")).toBeTruthy();
});
it("input click opens content", () => {
renderPicker();
fireEvent.click(screen.getByTestId("input"));
expect(screen.getByTestId("content")).toBeTruthy();
});
it("renders open when defaultOpen is true", () => {
renderPicker({ defaultOpen: true });
expect(screen.getByTestId("content")).toBeTruthy();
});
it("controlled open state shows content", () => {
renderPicker({ open: true, onOpenChange: vi.fn() });
expect(screen.getByTestId("content")).toBeTruthy();
});
it("open content has role=dialog", () => {
renderPicker({ defaultOpen: true });
expect(screen.getByRole("dialog")).toBeTruthy();
});
});
describe("DatePicker — schema and meta", () => {
it("schema validates valid ISO date", () => {
expect(DatePickerRootPropsSchema.safeParse({ value: "2024-06-01" }).success).toBe(true);
});
it("schema rejects non-string value", () => {
expect(DatePickerRootPropsSchema.safeParse({ value: 20240601 }).success).toBe(false);
});
it("schema accepts all optional fields absent", () => {
expect(DatePickerRootPropsSchema.safeParse({}).success).toBe(true);
});
it("meta has correct name", () => {
expect(DatePickerMeta.name).toBe("DatePicker");
});
it("meta contains required parts", () => {
expect(DatePickerMeta.parts).toContain("Root");
expect(DatePickerMeta.parts).toContain("Input");
expect(DatePickerMeta.parts).toContain("Content");
});
it("meta lists Calendar as a part", () => {
expect(DatePickerMeta.parts).toContain("Calendar");
});
});