blob: b0b679b118ee3fde0959e1f72621e2f3ddc230a4 [file]
/**
* The mount point.
*
* jsdom resolves document.baseURI through any <base> tag in the document, the
* same as a browser, so these tests can put the app in a sub-directory by
* adding one.
*/
import { afterEach, describe, expect, it } from "vitest";
import { apiUrl, appPath, basePath, baseUrl, loginUrl, logoutUrl, withoutBase } from "./base";
function mountAt(href: string): void {
const tag = document.createElement("base");
tag.setAttribute("href", href);
document.head.appendChild(tag);
}
afterEach(() => {
for (const tag of [...document.head.querySelectorAll("base")]) tag.remove();
});
describe("at the root of a host", () => {
it("has an empty prefix", () => {
expect(basePath()).toBe("");
});
it("builds app paths", () => {
expect(appPath("/help")).toBe("/help");
expect(appPath("help")).toBe("/help");
expect(appPath("/")).toBe("/");
});
it("builds API paths", () => {
expect(apiUrl("/events")).toBe("/api/events");
expect(apiUrl("events/3.ics")).toBe("/api/events/3.ics");
});
it("passes route paths through unchanged", () => {
expect(withoutBase("/help")).toBe("/help");
expect(withoutBase("/e/AbCd2345")).toBe("/e/AbCd2345");
expect(withoutBase("/")).toBe("/");
});
});
describe("the OAuth fallback URLs", () => {
it("point at the root when the app is served there", () => {
expect(loginUrl()).toBe("/auth?login=/");
expect(logoutUrl()).toBe("/auth?logout=/");
});
it("carry the mount point when the app is in a sub-directory", () => {
mountAt("/calendar/");
expect(loginUrl()).toBe("/calendar/auth?login=/calendar/");
expect(logoutUrl()).toBe("/calendar/auth?logout=/calendar/");
});
it("can be pointed back at a specific page", () => {
mountAt("/calendar/");
expect(loginUrl(appPath("/help"))).toBe("/calendar/auth?login=/calendar/help");
});
});
describe("in a sub-directory", () => {
it("reads the prefix off the base tag", () => {
mountAt("/calendar/");
expect(basePath()).toBe("/calendar");
expect(baseUrl().pathname).toBe("/calendar/");
});
it("copes with a base href that has no trailing slash", () => {
mountAt("/calendar");
expect(basePath()).toBe("/calendar");
});
it("copes with an absolute base href", () => {
mountAt("https://calendar.apache.org/calendar/");
expect(basePath()).toBe("/calendar");
});
it("handles a prefix more than one segment deep", () => {
mountAt("/tools/calendar/");
expect(basePath()).toBe("/tools/calendar");
expect(apiUrl("/events")).toBe("/tools/calendar/api/events");
});
it("prefixes app paths", () => {
mountAt("/calendar/");
expect(appPath("/help")).toBe("/calendar/help");
expect(appPath("/")).toBe("/calendar/");
});
it("prefixes API paths", () => {
mountAt("/calendar/");
expect(apiUrl("/events")).toBe("/calendar/api/events");
expect(apiUrl("/shortlink/AbCd2345")).toBe("/calendar/api/shortlink/AbCd2345");
});
it("strips the prefix off a browser path for route matching", () => {
mountAt("/calendar/");
expect(withoutBase("/calendar/help")).toBe("/help");
expect(withoutBase("/calendar/e/AbCd2345")).toBe("/e/AbCd2345");
expect(withoutBase("/calendar/")).toBe("/");
expect(withoutBase("/calendar")).toBe("/");
});
it("reports a path outside the app rather than guessing", () => {
mountAt("/calendar/");
expect(withoutBase("/")).toBeNull();
expect(withoutBase("/help")).toBeNull();
// A sibling directory that merely starts with the same letters.
expect(withoutBase("/calendarium/help")).toBeNull();
});
});