The branch plan-puzzle-v1-tests had accumulated changes from a sibling thread (Plan Puzzle v1 backend + frontend) that hadn't been committed yet, plus a new src/lib/git/repo-url helper used by the Forgejo ingest path. Pick them all up so the working tree is clean and the branch reflects everything since its fork. Files (Plan Puzzle): src/app/actions/client-proposal.ts src/app/actions/owner-plan.ts src/app/actions/reschedule.ts src/app/actions/reschedule-helpers.ts (+ test) src/components/admin/project-form.tsx src/components/roadmap/roadmap-builder.tsx src/components/roadmap/timeline-view.tsx src/lib/cards/write-with-audit.ts (+ test) src/lib/roadmap/timeline.ts (+ test) New helper: src/lib/git/repo-url.ts (+ test) Verified: npm run build clean, 466/466 unit tests pass.
90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
|
|
import { parseRepoRef } from "./repo-url";
|
|
|
|
describe("parseRepoRef", () => {
|
|
it("parses a Forgejo HTTPS URL with .git suffix", () => {
|
|
expect(
|
|
parseRepoRef(
|
|
"http://forgejo-b82b4lpyyzyg40thdsjdd38i.163.245.214.68.sslip.io/David/mega-plant.git"
|
|
)
|
|
).toEqual({ owner: "David", name: "mega-plant" });
|
|
});
|
|
|
|
it("parses a GitHub URL without .git suffix", () => {
|
|
expect(parseRepoRef("https://github.com/octocat/Hello-World")).toEqual({
|
|
owner: "octocat",
|
|
name: "Hello-World",
|
|
});
|
|
});
|
|
|
|
it("parses an SSH scp-style URL", () => {
|
|
expect(parseRepoRef("git@forgejo.example.com:David/mega-plant.git")).toEqual(
|
|
{ owner: "David", name: "mega-plant" }
|
|
);
|
|
});
|
|
|
|
it("parses an ssh:// URL", () => {
|
|
expect(parseRepoRef("ssh://git@host/owner/repo.git")).toEqual({
|
|
owner: "owner",
|
|
name: "repo",
|
|
});
|
|
});
|
|
|
|
it("parses an http URL with a port", () => {
|
|
expect(parseRepoRef("http://localhost:3000/David/mega-plant.git")).toEqual({
|
|
owner: "David",
|
|
name: "mega-plant",
|
|
});
|
|
});
|
|
|
|
it("strips a trailing slash", () => {
|
|
expect(parseRepoRef("https://gitea.example.com/owner/repo/")).toEqual({
|
|
owner: "owner",
|
|
name: "repo",
|
|
});
|
|
});
|
|
|
|
it("treats owner/name shorthand as a path", () => {
|
|
expect(parseRepoRef("David/mega-plant")).toEqual({
|
|
owner: "David",
|
|
name: "mega-plant",
|
|
});
|
|
});
|
|
|
|
it("preserves case from the URL", () => {
|
|
expect(
|
|
parseRepoRef("https://forgejo.example.com/David/Mega-Plant.git")
|
|
).toEqual({ owner: "David", name: "Mega-Plant" });
|
|
});
|
|
|
|
it("drops extra path segments (commits, branches, …)", () => {
|
|
expect(
|
|
parseRepoRef("https://gitea.example.com/owner/repo/commits/main")
|
|
).toEqual({ owner: "owner", name: "repo" });
|
|
});
|
|
|
|
it("ignores extra whitespace around the input", () => {
|
|
expect(parseRepoRef(" https://gitea.example.com/owner/repo.git ")).toEqual(
|
|
{ owner: "owner", name: "repo" }
|
|
);
|
|
});
|
|
|
|
it("returns null for empty or whitespace input", () => {
|
|
expect(parseRepoRef("")).toBeNull();
|
|
expect(parseRepoRef(" ")).toBeNull();
|
|
});
|
|
|
|
it("returns null when there is only one path segment", () => {
|
|
expect(parseRepoRef("https://gitea.example.com/owner")).toBeNull();
|
|
expect(parseRepoRef("owner")).toBeNull();
|
|
});
|
|
|
|
it("returns null when the URL has no path", () => {
|
|
expect(parseRepoRef("https://gitea.example.com/")).toBeNull();
|
|
});
|
|
|
|
it("returns null for garbage", () => {
|
|
expect(parseRepoRef("not a url at all !!!")).toBeNull();
|
|
});
|
|
});
|