import { describe, expect, it } from "vitest"; import { DEFAULT_LIST_STATE, parseListState, serializeListState, toQueryString, withRange } from "@/lib/url-state"; const parse = (qs: string) => parseListState(new URLSearchParams(qs)); describe("parseListState", () => { it("defaults to every calendar except Birthdays, upcoming, by start", () => { expect(parse("")).toEqual({ calendarIds: [1, 2, 4, 3], range: "future", sort: "start_asc", query: "" }); }); it("reads calendars by slug, dropping unknown ones and duplicates", () => { expect(parse("cal=choir,nope,birthdays,choir").calendarIds).toEqual([4, 5]); }); it("keeps an explicitly empty selection", () => { expect(parse("cal=").calendarIds).toEqual([]); }); it("sorts the past newest first by default", () => { expect(parse("range=past").sort).toBe("start_desc"); expect(parse("range=past&sort=start_asc").sort).toBe("start_asc"); }); it("falls back to defaults for unknown range and sort", () => { expect(parse("range=soon&sort=random")).toMatchObject({ range: "future", sort: "start_asc" }); }); it("reads range, sort and search", () => { expect(parse("range=past&sort=created_desc&q=probe")).toMatchObject({ range: "past", sort: "created_desc", query: "probe", }); }); }); describe("serializeListState", () => { it("leaves the default view out of the URL", () => { expect(serializeListState(DEFAULT_LIST_STATE).toString()).toBe(""); }); it("treats the default calendars in another order as the default", () => { expect(serializeListState({ ...DEFAULT_LIST_STATE, calendarIds: [3, 4, 2, 1] }).toString()).toBe(""); }); it("round-trips a non-default view", () => { const state = { calendarIds: [5], range: "all" as const, sort: "start_desc" as const, query: "geburtstag" }; expect(parseListState(serializeListState(state))).toEqual(state); }); it("writes an empty selection as cal=", () => { expect(serializeListState({ ...DEFAULT_LIST_STATE, calendarIds: [] }).toString()).toBe("cal="); }); }); describe("withRange", () => { it("swaps a default sort for the new range's default, keeping the URL clean", () => { const past = withRange(DEFAULT_LIST_STATE, "past"); expect(past.sort).toBe("start_desc"); expect(serializeListState(past).toString()).toBe("range=past"); expect(withRange(past, "all").sort).toBe("start_asc"); }); it("keeps a sort someone picked", () => { const picked = { ...DEFAULT_LIST_STATE, sort: "created_desc" as const }; expect(withRange(picked, "past").sort).toBe("created_desc"); }); }); describe("toQueryString", () => { it("keeps the calendar list readable but escapes commas in the search", () => { const qs = toQueryString({ ...DEFAULT_LIST_STATE, calendarIds: [1, 4], query: "a,b" }); expect(qs).toBe("cal=public,choir&q=a%2Cb"); expect(parseListState(new URLSearchParams(qs))).toMatchObject({ calendarIds: [1, 4], query: "a,b" }); }); });