import type { PullRequestActor, PullRequestCapabilities, PullRequestComment, PullRequestDetail, PullRequestViewerPermissions, } from "@t3tools/contracts"; import { describe, expect, it } from "vite-plus/test"; import { canEditPullRequestChangeRequest, canEditPullRequestComment, } from "./pullRequestEditing.logic"; type Subject = Pick; function actor(login: string): PullRequestActor { return { login, name: null, avatarUrl: null }; } function capabilities(edit?: PullRequestCapabilities["edit"]): PullRequestCapabilities { return { diff: true, comment: true, actions: [], mergeMethods: [], search: true, reactions: true, review: { inlineComment: true, reply: true, resolve: true, verdicts: [] }, reviewers: { request: true, listCandidates: true }, ...(edit === undefined ? {} : { edit }), }; } function permissions( overrides: Partial = {}, ): PullRequestViewerPermissions { return { actions: [], comment: true, resolve: true, verdicts: [], requestReviewers: true, ...overrides, }; } function subject(overrides: Partial = {}): Subject { return { author: actor("octocat"), capabilities: capabilities({ changeRequest: true, comment: true }), viewer: "octocat", viewerPermissions: permissions(), ...overrides, }; } function comment(overrides: Partial = {}): PullRequestComment { return { id: "c1", kind: "issue-comment", author: actor("octocat"), body: "words", createdAt: "2026-01-01T00:00:00.000Z", url: null, path: null, reviewState: null, ...overrides, }; } describe("canEditPullRequestChangeRequest", () => { it("lets the author rewrite their own change request", () => { expect(canEditPullRequestChangeRequest(subject())).toBe(true); }); it("matches the author regardless of case", () => { expect(canEditPullRequestChangeRequest(subject({ viewer: "OctoCat" }))).toBe(true); }); it("lets somebody who may merge rewrite a change request they did not write", () => { expect( canEditPullRequestChangeRequest( subject({ author: actor("someone-else"), viewerPermissions: permissions({ actions: ["merge"] }), }), ), ).toBe(true); }); it("refuses a reader who neither wrote it nor may merge it", () => { expect( canEditPullRequestChangeRequest( subject({ author: actor("someone-else"), viewerPermissions: permissions({ actions: ["close"] }), }), ), ).toBe(false); }); it("refuses where the host cannot rewrite a change request at all", () => { expect( canEditPullRequestChangeRequest( subject({ capabilities: capabilities({ changeRequest: false, comment: true }) }), ), ).toBe(false); expect(canEditPullRequestChangeRequest(subject({ capabilities: capabilities() }))).toBe(false); }); it("refuses where the host did not say who the reader is", () => { expect(canEditPullRequestChangeRequest(subject({ viewer: undefined }))).toBe(false); }); it("still allows a merger the host could not name", () => { expect( canEditPullRequestChangeRequest( subject({ viewer: undefined, viewerPermissions: permissions({ actions: ["merge"] }) }), ), ).toBe(true); }); }); describe("canEditPullRequestComment", () => { it("lets the reader rewrite their own conversation comment", () => { expect(canEditPullRequestComment(subject(), comment())).toBe(true); }); it("lets the reader rewrite their own remark on a line", () => { expect(canEditPullRequestComment(subject(), comment({ kind: "review-comment" }))).toBe(true); }); it("matches the author regardless of case", () => { expect( canEditPullRequestComment( subject({ viewer: "OCTOCAT" }), comment({ author: actor("octocat") }), ), ).toBe(true); }); it("refuses somebody else's remark", () => { expect(canEditPullRequestComment(subject(), comment({ author: actor("someone-else") }))).toBe( false, ); }); it("refuses a remark the host attributes to nobody", () => { expect(canEditPullRequestComment(subject(), comment({ author: null }))).toBe(false); }); it("refuses a review's own summary", () => { expect(canEditPullRequestComment(subject(), comment({ kind: "review" }))).toBe(false); }); it("refuses where the host cannot rewrite a remark at all", () => { expect( canEditPullRequestComment( subject({ capabilities: capabilities({ changeRequest: true, comment: false }) }), comment(), ), ).toBe(false); expect(canEditPullRequestComment(subject({ capabilities: capabilities() }), comment())).toBe( false, ); }); it("refuses where the host did not say who the reader is", () => { expect(canEditPullRequestComment(subject({ viewer: undefined }), comment())).toBe(false); }); });