import { describe, expect, it } from "bun:test"; import { commitGroupingKey, gitShaFromSourceId, isLikelyGitRemote, normalizeGitRemote, resolveGitRemotes, } from "./git-remote"; describe("normalizeGitRemote", () => { it("normalizes common remote forms to host/path", () => { expect(normalizeGitRemote("git@github.com:owner/repo.git")).toBe( "github.com/owner/repo", ); expect(normalizeGitRemote("https://github.com/owner/repo.git")).toBe( "github.com/owner/repo", ); expect(normalizeGitRemote("ssh://git@github.com/owner/repo")).toBe( "github.com/owner/repo", ); expect(normalizeGitRemote("git+https://github.com/owner/repo.git")).toBe( "github.com/owner/repo", ); }); it("lowercases and strips trailing slashes", () => { expect(normalizeGitRemote("https://GitHub.com/Owner/Repo/")).toBe( "github.com/owner/repo", ); }); it("returns null for empty input", () => { expect(normalizeGitRemote(null)).toBeNull(); expect(normalizeGitRemote("")).toBeNull(); expect(normalizeGitRemote(" ")).toBeNull(); }); }); describe("isLikelyGitRemote", () => { it("accepts normalized repository references", () => { expect(isLikelyGitRemote("github.com/owner/repo")).toBe(true); expect(isLikelyGitRemote("gitlab.com/group/subgroup/repo")).toBe(true); expect(isLikelyGitRemote("git.example.io:8443/owner/repo")).toBe(true); }); it("rejects values that are not repository references", () => { expect(isLikelyGitRemote("not a url at all")).toBe(false); expect(isLikelyGitRemote("just-some-words")).toBe(false); expect(isLikelyGitRemote("github.com")).toBe(false); expect(isLikelyGitRemote("localhost/repo")).toBe(false); expect(isLikelyGitRemote("owner/repo")).toBe(false); }); }); describe("resolveGitRemotes", () => { it("unions and de-duplicates equivalent remote forms across roots", () => { expect( resolveGitRemotes([ "git@github.com:owner/repo.git", "https://github.com/owner/repo.git", "https://github.com/owner/other", ]), ).toEqual(["github.com/owner/other", "github.com/owner/repo"]); }); it("keeps identity when a gitless twin root is attached", () => { // The regression this guards: a null/empty remote must not erase the // identity contributed by a sibling root. expect( resolveGitRemotes([null, "", " ", "github.com/owner/repo"]), ).toEqual(["github.com/owner/repo"]); }); it("returns an empty array for a genuinely gitless project", () => { expect(resolveGitRemotes([])).toEqual([]); expect(resolveGitRemotes([null, undefined, ""])).toEqual([]); }); }); describe("commitGroupingKey", () => { it("produces the same key for the same commit across remote forms", () => { const sha = "ABC123"; const fromSsh = commitGroupingKey("git@github.com:owner/repo.git", sha); const fromHttps = commitGroupingKey( "https://github.com/owner/repo.git", sha, ); const fromHub = commitGroupingKey("github.com/Owner/Repo", sha); expect(fromSsh).toBe("github.com/owner/repo:abc123"); expect(fromHttps).toBe(fromSsh); expect(fromHub).toBe(fromSsh); }); it("returns null without a usable remote or sha", () => { expect(commitGroupingKey(null, "abc123")).toBeNull(); expect(commitGroupingKey("", "abc123")).toBeNull(); expect(commitGroupingKey("github.com/owner/repo", "")).toBeNull(); expect(commitGroupingKey("github.com/owner/repo", null)).toBeNull(); }); }); describe("gitShaFromSourceId", () => { it("keeps raw git commit source IDs unchanged", () => { expect(gitShaFromSourceId("ABC123")).toBe("ABC123"); }); it("extracts the sha from old GitHub import source IDs", () => { expect(gitShaFromSourceId("github:owner/repo:ABC123")).toBe("ABC123"); }); it("returns null for empty source IDs", () => { expect(gitShaFromSourceId(null)).toBeNull(); expect(gitShaFromSourceId("")).toBeNull(); }); });