Files
multica/packages/views/common/github-url.test.ts
Rusty Raven 999f73e61f fix(projects): show owner/repo label for GitHub resource URLs (MUL-5221) (#5795)
* fix(projects): show owner/repo label for GitHub resource URLs instead of truncated full URL

Long GitHub URLs in the project-resources sidebar are end-truncated by CSS
`truncate`, making similar repos like org/very-long-repo-a and
org/very-long-repo-b indistinguishable from the visible prefix alone.

Extract just the `owner/repo` segment from the URL for display; keep the full
URL in the tooltip so it remains accessible on hover. Applied to both the
resource row and the repository picker popover. Custom labels are unaffected.

Fixes #5771

Co-authored-by: multica-agent <github@multica.ai>

* fix(projects): strip .git suffix and handle scp SSH URLs in githubShortLabel; add middle-truncation for long repo names

Addresses #5795 review feedback:
- Strip .git suffix (example-org/very-long-repo-name.git → without .git)
- Handle git@github.com:owner/repo.git (scp shorthand) which new URL() rejects
- Add midTruncate() so repos sharing a long common prefix are distinguishable
  by their tail (customer-alpha vs customer-beta) rather than being end-truncated
  identically by CSS

Fixes #5771.

Co-authored-by: multica-agent <github@multica.ai>

* refactor(projects): share githubShortLabel across project resource UIs

Move githubShortLabel/midTruncate out of project-resources-section into
packages/views/common/github-url.ts so the create-project repository picker
reuses the same owner/repo shortening (it was still rendering full URLs) and
recognize the www.github.com host. Add github-url.test.ts covering the
https / ssh / scp / enterprise / malformed cases plus middle-truncation.

Addresses #5795 review feedback: shared helper, create-project coverage, tests.

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: Bohan Jiang <52446949+Bohan-J@users.noreply.github.com>
2026-07-24 15:55:57 +08:00

88 lines
2.8 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { githubShortLabel, midTruncate } from "./github-url";
describe("githubShortLabel", () => {
it("extracts owner/repo from an https URL", () => {
expect(githubShortLabel("https://github.com/octocat/hello-world")).toBe(
"octocat/hello-world",
);
});
it("ignores extra path segments after owner/repo", () => {
expect(
githubShortLabel("https://github.com/octocat/hello-world/tree/main"),
).toBe("octocat/hello-world");
});
it("strips a trailing .git suffix", () => {
expect(githubShortLabel("https://github.com/octocat/hello-world.git")).toBe(
"octocat/hello-world",
);
});
it("handles the www.github.com host", () => {
expect(githubShortLabel("https://www.github.com/octocat/hello-world")).toBe(
"octocat/hello-world",
);
});
it("handles ssh:// URLs and strips .git", () => {
expect(
githubShortLabel("ssh://git@github.com/octocat/hello-world.git"),
).toBe("octocat/hello-world");
});
it("handles scp-style shorthand (git@github.com:owner/repo.git)", () => {
expect(githubShortLabel("git@github.com:octocat/hello-world.git")).toBe(
"octocat/hello-world",
);
});
it("handles scp-style shorthand without a .git suffix", () => {
expect(githubShortLabel("git@github.com:octocat/hello-world")).toBe(
"octocat/hello-world",
);
});
it("middle-truncates so a shared long prefix stays distinguishable", () => {
const a = githubShortLabel(
"https://github.com/example-organization/very-long-repository-name-for-customer-alpha.git",
);
const b = githubShortLabel(
"https://github.com/example-organization/very-long-repository-name-for-customer-beta.git",
);
expect(a).not.toBe(b);
expect(a.length).toBeLessThanOrEqual(40);
expect(a.endsWith("alpha")).toBe(true);
expect(b.endsWith("beta")).toBe(true);
});
it("returns enterprise-host URLs unchanged", () => {
const url = "https://github.enterprise.com/octocat/hello-world";
expect(githubShortLabel(url)).toBe(url);
});
it("returns malformed input unchanged", () => {
expect(githubShortLabel("not a url")).toBe("not a url");
});
it("returns a github URL without a repo segment unchanged", () => {
const url = "https://github.com/octocat";
expect(githubShortLabel(url)).toBe(url);
});
});
describe("midTruncate", () => {
it("leaves short strings untouched", () => {
expect(midTruncate("short")).toBe("short");
});
it("caps the result at maxLen and inserts an ellipsis", () => {
const out = midTruncate("a".repeat(100), 21);
expect(out.length).toBe(21);
expect(out).toContain("…");
expect(out.startsWith("aaaaaaaaaa")).toBe(true);
expect(out.endsWith("aaaaaaaaaa")).toBe(true);
});
});