Files
paseo/packages/app/src/git/forge-icon.test.ts
T
a8ebd390fa feat(forge): pluggable forge abstraction + GitLab and Gitea/Forgejo/Codeberg (#1913)
* refactor(forge): forge-neutral foundation (GitHub-only)

Decouple git-hosting from GitHub behind a neutral abstraction (issue #1616), GitHub-only for now; existing GitHub behaviour is unchanged.

- Forge manifest, neutral ForgeService contract, forge registry + resolver, and a client forge-module registry.
- GitHub code renamed to the neutral shape; PR/Issue attachment wording preserved.
- forge.search.response enums parse tolerantly (unknown kind/auth state degrade instead of breaking the client).
- createPullRequest reports typed CLI/auth errors instead of a generic message.
- forge-resolver host/remote caches are LRU-bounded.
- Forge host trust is explicit: only a known cloud host or a CLI-authenticated host is ever talked to; an unauthenticated GitHub Enterprise host fails resolution instead of routing to github.com.
- Docs: forge-providers guide, glossary and i18n forge-copy conventions, architecture and rpc-namespacing terminology.
- Vitest React Native mocks (unistyles, svg, linking, lucide) consolidated into shared aliased test-stubs.

* feat(forge): GitLab adapter, forge-aware UI, pipelines and approvals

GitLab adapter over the glab CLI on the neutral contracts: MR status, forge-aware UI, pipeline tree, and N-of-M approvals.

- threadIsResolved is part of the neutral timeline item.
- Pipeline load failures show an error instead of an empty section.
- Manual pipeline jobs render as pending.
- Fork/detached MR head pipelines are fetched by MR iid (glab ci get --merge-request).

* feat(forge): Gitea family adapter (Gitea, Forgejo, Codeberg)

One adapter over the tea CLI serving Gitea, Forgejo, and Codeberg on the neutral contracts.

- CI status aggregates commit statuses and Actions runs together.
- Gitea's terminal "warning" state maps to failure on server and client.
- Gitea Actions check details are reachable from the PR pane by workflowRunId.

* refactor(forge): localize compatibility handling

* test(forge): expect normalized GitLab facts

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-07-17 15:03:26 +08:00

50 lines
1.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { GitPullRequest } from "lucide-react-native";
import { getForgeBrandColorMapping, getForgeIconComponent } from "./forge-icon";
import { CLIENT_FORGE_VIEW_MODULES } from "./forges/view";
describe("getForgeIconComponent", () => {
it("resolves a dedicated brand icon for every registered forge module", () => {
for (const module of CLIENT_FORGE_VIEW_MODULES) {
expect(getForgeIconComponent(module.id)).toBe(module.icon);
}
});
it("falls back to the generic pull-request glyph for unknown icon kinds", () => {
expect(getForgeIconComponent("some-unknown-forge")).toBe(GitPullRequest);
expect(getForgeIconComponent("")).toBe(GitPullRequest);
});
});
describe("getForgeBrandColorMapping", () => {
it("returns a theme mapping only for forges that declare a brand color", () => {
for (const module of CLIENT_FORGE_VIEW_MODULES) {
const mapping = getForgeBrandColorMapping(module.id);
if (module.brandColor) {
expect(mapping).toBeTypeOf("function");
} else {
expect(mapping).toBeNull();
}
}
});
it("resolves the light or dark brand color from the theme color scheme", () => {
const branded = CLIENT_FORGE_VIEW_MODULES.find((module) => module.brandColor);
expect(branded).toBeDefined();
if (!branded?.brandColor) {
return;
}
const mapping = getForgeBrandColorMapping(branded.id);
expect(mapping?.({ colorScheme: "light" } as never)).toEqual({
color: branded.brandColor.light,
});
expect(mapping?.({ colorScheme: "dark" } as never)).toEqual({
color: branded.brandColor.dark,
});
});
it("returns null for unknown icon kinds", () => {
expect(getForgeBrandColorMapping("some-unknown-forge")).toBeNull();
});
});