| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /* @vitest-environment node */
- import { describe, it, expect } from "vitest";
- import {
- SEARCH_SCOPE,
- SEARCH_LIMITS,
- DEFAULT_SEARCH_LIMIT,
- parseBranchesCsv,
- serializeBranchesCsv,
- parseSearchUrlState,
- serializeSearchUrlState,
- } from "./urlState.js";
- describe("lib/frontend/search/urlState", () => {
- describe("parseBranchesCsv / serializeBranchesCsv", () => {
- it("parses CSV into a unique, trimmed list", () => {
- expect(parseBranchesCsv(" NL06, NL20 ,NL06,, ")).toEqual([
- "NL06",
- "NL20",
- ]);
- });
- it("serializes branches into CSV with stable order and dedupe", () => {
- expect(serializeBranchesCsv(["NL20", " NL06 ", "NL20"])).toBe(
- "NL20,NL06"
- );
- });
- it("returns null when serializing empty branches", () => {
- expect(serializeBranchesCsv([])).toBe(null);
- expect(serializeBranchesCsv(null)).toBe(null);
- });
- });
- describe("parseSearchUrlState", () => {
- it("defaults to SINGLE with routeBranch when no params are present", () => {
- const sp = new URLSearchParams();
- const state = parseSearchUrlState(sp, { routeBranch: "NL01" });
- expect(state).toEqual({
- q: null,
- scope: SEARCH_SCOPE.SINGLE,
- branch: "NL01",
- branches: [],
- limit: DEFAULT_SEARCH_LIMIT,
- from: null,
- to: null,
- });
- });
- it("parses SINGLE with explicit branch param", () => {
- const sp = new URLSearchParams({ q: " test ", branch: "NL02" });
- const state = parseSearchUrlState(sp, { routeBranch: "NL01" });
- expect(state.scope).toBe(SEARCH_SCOPE.SINGLE);
- expect(state.q).toBe("test");
- expect(state.branch).toBe("NL02");
- expect(state.branches).toEqual([]);
- expect(SEARCH_LIMITS.includes(state.limit)).toBe(true);
- });
- it("parses ALL when scope=all is set (highest precedence)", () => {
- const sp = new URLSearchParams({
- q: "x",
- scope: "all",
- branch: "NL01",
- branches: "NL06,NL20",
- limit: "200",
- });
- const state = parseSearchUrlState(sp, { routeBranch: "NL99" });
- expect(state).toEqual({
- q: "x",
- scope: SEARCH_SCOPE.ALL,
- branch: null,
- branches: [],
- limit: 200,
- from: null,
- to: null,
- });
- });
- it("parses MULTI when scope=multi is set", () => {
- const sp = new URLSearchParams({
- q: " reifen ",
- scope: "multi",
- branches: "NL06, NL20, NL06",
- limit: "50",
- });
- const state = parseSearchUrlState(sp, { routeBranch: "NL01" });
- expect(state.scope).toBe(SEARCH_SCOPE.MULTI);
- expect(state.q).toBe("reifen");
- expect(state.branch).toBe(null);
- expect(state.branches).toEqual(["NL06", "NL20"]);
- expect(state.limit).toBe(50);
- });
- it("parses MULTI when branches=... is present even without scope", () => {
- const sp = new URLSearchParams({
- q: "x",
- branches: "NL06,NL20",
- });
- const state = parseSearchUrlState(sp, { routeBranch: "NL01" });
- expect(state.scope).toBe(SEARCH_SCOPE.MULTI);
- expect(state.branches).toEqual(["NL06", "NL20"]);
- expect(state.limit).toBe(DEFAULT_SEARCH_LIMIT);
- });
- it("keeps from/to when provided", () => {
- const sp = new URLSearchParams({
- q: "x",
- branch: "NL01",
- from: "2025-12-01",
- to: "2025-12-31",
- limit: "200",
- });
- const state = parseSearchUrlState(sp, { routeBranch: "NL01" });
- expect(state.from).toBe("2025-12-01");
- expect(state.to).toBe("2025-12-31");
- expect(state.limit).toBe(200);
- });
- it("falls back to default limit for invalid values", () => {
- const sp = new URLSearchParams({ q: "x", branch: "NL01", limit: "999" });
- const state = parseSearchUrlState(sp, { routeBranch: "NL01" });
- expect(state.limit).toBe(DEFAULT_SEARCH_LIMIT);
- });
- });
- describe("serializeSearchUrlState", () => {
- it("serializes SINGLE as q + branch (no scope param)", () => {
- const qs = serializeSearchUrlState({
- q: "bridgestone",
- scope: SEARCH_SCOPE.SINGLE,
- branch: "NL01",
- limit: DEFAULT_SEARCH_LIMIT,
- });
- expect(qs).toBe("q=bridgestone&branch=NL01");
- });
- it("serializes MULTI as q + scope=multi + branches", () => {
- const qs = serializeSearchUrlState({
- q: "reifen",
- scope: SEARCH_SCOPE.MULTI,
- branches: ["NL06", "NL20"],
- limit: DEFAULT_SEARCH_LIMIT,
- });
- expect(qs).toBe("q=reifen&scope=multi&branches=NL06%2CNL20");
- });
- it("serializes ALL as q + scope=all", () => {
- const qs = serializeSearchUrlState({
- q: "x",
- scope: SEARCH_SCOPE.ALL,
- limit: DEFAULT_SEARCH_LIMIT,
- });
- expect(qs).toBe("q=x&scope=all");
- });
- it("includes limit when non-default", () => {
- const qs = serializeSearchUrlState({
- q: "x",
- scope: SEARCH_SCOPE.SINGLE,
- branch: "NL01",
- limit: 200,
- });
- expect(qs).toBe("q=x&branch=NL01&limit=200");
- });
- it("includes from/to when present (future-proof for RHL-025)", () => {
- const qs = serializeSearchUrlState({
- q: "x",
- scope: SEARCH_SCOPE.SINGLE,
- branch: "NL01",
- limit: 200,
- from: "2025-12-01",
- to: "2025-12-31",
- });
- expect(qs).toBe(
- "q=x&branch=NL01&limit=200&from=2025-12-01&to=2025-12-31"
- );
- });
- });
- });
|