1import { sourceControlClients } from "@t3tools/client-runtime/source-control-clients";
2import { describe, expect, it } from "vite-plus/test";
3import {
4 allowedMergeMethods,
5 canPerformPullRequestAction,
6 mergeUnavailableReason,
7 pullRequestActionLabel,
8} from "./pullRequestActions";
9
10const GITHUB = sourceControlClients.get("github").changeRequest;
11const GITLAB = sourceControlClients.get("gitlab").changeRequest;
12
13import type { PullRequestAction } from "@t3tools/contracts";
14
15const ALL_PR_ACTIONS: readonly PullRequestAction[] = [
16 "merge",
17 "ready",
18 "draft",
19 "update-branch",
20 "enable-auto-merge",
21 "disable-auto-merge",
22 "approve-workflows",
23 "close",
24 "reopen",
25 "revert",
26 "delete-branch",
27];
28
29type Detail = Parameters<typeof allowedMergeMethods>[0];
30
31function detail(overrides: Partial<Detail> = {}): Detail {
32 return {
33 state: "open",
34 isDraft: false,
35 mergeability: "mergeable",
36 autoMergeEnabled: false,
37 capabilities: {
38 actions: ALL_PR_ACTIONS,
39 mergeMethods: ["merge", "squash", "rebase"],
40 updateMethods: ["merge", "rebase"],
41 },
42 viewerPermissions: { actions: ALL_PR_ACTIONS, updateMethods: ["merge"] },
43 mergeCapabilities: { merge: true, squash: true, rebase: false },
44 ...overrides,
45 };
46}
47
48describe("mobile pull request actions", () => {
49 it("requires both provider support and account permission", () => {
50 expect(
51 canPerformPullRequestAction(detail({ viewerPermissions: { actions: [] } }), "merge"),
52 ).toBe(false);
53 expect(
54 canPerformPullRequestAction(
55 detail({ capabilities: { actions: [], mergeMethods: ["merge"] } }),
56 "merge",
57 ),
58 ).toBe(false);
59 expect(mergeUnavailableReason(detail(), false, GITHUB)).toContain("read-only");
60 });
61
62 it("blocks a conflicting PR's immediate merge and explains why", () => {
63 const pr = detail({ mergeability: "conflicting" });
64 expect(canPerformPullRequestAction(pr, "merge")).toBe(false);
65 expect(mergeUnavailableReason(pr, true, GITHUB)).toContain("conflicts");
66 });
67
68 it("names the change request with its host's term", () => {
69 expect(pullRequestActionLabel("close", GITHUB)).toBe("Close pull request");
70 expect(pullRequestActionLabel("close", GITLAB)).toBe("Close merge request");
71 expect(pullRequestActionLabel("revert", GITLAB)).toBe("Create revert merge request");
72 expect(mergeUnavailableReason(detail({ state: "merged" }), true, GITLAB)).toBe(
73 "This merge request has been merged.",
74 );
75 });
76});