// The activity page's view in the address bar: a link carries the tab and every filter, a hand-edited // value the API would refuse degrades to "no filter", a filter at its default leaves no key behind, // and a link to a page this one replaced opens that page's tab. import { describe, expect, it } from "vitest"; import { ACTIVITY_KEYS, activityParamsToState, activityParamUpdates, DEFAULT_ACTIVITY_STATE, sinceOf, type ActivityUrlState, } from "./activityUrlState"; const params = (updates: Record) => new URLSearchParams(Object.entries(updates).filter((e): e is [string, string] => e[1] !== null)); describe("activityUrlState", () => { it("round-trips the tab and every filter", () => { const state: ActivityUrlState = { tab: "admin", window: "30d", user: "none", q: "100% done", job: "channel_backfill", status: "interrupted", action: "config_set", }; expect(activityParamsToState(params(activityParamUpdates(state)))).toEqual(state); }); it("leaves no key for a filter at its default, and opens on the runs of the last 7 days", () => { expect( Object.values(activityParamUpdates(DEFAULT_ACTIVITY_STATE)).every((v) => v === null), ).toBe(true); expect([DEFAULT_ACTIVITY_STATE.tab, DEFAULT_ACTIVITY_STATE.window]).toEqual(["runs", "7d"]); }); it("drops a value the API would refuse instead of sending it", () => { const state = activityParamsToState( new URLSearchParams( "at=everything&aw=1y&au=me&rjob=Not-A-Job&rst=finished&aact=DROP%20TABLE", ), ); expect(state).toEqual(DEFAULT_ACTIVITY_STATE); }); it("opens the tab of the page a link still names", () => { expect(activityParamsToState(new URLSearchParams("page=audit")).tab).toBe("admin"); expect(activityParamsToState(new URLSearchParams("page=logs")).tab).toBe("logs"); // A tab the link names wins over the retired page's. expect(activityParamsToState(new URLSearchParams("page=logs&at=quota")).tab).toBe("quota"); }); it("clears its own keys and the server log's on a page change", () => { expect(ACTIVITY_KEYS).toEqual(expect.arrayContaining(["at", "aw", "au", "aq", "rjob", "lreq"])); }); it("starts the window that many hours back", () => { const now = Date.UTC(2026, 9, 18, 12); expect(sinceOf("24h", now)).toBe("2026-10-17T12:00:00.000Z"); expect(sinceOf("90d", now)).toBe("2026-07-20T12:00:00.000Z"); }); });