Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/swarm-ui/test/pr-report.test.mjs
iris f633963b77 swarm ui: a pull requests card on the reports tab
The reports tab gets a "pull requests" card under the issue report. It lists
the open PRs of every repo, or of one picked in a repo select, with the
columns a reviewer or merger filters on: author, labels, requested
reviewers, base branch, WIP (the forge's draft flag), approvals against the
base branch's protection rule, has all approvals, conflicts, protected base
and CI. Every column sorts, the small-set columns filter by picking values,
and the browser keeps the filters and the repo. No filter applies at first.

swarm-controller resolves each row so the page makes no calls of its own:
GET /api/pr-report and GET /api/repos/{org}/{repo}/pr-report. The required
approvals come from the first matching branch protection rule (an
unprotected base asks for none); an approval counts when it is the
reviewer's latest decision, on the current head, neither stale nor
dismissed and official.

A free-text table cell gets a minimum width, so a table with many columns
scrolls sideways instead of wrapping a title to a word a line.
2026-11-07 11:46:05 +01:00

69 lines
1.8 KiB
JavaScript

// The PR report's URL and the words its columns show and filter on.
import assert from "node:assert/strict";
import { test } from "node:test";
import {
approvalsText,
hasAllApprovals,
prReportUrl,
yesNo,
} from "../src/pages/pr-report.ts";
test("no repo, or a filter that is not owner/name, reads as all repos", () => {
assert.equal(prReportUrl(""), "/api/pr-report");
assert.equal(prReportUrl("nothing"), "/api/pr-report");
});
test("a repo has its own URL, with each part encoded", () => {
assert.equal(
prReportUrl("hyperhive/hyperhive"),
"/api/repos/hyperhive/hyperhive/pr-report",
);
assert.equal(
prReportUrl("o/a?b#c%d"),
"/api/repos/o/a%3Fb%23c%25d/pr-report",
);
});
test("a flag filters on yes and no", () => {
assert.equal(yesNo(true), "yes");
assert.equal(yesNo(false), "no");
});
const row = (over) => ({
targets_protected_branch: true,
required_approvals: 2,
approvals: 1,
...over,
});
test("approvals read as have/required against a protected base", () => {
assert.equal(approvalsText(row({})), "1/2");
assert.equal(approvalsText(row({ approvals: 0 })), "0/2");
});
test("an unprotected base, or a rule asking for none, shows only what it has", () => {
assert.equal(
approvalsText(row({ targets_protected_branch: false, approvals: 0 })),
"—",
);
assert.equal(
approvalsText(row({ required_approvals: 0, approvals: 2 })),
"2",
);
});
test("a PR has all approvals when it meets the rule, and an unprotected base always does", () => {
assert.equal(hasAllApprovals(row({})), false);
assert.equal(hasAllApprovals(row({ approvals: 2 })), true);
assert.equal(hasAllApprovals(row({ approvals: 3 })), true);
assert.equal(
hasAllApprovals(
row({
targets_protected_branch: false,
required_approvals: 0,
approvals: 0,
}),
),
true,
);
});