| 1 | import { describe, expect, it } from "vitest"; |
| 2 | import { movedLoginPath, movedPath, movedStatus } from "../../src/lib/redirects.js"; |
| 3 | |
| 4 | const from = { owner: "codician-team", name: "diffinery" }; |
| 5 | const to = { owner: "codician", name: "diffinery" }; |
| 6 | |
| 7 | describe("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 | |
| 45 | describe("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 | |
| 53 | describe("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 | }); |