import { describe, expect, it } from "vitest";
import {
isRedirect,
parseDiffRoute,
parseInterdiffRoute,
parseRange,
versionSegment,
type PullView
} from "#lib/api/pullRoute.ts";
const versions = [
{ base: "b0", head: "h0" },
{ base: "b1", head: "h1" }
];
// dispatches on `..` the way the loader does
const view = (versionParam: string, rangeParam?: string): PullView => {
const result = versionParam.includes("..")
? parseInterdiffRoute(versions, versionParam, rangeParam)
: parseDiffRoute(versions, versionParam, rangeParam);
if (isRedirect(result)) throw new Error(`unexpected redirect: ${result.redirect}`);
return result;
};
describe("parseRange", () => {
it("accepts every shape the appview accepts", () => {
expect(parseRange("")).toEqual({ base: "", head: "" });
expect(parseRange(" ")).toEqual({ base: "", head: "" });
expect(parseRange("abc")).toEqual({ base: "", head: "abc" });
expect(parseRange("a..b")).toEqual({ base: "a", head: "b" });
expect(parseRange("..b")).toEqual({ base: "", head: "b" });
expect(parseRange("a..")).toEqual({ base: "a", head: "" });
});
it("rejects empty and multi ranges", () => {
expect(parseRange("..")).toBeNull();
expect(parseRange("a...b")).toBeNull();
expect(parseRange("a..b..c")).toBeNull();
});
});
describe("parseDiffRoute", () => {
it("resolves latest and numbers to the version's own ends", () => {
expect(view("latest")).toEqual({ mode: "diff", version: 1, base: "b1", head: "h1" });
expect(view("0")).toMatchObject({ version: 0, base: "b0", head: "h0" });
});
it("takes an explicit range, and the base/head magic words", () => {
expect(view("1", "c1..c2")).toMatchObject({ base: "c1", head: "c2" });
// a bare rev is a head, and the words fall back to the version's ends
expect(view("1", "c2")).toMatchObject({ base: "b1", head: "c2" });
expect(view("1", "base..head")).toMatchObject({ base: "b1", head: "h1" });
});
it("resolves an empty version list instead of bouncing latest back to itself", () => {
expect(parseDiffRoute([], "latest")).toEqual({
mode: "diff",
version: 0,
base: "",
head: ""
});
});
it("redirects a bad version to latest and a bad range to the version", () => {
expect(parseDiffRoute(versions, "9")).toEqual({ redirect: "latest" });
expect(parseDiffRoute(versions, "foo")).toEqual({ redirect: "latest" });
expect(parseDiffRoute(versions, "-1")).toEqual({ redirect: "latest" });
expect(parseDiffRoute(versions, "1", "a..b..c")).toEqual({ redirect: "version" });
});
});
describe("parseInterdiffRoute", () => {
it("parses both versions, resolves their ends, and takes the change filter", () => {
expect(view("0..1")).toEqual({
mode: "interdiff",
oldVersion: 0,
version: 1,
from: { base: "b0", head: "h0" },
to: { base: "b1", head: "h1" },
changeId: ""
});
expect(view("0..1", "all")).toMatchObject({ changeId: "" });
expect(view("0..1", "kmzwvxqo")).toMatchObject({ changeId: "kmzwvxqo" });
});
it("bounds-checks both sides instead of panicking", () => {
expect(parseInterdiffRoute(versions, "0..9")).toEqual({ redirect: "latest" });
expect(parseInterdiffRoute(versions, "foo..1")).toEqual({ redirect: "latest" });
expect(parseInterdiffRoute(versions, "..1")).toEqual({ redirect: "latest" });
});
});
describe("versionSegment", () => {
it("parses back to the same view", () => {
for (const segment of ["0", "1", "0..1", "1..1"]) {
expect(versionSegment(view(segment))).toBe(segment);
}
});
it("pins latest to its number", () => {
expect(versionSegment(view("latest"))).toBe("1");
});
});