80 lines
3.6 KiB
TypeScript
80 lines
3.6 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { readFileSync } from "node:fs";
|
|
import { mountHtml, renderComponent } from "../../test/src/index.ts";
|
|
import { uiComponentPath } from "../src/registry.ts";
|
|
|
|
const source = readFileSync(uiComponentPath("DatePicker"), "utf8");
|
|
|
|
test("calendar aligns leap February with Monday-first labels and disables out-of-range dates", async () => {
|
|
const dom = mountHtml(
|
|
await renderComponent(source, {
|
|
value: "2024-02-15",
|
|
firstDayOfWeek: 1,
|
|
min: "2024-02-10",
|
|
max: "2024-02-20",
|
|
}),
|
|
);
|
|
const days = dom.querySelectorAll(".wrn-next__calendar-grid button") as HTMLButtonElement[];
|
|
expect(days).toHaveLength(29);
|
|
expect(days[0].style.gridColumn).toBe("4");
|
|
expect(dom.querySelector(".wrn-next__calendar-weekdays")?.textContent).toContain("Mon");
|
|
expect(days[8].disabled).toBe(true);
|
|
expect(days[9].disabled).toBe(false);
|
|
expect(days[20].disabled).toBe(true);
|
|
expect(days[14].getAttribute("aria-pressed")).toBe("true");
|
|
expect(days[14].getAttribute("aria-label")).toContain("February");
|
|
});
|
|
|
|
test("calendar starts from an empty value, selects a date, and returns focus on Escape", async () => {
|
|
const dom = mountHtml(await renderComponent(source, { name: "date", value: "" }));
|
|
const trigger = dom.querySelector(".wrn-next__date-trigger") as HTMLButtonElement;
|
|
trigger.click();
|
|
const days = dom.querySelectorAll(".wrn-next__calendar-grid button") as HTMLButtonElement[];
|
|
days[0].click();
|
|
expect((dom.querySelector("input") as HTMLInputElement).value).toMatch(/^\d{4}-\d{2}-01$/);
|
|
const selected = dom.querySelector('button[aria-pressed="true"]') as HTMLButtonElement;
|
|
selected.focus();
|
|
selected.dispatchEvent(
|
|
new (dom.window as Window & typeof globalThis).KeyboardEvent("keydown", {
|
|
key: "ArrowRight",
|
|
bubbles: true,
|
|
}),
|
|
);
|
|
expect((dom.document.activeElement as HTMLElement)?.textContent).toBe("2");
|
|
dom.document.activeElement!.dispatchEvent(
|
|
new (dom.window as Window & typeof globalThis).KeyboardEvent("keydown", {
|
|
key: "Escape",
|
|
bubbles: true,
|
|
}),
|
|
);
|
|
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
|
expect(dom.document.activeElement).toBe(trigger);
|
|
});
|
|
|
|
test("calendar has 28 days in a non-leap February and cannot select while read-only", async () => {
|
|
const dom = mountHtml(await renderComponent(source, { value: "2025-02-15", readonly: true }));
|
|
const days = dom.querySelectorAll(".wrn-next__calendar-grid button") as HTMLButtonElement[];
|
|
expect(days).toHaveLength(28);
|
|
expect(Array.from(days).every((day) => day.disabled)).toBe(true);
|
|
days[0].click();
|
|
expect((dom.querySelector("input") as HTMLInputElement).value).toBe("2025-02-15");
|
|
});
|
|
|
|
test("calendar keeps native month and year controls aligned after opening and changing months", async () => {
|
|
const dom = mountHtml(await renderComponent(source, { value: "2026-09-20" }));
|
|
(dom.querySelector(".wrn-next__date-trigger") as HTMLButtonElement).click();
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
let selectors = dom.querySelectorAll(".wrn-next__date-selectors select") as HTMLSelectElement[];
|
|
expect(selectors[0].value).toBe("09");
|
|
expect(selectors[1].value).toBe("2026");
|
|
selectors[0].value = "02";
|
|
selectors[0].dispatchEvent(
|
|
new (dom.window as Window & typeof globalThis).Event("change", { bubbles: true }),
|
|
);
|
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
selectors = dom.querySelectorAll(".wrn-next__date-selectors select") as HTMLSelectElement[];
|
|
expect(selectors[0].value).toBe("02");
|
|
expect(selectors[1].value).toBe("2026");
|
|
expect(dom.querySelectorAll(".wrn-next__calendar-grid button")).toHaveLength(28);
|
|
});
|