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,
	});
});
