src/lib/date-input.test.ts
Rama main · réplica de lectura del repositorio original.
import { describe, expect, it } from "vitest";
import { parseDateInput, parseDateTimeInput } from "./date-input";
describe("parseDateInput", () => {
it("reads the canonical form back unchanged", () => {
expect(parseDateInput("2024-06-01")).toBe("2024-06-01");
});
it("accepts loose separators and single digits", () => {
for (const text of [
"2024-6-1",
"2024/06/01",
"2024.6.01",
"2024 06 01",
"20240601",
" 2024-06-01 ",
]) {
expect(parseDateInput(text)).toBe("2024-06-01");
}
});
it("refuses a day-first or month-first date rather than guessing", () => {
// "01/06/2024" is two different days depending on who typed it, and a
// picker that picks one stores the wrong dive date silently.
expect(parseDateInput("01/06/2024")).toBeNull();
expect(parseDateInput("06/01/2024")).toBeNull();
expect(parseDateInput("1 June 2024")).toBeNull();
});
it("refuses a day the month does not have", () => {
expect(parseDateInput("2024-06-31")).toBeNull();
expect(parseDateInput("2025-02-29")).toBeNull();
expect(parseDateInput("2024-02-29")).toBe("2024-02-29");
expect(parseDateInput("2000-02-29")).toBe("2000-02-29");
expect(parseDateInput("1900-02-29")).toBeNull();
});
it("refuses an impossible month or day", () => {
expect(parseDateInput("2024-13-01")).toBeNull();
expect(parseDateInput("2024-00-01")).toBeNull();
expect(parseDateInput("2024-06-00")).toBeNull();
});
it("refuses a half-typed date", () => {
expect(parseDateInput("2")).toBeNull();
expect(parseDateInput("2024-")).toBeNull();
expect(parseDateInput("2024-06")).toBeNull();
expect(parseDateInput("2024-06-011")).toBeNull();
});
it("tells a cleared field from an unreadable one", () => {
expect(parseDateInput("")).toBe("");
expect(parseDateInput(" ")).toBe("");
expect(parseDateInput("soon")).toBeNull();
});
});
describe("parseDateTimeInput", () => {
it("reads a date and time in either ISO separator", () => {
expect(parseDateTimeInput("2024-06-01 10:04:47")).toBe(
"2024-06-01 10:04:47",
);
expect(parseDateTimeInput("2024-06-01T10:04:47")).toBe(
"2024-06-01 10:04:47",
);
});
it("fills in the parts the diver left off", () => {
expect(parseDateTimeInput("2024-06-01 10:04")).toBe("2024-06-01 10:04:00");
expect(parseDateTimeInput("2024-6-1 9:4")).toBe("2024-06-01 09:04:00");
expect(parseDateTimeInput("2024-06-01")).toBe("2024-06-01 00:00:00");
});
it("drops a fraction the field has no room for", () => {
expect(parseDateTimeInput("2024-06-01T10:04:47.910")).toBe(
"2024-06-01 10:04:47",
);
});
it("refuses a string carrying a UTC offset", () => {
// The offset is the dive's own zone and lives in its own control; honouring
// it here is impossible and dropping it would move the dive by that many
// hours without saying so.
expect(parseDateTimeInput("2024-06-01T10:04:47+02:00")).toBeNull();
expect(parseDateTimeInput("2024-06-01T10:04:47Z")).toBeNull();
});
it("refuses an out-of-range time rather than clamping it", () => {
expect(parseDateTimeInput("2024-06-01 25:00:00")).toBeNull();
expect(parseDateTimeInput("2024-06-01 10:60:00")).toBeNull();
expect(parseDateTimeInput("2024-06-01 10:04:60")).toBeNull();
});
it("applies the same calendar rules as the date-only field", () => {
expect(parseDateTimeInput("2025-02-29 10:00")).toBeNull();
expect(parseDateTimeInput("")).toBe("");
expect(parseDateTimeInput("tomorrow")).toBeNull();
});
});