app/utils/history.test.ts
Rama main · réplica de lectura del repositorio original.
import type { Location } from "history";
import history, { patchLocation, toLocationDescriptor } from "./history";
import {
getSplitPath,
initSplitViewNavigation,
setFocusedSplitPane,
withoutSplitViewNavigation,
} from "./splitView";
describe("patchLocation", () => {
const location: Location = {
pathname: "/doc/my-doc",
search: "?foo=bar",
hash: "#one",
state: { sidebarContext: "starred-123" },
key: "abc123",
};
it("carries over the safe fields and applies the patch", () => {
expect(patchLocation(location, { hash: "#two" })).toEqual({
pathname: "/doc/my-doc",
search: "?foo=bar",
hash: "#two",
state: { sidebarContext: "starred-123" },
});
});
it("does not carry over internal fields such as key", () => {
expect(patchLocation(location, {})).not.toHaveProperty("key");
});
it("can override multiple fields at once", () => {
expect(
patchLocation(location, { search: "?q=1", hash: "#three" })
).toMatchObject({ search: "?q=1", hash: "#three" });
});
});
describe("toLocationDescriptor", () => {
it("parses a string path", () => {
expect(toLocationDescriptor("/doc/my-doc?foo=bar#hash")).toMatchObject({
pathname: "/doc/my-doc",
search: "?foo=bar",
hash: "#hash",
});
});
it("attaches state to a string path", () => {
expect(
toLocationDescriptor("/doc/my-doc", { restore: true })
).toMatchObject({
pathname: "/doc/my-doc",
state: { restore: true },
});
});
it("returns location descriptor objects unchanged", () => {
const descriptor = { pathname: "/doc/my-doc" };
expect(toLocationDescriptor(descriptor)).toBe(descriptor);
});
});
describe("split view navigation", () => {
const navigate = (path: string) => {
withoutSplitViewNavigation(() => history.replace(path));
};
beforeEach(() => {
setFocusedSplitPane("primary");
navigate("/home");
});
it("leaves navigation unchanged when no split view is open", () => {
history.push("/doc/my-doc");
expect(history.location.pathname).toEqual("/doc/my-doc");
expect(history.location.search).toEqual("");
});
it("preserves the split parameter when the primary pane navigates", () => {
navigate("/doc/my-doc?split=%2Fdoc%2Fother-doc");
history.push("/doc/third-doc");
expect(history.location.pathname).toEqual("/doc/third-doc");
expect(getSplitPath(history.location.search)).toEqual("/doc/other-doc");
});
it("preserves the split parameter on replace", () => {
navigate("/search?split=%2Fdoc%2Fother-doc");
history.replace("/search?q=foo");
expect(history.location.pathname).toEqual("/search");
expect(history.location.search).toContain("q=foo");
expect(getSplitPath(history.location.search)).toEqual("/doc/other-doc");
});
it("directs pushes to the secondary pane when it has focus", () => {
navigate("/doc/my-doc?split=%2Fdoc%2Fother-doc");
setFocusedSplitPane("secondary");
history.push("/doc/third-doc");
expect(history.location.pathname).toEqual("/doc/my-doc");
expect(getSplitPath(history.location.search)).toEqual("/doc/third-doc");
});
it("closes the split view when navigating to a non-splitable route", () => {
navigate("/doc/my-doc?split=%2Fdoc%2Fother-doc");
history.push("/settings/users");
expect(history.location.pathname).toEqual("/settings/users");
expect(getSplitPath(history.location.search)).toBeUndefined();
});
it("uses locations with an explicit split parameter verbatim", () => {
navigate("/doc/my-doc?split=%2Fdoc%2Fother-doc");
setFocusedSplitPane("secondary");
history.push({
pathname: "/doc/my-doc",
search: "?split=%2Fdoc%2Fthird-doc",
});
expect(history.location.pathname).toEqual("/doc/my-doc");
expect(getSplitPath(history.location.search)).toEqual("/doc/third-doc");
});
it("skips split view handling when suppressed", () => {
navigate("/doc/my-doc?split=%2Fdoc%2Fother-doc");
withoutSplitViewNavigation(() => history.push("/doc/third-doc"));
expect(history.location.pathname).toEqual("/doc/third-doc");
expect(getSplitPath(history.location.search)).toBeUndefined();
});
describe("with the split view modifier held", () => {
let stop: () => void;
// The test environment is neither macOS nor Electron, so the modifier is
// control together with shift.
const holdModifier = () =>
window.dispatchEvent(
new KeyboardEvent("keydown", {
key: "Control",
ctrlKey: true,
shiftKey: true,
})
);
beforeEach(() => {
stop = initSplitViewNavigation(history);
});
afterEach(() => stop());
it("opens the route in the secondary pane", () => {
holdModifier();
history.push("/doc/my-doc");
expect(history.location.pathname).toEqual("/home");
expect(getSplitPath(history.location.search)).toEqual("/doc/my-doc");
});
it("navigates normally when the route carries location state", () => {
holdModifier();
history.push("/doc/my-doc", { sidebarContext: "collections" });
expect(history.location.pathname).toEqual("/doc/my-doc");
expect(getSplitPath(history.location.search)).toBeUndefined();
});
it("navigates normally to a route that cannot render in a pane", () => {
holdModifier();
history.push("/settings/users");
expect(history.location.pathname).toEqual("/settings/users");
expect(getSplitPath(history.location.search)).toBeUndefined();
});
it("leaves replace unchanged", () => {
holdModifier();
history.replace("/doc/my-doc");
expect(history.location.pathname).toEqual("/doc/my-doc");
expect(getSplitPath(history.location.search)).toBeUndefined();
});
});
});