A YouTube search is `?yt=<term>` (+ `ytn` for a non-default count), so a reload, a link or Back/Forward reopens it. It runs by itself only where it costs no quota: the free page scrape, a search asked for in this document, or results still cached. An API search reopened any other way shows its term and waits for "Search YouTube again". Home's time budget is `hb`; the question's draw stays on the history entry. An e2e spec opens every page's bookmark in a fresh browser context; CLAUDE.md and docs/development.md name the module URL codec as the place for view state.
32 lines
1.3 KiB
TypeScript
32 lines
1.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { ytCountFrom, ytSearchFrom, ytSearchParams } from "./ytSearchUrlState";
|
|
|
|
const p = (q: string) => new URLSearchParams(q);
|
|
|
|
describe("the live YouTube search's address", () => {
|
|
it("reads the term, trimmed; a blank one names no search", () => {
|
|
expect(ytSearchFrom(p("yt=%20lofi%20"))).toBe("lofi");
|
|
expect(ytSearchFrom(p("yt=%20%20"))).toBeNull();
|
|
expect(ytSearchFrom(p("q=lofi"))).toBeNull();
|
|
});
|
|
|
|
it("reads one of the offered counts, else the default", () => {
|
|
expect(ytCountFrom(p("ytn=60"))).toBe(60);
|
|
expect(ytCountFrom(p("ytn=61"))).toBe(20);
|
|
expect(ytCountFrom(p("ytn=x"))).toBe(20);
|
|
expect(ytCountFrom(p(""))).toBe(20);
|
|
});
|
|
|
|
it("writes the count only off its default, and nothing with no search", () => {
|
|
expect(ytSearchParams("lofi", 40)).toEqual({ yt: "lofi", ytn: "40" });
|
|
expect(ytSearchParams("lofi", 20)).toEqual({ yt: "lofi", ytn: null });
|
|
expect(ytSearchParams(null, 40)).toEqual({ yt: null, ytn: null });
|
|
});
|
|
|
|
it("round-trips", () => {
|
|
const q = new URLSearchParams();
|
|
for (const [k, v] of Object.entries(ytSearchParams("lofi beats", 100))) if (v) q.set(k, v);
|
|
expect([ytSearchFrom(q), ytCountFrom(q)]).toEqual(["lofi beats", 100]);
|
|
});
|
|
});
|