diff --git a/packages/panel/src/tasks/agent-pull-request-tab.test.ts b/packages/panel/src/tasks/agent-pull-request-tab.test.ts index bdcdefb204..41c780264b 100644 --- a/packages/panel/src/tasks/agent-pull-request-tab.test.ts +++ b/packages/panel/src/tasks/agent-pull-request-tab.test.ts @@ -2621,12 +2621,12 @@ test("while a merge's change is out its control stands busy, and where GitHub re ); }); -test("Review stands at the end of the tabs' row while the pull request is open or a draft, and nowhere once it is closed or merged", async () => { +test("Review stands at the end of the tabs' row however the pull request stands, open, a draft, closed, or merged, as GitHub takes a review of each", async () => { const states = [ [PULL_REQUEST_STATE.OPEN, true], [PULL_REQUEST_STATE.DRAFT, true], - [PULL_REQUEST_STATE.CLOSED, false], - [PULL_REQUEST_STATE.MERGED, false], + [PULL_REQUEST_STATE.CLOSED, true], + [PULL_REQUEST_STATE.MERGED, true], ] as const; for (const [state, offered] of states) { const tab = await draw( @@ -2784,7 +2784,7 @@ test("Review opens a panel whose choice and words are submitted for the agent as ); }); -test("a review GitHub refuses says so in GitHub's own words inside the panel, never over the header, and the words written stand for another try; a merged pull request offers no Review", async () => { +test("a review GitHub refuses says so in GitHub's own words inside the panel, never over the header, and the words written stand for another try", async () => { changeAnswer = { outcome: PULL_REQUEST_WRITE_OUTCOME.REFUSED, words: "Review Can not approve your own pull request", @@ -2801,16 +2801,32 @@ test("a review GitHub refuses says so in GitHub's own words inside the panel, ne ); assert.equal(tab.querySelector(".pull-request-write-note"), null); assert.equal(panel.querySelector("textarea")?.value, "LGTM"); - act(() => root?.unmount()); - root = undefined; +}); +test("a merged pull request still takes a review, sent for the agent as one on an open one is, and keeps its comment box, as GitHub does", async () => { const merged = await draw( - controlAnswering({ - pullRequest: () => - Promise.resolve({ pullRequest: { ...PULL_REQUEST, state: PULL_REQUEST_STATE.MERGED } }), - }), + controlAnswering( + { + pullRequest: () => + Promise.resolve({ + pullRequest: { ...PULL_REQUEST, state: PULL_REQUEST_STATE.MERGED, mergedAt: 5_000 }, + }), + }, + PULL_REQUEST_STATE.MERGED, + ), ); - assert.equal(buttonWith(merged, /^Review$/u), undefined); + assert.ok(merged.querySelector(".pull-request-comment-box"), "its comment box stands"); + const panel = openReview(merged); + writeReview(panel, "Late, but LGTM"); + await submitReview(panel, "Approve"); + assert.deepEqual(changes.at(-1), [ + AGENT.id, + { + action: PULL_REQUEST_ACTION.SUBMIT_REVIEW, + event: REVIEW_EVENT.APPROVE, + body: "Late, but LGTM", + }, + ]); }); test("a press outside the review panel closes it, its words kept, and one on a short window opens it on the side with more room, bounded to that room", async () => { diff --git a/packages/panel/src/tasks/agent-pull-request-tab.tsx b/packages/panel/src/tasks/agent-pull-request-tab.tsx index e0abd96d07..c6ffb9ed2a 100644 --- a/packages/panel/src/tasks/agent-pull-request-tab.tsx +++ b/packages/panel/src/tasks/agent-pull-request-tab.tsx @@ -229,8 +229,8 @@ import { useWorkingNow, workingTime } from "./working-time.js"; * wearing where each stands, the reviewer and label pickers, and its labels * in their GitHub colours (`pull-request-labels.tsx`) at the line's end, so * a pull request with no labels spends no line on them. Under it, a row of - * tabs ending in Review while it is open or a draft - * (`pull-request-review.tsx`), each tab its glyph, its name, and a quiet + * tabs ending in Review, merged or closed too, as GitHub takes a review + * then (`pull-request-review.tsx`), each tab its glyph, its name, and a quiet * count: Conversation, its description and its comments and * reviews in time order, as GitHub renders them (`body_html`), drawn * through the transcript's own markdown drawing (`GitHubWords`), with an @@ -2231,9 +2231,8 @@ function PullRequestTabBody({ ); const overview = landed(parts.pullRequest); const title = overview ?? published; - // Review stands at the end of the tabs while the pull request is open or a draft, as the pill says it stands. - const reviewable = - held?.state === PULL_REQUEST_STATE.OPEN || held?.state === PULL_REQUEST_STATE.DRAFT; + // Review stands at the end of the tabs once the pull request is held, whatever it stands as, because GitHub takes a review of one merged or closed too; where GitHub refuses one, as on a locked conversation, the panel says why in GitHub's words. + const reviewable = held !== undefined; const now = useMinute(); // A change is read back as Refresh reads: the tab, and what the agent published, which the plan's own marks draw. const written = refresh;