fix: preserve pr summary hidden link totals

This commit is contained in:
Aditi Chauhan 2026-07-05 13:14:49 +05:30
parent 53d675e8ac
commit c989df0851
3 changed files with 57 additions and 1 deletions

View File

@ -52,4 +52,29 @@ describe("PRSummaryParts", () => {
expect(screen.queryByText("types")).not.toBeInTheDocument();
expect(screen.getByText("+1 check")).toBeInTheDocument();
});
it("counts overflow beyond helper-truncated links", () => {
render(
<PRSummaryParts
interactiveLinks={false}
pr={summary({
ci: {
state: "failing",
failingChecks: [
{ name: "unit", status: "failed", conclusion: "failure", url: "https://checks.example/unit" },
{ name: "lint", status: "failed", conclusion: "failure", url: "https://checks.example/lint" },
{ name: "types", status: "failed", conclusion: "failure", url: "https://checks.example/types" },
{ name: "build", status: "failed", conclusion: "failure", url: "https://checks.example/build" },
],
},
})}
/>,
);
expect(screen.getByText("unit")).toBeInTheDocument();
expect(screen.getByText("lint")).toBeInTheDocument();
expect(screen.getByText("types")).toBeInTheDocument();
expect(screen.queryByText("build")).not.toBeInTheDocument();
expect(screen.getByText("+1 check")).toBeInTheDocument();
});
});

View File

@ -97,7 +97,10 @@ export function PRSummaryParts({
>
{parts.map((part) => {
const links = part.links.slice(0, maxLinks);
const overflowLabel = overflowPartLabel(part.links.length - links.length, part.overflowNoun);
const overflowLabel = overflowPartLabel(
(part.linkTotal ?? part.links.length) - links.length,
part.overflowNoun,
);
return (
<div key={part.key} className={cn("min-w-0", stacked ? "flex flex-col" : "inline-flex flex-wrap gap-x-1")}>
<div className="min-w-0 truncate">

View File

@ -41,6 +41,7 @@ export type PRSummaryPart = {
status: string;
summary?: string;
links: PRSummaryLink[];
linkTotal?: number;
overflowLabel?: string;
overflowNoun?: string;
tone: PRDisplayTone;
@ -124,6 +125,7 @@ export function prSummaryParts(pr: SessionPRSummary): PRSummaryPart[] {
status: ciLabel(pr.ci.state),
summary: ciSummary(pr),
links: ciLinks(pr),
linkTotal: pr.ci.state === "failing" ? pr.ci.failingChecks.length : 0,
overflowLabel: pr.ci.state === "failing" ? overflowLabel(pr.ci.failingChecks.length, 3, "check") : undefined,
overflowNoun: "check",
tone: ciTone(pr.ci.state),
@ -134,6 +136,7 @@ export function prSummaryParts(pr: SessionPRSummary): PRSummaryPart[] {
status: mergeabilityLabel(pr.mergeability.state),
summary: mergeSummary(pr),
links: mergeLinks(pr),
linkTotal: mergeLinkTotal(pr),
overflowLabel: mergeOverflowLabel(pr),
overflowNoun: mergeOverflowNoun(pr),
tone: mergeabilityTone(pr.mergeability.state),
@ -144,6 +147,7 @@ export function prSummaryParts(pr: SessionPRSummary): PRSummaryPart[] {
status: reviewLabel(pr.review.decision),
summary: reviewSummary(pr),
links: reviewLinks(pr),
linkTotal: reviewLinkTotal(pr),
overflowLabel:
pr.state === "draft" || pr.review.decision === "review_required"
? undefined
@ -254,10 +258,34 @@ function mergeOverflowLabel(pr: SessionPRSummary): string | undefined {
return undefined;
}
function mergeLinkTotal(pr: SessionPRSummary): number {
if (pr.state === "merged" || pr.state === "closed") {
return 0;
}
if (pr.mergeability.state === "conflicting") {
const conflictFileCount = pr.mergeability.conflictFiles?.length ?? 0;
return conflictFileCount > 0 ? conflictFileCount : mergeLinks(pr).length;
}
if (pr.mergeability.state === "blocked" || pr.mergeability.state === "unstable") {
return pr.mergeability.reasons.length;
}
return 0;
}
function mergeOverflowNoun(pr: SessionPRSummary): string {
return (pr.mergeability.conflictFiles ?? []).length > 0 ? "file" : "reason";
}
function reviewLinkTotal(pr: SessionPRSummary): number {
if (pr.state === "merged" || pr.state === "closed" || pr.state === "draft") {
return 0;
}
if (pr.review.decision !== "changes_requested" && !pr.review.hasUnresolvedHumanComments) {
return 0;
}
return pr.review.unresolvedBy.length > 0 ? pr.review.unresolvedBy.length : reviewLinks(pr).length;
}
function toCIState(value: string): SessionPRSummary["ci"]["state"] {
return ciStates.has(value as SessionPRSummary["ci"]["state"])
? (value as SessionPRSummary["ci"]["state"])