Files
nxdns/admin/src/features/activity/search.test.ts
T
mokhtar fa323c7ed4
Gates / test (push) Successful in 1m40s
Gates / package (push) Successful in 3m58s
Gates / container (push) Successful in 14s
CI / gates (push) Successful in 12m51s
Gates / frontend (push) Successful in 1m18s
Gates / test-aarch64 (push) Successful in 6m57s
milestone 29: activity — history, live and policy simulation on one surface
query log, live and lookup merge into /activity. history filters live
in the url, so a pasted link or back/forward reproduces the exact
view; the result column separates servfail and nxdomain from success
in the list. live is follow-by-default with freeze, and a streamed
row opens its in-memory provenance detail — no correlation invented
for rows sqlite has not written. lookup survives as the current
policy simulation under /activity/test. investigation links carry
absolute bounds, and the diagnostics page now honors since/until
instead of ignoring them. the old routes are gone without aliases.
2026-08-22 10:52:56 +02:00

114 lines
3.0 KiB
TypeScript

import { validateActivitySearch, validateBlocked, validateMode, validateText, validateTimestamp } from "./search";
test("mode is the two-value union, defaulting to history", () => {
expect(validateMode("live")).toBe("live");
expect(validateMode("history")).toBe("history");
expect(validateMode(undefined)).toBe("history");
expect(validateMode("Live")).toBe("history");
expect(validateMode("")).toBe("history");
expect(validateMode(0)).toBe("history");
expect(validateMode(["live"])).toBe("history");
});
test("a bound is a safe integer or nothing at all", () => {
expect(validateTimestamp(1_700_000_000)).toBe(1_700_000_000);
expect(validateTimestamp(0)).toBe(0);
expect(validateTimestamp(-1)).toBe(-1);
});
test.each([
["a fraction", 1_700_000_000.5],
["Infinity", Number.POSITIVE_INFINITY],
["-Infinity", Number.NEGATIVE_INFINITY],
["NaN", Number.NaN],
["past the safe range", Number.MAX_SAFE_INTEGER + 1],
["1e21", 1e21],
["a numeric string", "1700000000"],
["an empty string", ""],
["null", null],
["undefined", undefined],
["a boolean", true],
["an array", [1_700_000_000]],
["a bigint", 1_700_000_000n],
])("a bound rejects %s", (_name, value) => {
expect(validateTimestamp(value)).toBeUndefined();
});
test("blocked keeps false, which is the allowed-only filter", () => {
expect(validateBlocked(true)).toBe(true);
expect(validateBlocked(false)).toBe(false);
});
test.each([
["the string true", "true"],
["the string false", "false"],
["1", 1],
["0", 0],
["null", null],
["undefined", undefined],
])("blocked rejects %s", (_name, value) => {
expect(validateBlocked(value)).toBeUndefined();
});
test("a text filter is trimmed, and an empty one is no filter", () => {
expect(validateText("ads.example")).toBe("ads.example");
expect(validateText(" ads.example ")).toBe("ads.example");
expect(validateText("")).toBeUndefined();
expect(validateText(" ")).toBeUndefined();
expect(validateText("\t\n")).toBeUndefined();
expect(validateText(42)).toBeUndefined();
expect(validateText(undefined)).toBeUndefined();
});
test("a whole search normalizes every field and drops nothing else in", () => {
expect(
validateActivitySearch({
mode: "live",
since: 1_700_000_000,
until: 1_700_000_600,
domain: " ads.example ",
client: "192.0.2.10",
blocked: false,
unknown: "kept out",
}),
).toEqual({
mode: "live",
since: 1_700_000_000,
until: 1_700_000_600,
domain: "ads.example",
client: "192.0.2.10",
blocked: false,
});
});
test("an empty search is history with no filters", () => {
expect(validateActivitySearch({})).toEqual({
mode: "history",
since: undefined,
until: undefined,
domain: undefined,
client: undefined,
blocked: undefined,
});
});
test("a search of junk applies nothing", () => {
expect(
validateActivitySearch({
mode: "HISTORY ",
since: "1700000000",
until: Number.POSITIVE_INFINITY,
domain: " ",
client: null,
blocked: "true",
}),
).toEqual({
mode: "history",
since: undefined,
until: undefined,
domain: undefined,
client: undefined,
blocked: undefined,
});
});