|
@@ -0,0 +1,88 @@
|
|
|
|
|
+/* @vitest-environment node */
|
|
|
|
|
+
|
|
|
|
|
+import { describe, it, expect } from "vitest";
|
|
|
|
|
+import {
|
|
|
|
|
+ isValidIsoDateYmd,
|
|
|
|
|
+ normalizeIsoDateYmdOrNull,
|
|
|
|
|
+ compareIsoDatesYmd,
|
|
|
|
|
+ isInvalidIsoDateRange,
|
|
|
|
|
+ formatIsoDateDe,
|
|
|
|
|
+ formatIsoDateRangeLabelDe,
|
|
|
|
|
+} from "./dateRange.js";
|
|
|
|
|
+
|
|
|
|
|
+describe("lib/frontend/search/dateRange", () => {
|
|
|
|
|
+ describe("isValidIsoDateYmd", () => {
|
|
|
|
|
+ it("accepts strict YYYY-MM-DD", () => {
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-12-01")).toBe(true);
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-01-31")).toBe(true);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it("rejects invalid formats and obvious invalid ranges", () => {
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025/12/01")).toBe(false);
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-1-01")).toBe(false);
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-01-1")).toBe(false);
|
|
|
|
|
+
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-13-01")).toBe(false);
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-00-01")).toBe(false);
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-12-00")).toBe(false);
|
|
|
|
|
+ expect(isValidIsoDateYmd("2025-12-32")).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe("normalizeIsoDateYmdOrNull", () => {
|
|
|
|
|
+ it("trims and returns null for invalid values", () => {
|
|
|
|
|
+ expect(normalizeIsoDateYmdOrNull(" 2025-12-01 ")).toBe("2025-12-01");
|
|
|
|
|
+ expect(normalizeIsoDateYmdOrNull("")).toBe(null);
|
|
|
|
|
+ expect(normalizeIsoDateYmdOrNull("2025/12/01")).toBe(null);
|
|
|
|
|
+ expect(normalizeIsoDateYmdOrNull(null)).toBe(null);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe("compareIsoDatesYmd", () => {
|
|
|
|
|
+ it("compares lexicographically", () => {
|
|
|
|
|
+ expect(compareIsoDatesYmd("2025-01-01", "2025-01-01")).toBe(0);
|
|
|
|
|
+ expect(compareIsoDatesYmd("2025-01-01", "2025-01-02")).toBe(-1);
|
|
|
|
|
+ expect(compareIsoDatesYmd("2025-12-31", "2025-01-01")).toBe(1);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe("isInvalidIsoDateRange", () => {
|
|
|
|
|
+ it("is false for open ranges and equal dates", () => {
|
|
|
|
|
+ expect(isInvalidIsoDateRange("2025-12-01", null)).toBe(false);
|
|
|
|
|
+ expect(isInvalidIsoDateRange(null, "2025-12-31")).toBe(false);
|
|
|
|
|
+ expect(isInvalidIsoDateRange("2025-12-01", "2025-12-01")).toBe(false);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it("is true when from > to", () => {
|
|
|
|
|
+ expect(isInvalidIsoDateRange("2025-12-31", "2025-12-01")).toBe(true);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe("formatIsoDateDe / formatIsoDateRangeLabelDe", () => {
|
|
|
|
|
+ it("formats single dates as DD.MM.YYYY", () => {
|
|
|
|
|
+ expect(formatIsoDateDe("2025-12-01")).toBe("01.12.2025");
|
|
|
|
|
+ expect(formatIsoDateDe("invalid")).toBe(null);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it("formats date range labels", () => {
|
|
|
|
|
+ expect(
|
|
|
|
|
+ formatIsoDateRangeLabelDe({ from: "2025-12-01", to: "2025-12-31" })
|
|
|
|
|
+ ).toBe("01.12.2025 – 31.12.2025");
|
|
|
|
|
+
|
|
|
|
|
+ // Same day => single day label (and this must be treated as a valid one-day search)
|
|
|
|
|
+ expect(
|
|
|
|
|
+ formatIsoDateRangeLabelDe({ from: "2025-12-01", to: "2025-12-01" })
|
|
|
|
|
+ ).toBe("01.12.2025");
|
|
|
|
|
+
|
|
|
|
|
+ expect(formatIsoDateRangeLabelDe({ from: "2025-12-01", to: null })).toBe(
|
|
|
|
|
+ "ab 01.12.2025"
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ expect(formatIsoDateRangeLabelDe({ from: null, to: "2025-12-31" })).toBe(
|
|
|
|
|
+ "bis 31.12.2025"
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ expect(formatIsoDateRangeLabelDe({ from: null, to: null })).toBe(null);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+});
|