refactor(app): extract pr-pane derivations into pure utils and unit tests (#713)

Move getStateLabel and getActivityVerb out of pr-pane.tsx into pr-pane-data.ts
so they can be tested without JSDOM, React, or vi.mock. Add exhaustive unit tests
for both helpers alongside the existing mapPrPaneData/formatAge/deriveAvatarColor
coverage. Delete pr-pane.test.tsx — the component test was asserting on derived
label/icon strings that are now covered by pure function tests.
This commit is contained in:
Mohamed Boudra
2026-05-05 19:58:55 +07:00
parent 90c7e591e8
commit 6bd5d4c410
4 changed files with 57 additions and 184 deletions
+42 -1
View File
@@ -3,7 +3,13 @@ import type {
CheckoutPrStatusResponse,
PullRequestTimelineResponse,
} from "@server/shared/messages";
import { deriveAvatarColor, formatAge, mapPrPaneData } from "./pr-pane-data";
import {
deriveAvatarColor,
formatAge,
getActivityVerb,
getStateLabel,
mapPrPaneData,
} from "./pr-pane-data";
type CheckoutPrStatus = NonNullable<CheckoutPrStatusResponse["payload"]["status"]>;
type PullRequestTimeline = PullRequestTimelineResponse["payload"];
@@ -335,3 +341,38 @@ describe("formatAge", () => {
expect(formatAge(now - 365 * 24 * 60 * 60_000, now)).toBe("1y ago");
});
});
describe("getStateLabel", () => {
it.each([
["open", "Open"],
["draft", "Draft"],
["merged", "Merged"],
["closed", "Closed"],
] as const)("maps %s → %s", (state, expected) => {
expect(getStateLabel(state)).toBe(expected);
});
});
describe("getActivityVerb", () => {
it("returns Commented for comment kind", () => {
expect(getActivityVerb({ kind: "comment" })).toBe("Commented");
});
it("returns Approved for approved review", () => {
expect(getActivityVerb({ kind: "review", reviewState: "approved" })).toBe("Approved");
});
it("returns Requested changes for changes_requested review", () => {
expect(getActivityVerb({ kind: "review", reviewState: "changes_requested" })).toBe(
"Requested changes",
);
});
it("returns Reviewed for a commented review with body (generic case)", () => {
expect(getActivityVerb({ kind: "review", reviewState: "commented" })).toBe("Reviewed");
});
it("returns Reviewed when reviewState is undefined", () => {
expect(getActivityVerb({ kind: "review" })).toBe("Reviewed");
});
});
+14
View File
@@ -225,3 +225,17 @@ function hashLogin(login: string): number {
}
return hash;
}
export function getStateLabel(state: PrState): string {
if (state === "draft") return "Draft";
if (state === "merged") return "Merged";
if (state === "closed") return "Closed";
return "Open";
}
export function getActivityVerb(item: Pick<PrPaneActivity, "kind" | "reviewState">): string {
if (item.kind === "comment") return "Commented";
if (item.reviewState === "approved") return "Approved";
if (item.reviewState === "changes_requested") return "Requested changes";
return "Reviewed";
}