Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

59 lines · 2.8 KBRaw History
1import { describe, expect, it } from "vitest";
2import { movedLoginPath, movedPath, movedStatus } from "../../src/lib/redirects.js";
3
4const from = { owner: "codician-team", name: "diffinery" };
5const to = { owner: "codician", name: "diffinery" };
6
7describe("moved repository paths", () => {
8 it("rewrites web pages and keeps the rest of the path", () => {
9 expect(movedPath("/codician-team/diffinery", from, to)).toBe("/codician/diffinery");
10 expect(movedPath("/codician-team/diffinery/blob/main/README.md", from, to)).toBe("/codician/diffinery/blob/main/README.md");
11 expect(movedPath("/codician-team/diffinery/issues/", from, to)).toBe("/codician/diffinery/issues/");
12 });
13
14 it("rewrites REST paths", () => {
15 expect(movedPath("/api/v3/repos/codician-team/diffinery/issues/3", from, to)).toBe("/api/v3/repos/codician/diffinery/issues/3");
16 expect(movedPath("/api/v3/repos/codician-team/diffinery", from, { owner: "codician", name: "forge" })).toBe("/api/v3/repos/codician/forge");
17 });
18
19 it("keeps a .git suffix on Git URLs", () => {
20 expect(movedPath("/codician-team/diffinery.git/info/refs", from, to)).toBe("/codician/diffinery.git/info/refs");
21 expect(movedPath("/codician-team/diffinery/info/refs", from, to)).toBe("/codician/diffinery/info/refs");
22 });
23
24 it("matches owner and name without regard to case, like the directory", () => {
25 expect(movedPath("/Codician-Team/Diffinery/pulls", from, to)).toBe("/codician/diffinery/pulls");
26 });
27
28 it("only rewrites a whole owner/name pair", () => {
29 expect(movedPath("/codician-team/diffinery-old/pulls", from, to)).toBeNull();
30 expect(movedPath("/codician-team-2/diffinery", from, to)).toBeNull();
31 expect(movedPath("/codician-team", from, to)).toBeNull();
32 });
33
34 it("is null when the name came from somewhere other than the path", () => {
35 expect(movedPath("/mcp", from, to)).toBeNull();
36 expect(movedPath("/settings/files", from, to)).toBeNull();
37 });
38
39 it("encodes the new names and survives malformed escapes", () => {
40 expect(movedPath("/codician-team/diffinery/tree/a%2Fb", from, { owner: "x", name: "y" })).toBe("/x/y/tree/a%2Fb");
41 expect(movedPath("/%E0%A4%A/diffinery", from, to)).toBeNull();
42 });
43});
44
45describe("renamed account paths", () => {
46 it("rewrites the first segment only", () => {
47 expect(movedLoginPath("/old-org", "old-org", "new-org")).toBe("/new-org");
48 expect(movedLoginPath("/Old-Org/site/issues", "old-org", "new-org")).toBe("/new-org/site/issues");
49 expect(movedLoginPath("/other/old-org", "old-org", "new-org")).toBeNull();
50 });
51});
52
53describe("moved status", () => {
54 it("is 301 for reads and 307 for everything else, as on GitHub", () => {
55 expect(movedStatus("GET")).toBe(301);
56 expect(movedStatus("HEAD")).toBe(301);
57 for (const m of ["POST", "PUT", "PATCH", "DELETE"]) expect(movedStatus(m)).toBe(307);
58 });
59});