1import { describe, expect, it } from "vite-plus/test";
2
3import { resolvePullRequestConflict, resolvePullRequestState } from "./pullRequestPresentation";
4import { PullRequestGlyph } from "./pullRequestIcons";
5
6describe("resolvePullRequestState", () => {
7 it.each([
8 [
9 "open",
10 { state: "open", isDraft: false },
11 PullRequestGlyph.pullRequest,
12 "Open",
13 "text-emerald-600 dark:text-emerald-300/90",
14 ],
15 [
16 "draft",
17 { state: "open", isDraft: true },
18 PullRequestGlyph.draft,
19 "Draft",
20 "text-zinc-500 dark:text-zinc-400/80",
21 ],
22 [
23 "closed",
24 { state: "closed", isDraft: false },
25 PullRequestGlyph.closed,
26 "Closed",
27 "text-red-600 dark:text-red-300/90",
28 ],
29 [
30 "merged",
31 { state: "merged", isDraft: false },
32 PullRequestGlyph.merged,
33 "Merged",
34 "text-violet-600 dark:text-violet-300/90",
35 ],
36 ] as const)(
37 "resolves the %s lifecycle presentation",
38 (_name, input, Icon, label, toneClassName) => {
39 expect(resolvePullRequestState(input)).toEqual({
40 Icon,
41 label,
42 toneClassName,
43 });
44 },
45 );
46
47 it("keeps a merged pull request merged when stale draft metadata is also present", () => {
48 expect(resolvePullRequestState({ state: "merged", isDraft: true })).toMatchObject({
49 Icon: PullRequestGlyph.merged,
50 label: "Merged",
51 });
52 });
53
54 it("keeps a closed pull request closed when stale draft metadata is also present", () => {
55 expect(resolvePullRequestState({ state: "closed", isDraft: true })).toMatchObject({
56 Icon: PullRequestGlyph.closed,
57 label: "Closed",
58 });
59 });
60
61 it("keeps lifecycle and conflict presentation independent for an open conflicting pull request", () => {
62 const input = {
63 state: "open" as const,
64 isDraft: false,
65 mergeability: "conflicting" as const,
66 baseBranch: "main",
67 };
68
69 expect(resolvePullRequestState(input)).toMatchObject({
70 Icon: PullRequestGlyph.pullRequest,
71 label: "Open",
72 });
73 expect(resolvePullRequestConflict(input)).toMatchObject({
74 Icon: PullRequestGlyph.conflicting,
75 label: "Conflicts with main",
76 toneClassName: "text-destructive",
77 });
78 });
79});
80
81describe("resolvePullRequestConflict", () => {
82 it.each([
83 ["closed", { state: "closed", isDraft: false }],
84 ["merged", { state: "merged", isDraft: false }],
85 ["closed draft", { state: "closed", isDraft: true }],
86 ["merged draft", { state: "merged", isDraft: true }],
87 ["open draft", { state: "open", isDraft: true }],
88 ] as const)("does not report a conflict for %s", (_name, input) => {
89 expect(
90 resolvePullRequestConflict({
91 ...input,
92 mergeability: "conflicting",
93 baseBranch: "main",
94 }),
95 ).toBeNull();
96 });
97
98 it.each([
99 ["omitted", undefined],
100 ["unknown", "unknown"],
101 ["mergeable", "mergeable"],
102 ] as const)("does not report an open conflict when mergeability is %s", (_name, mergeability) => {
103 const input = {
104 state: "open" as const,
105 isDraft: false,
106 ...(mergeability === undefined ? {} : { mergeability }),
107 };
108 expect(resolvePullRequestConflict(input)).toBeNull();
109 });
110
111 it("reports a known conflict with its base branch", () => {
112 expect(
113 resolvePullRequestConflict({
114 state: "open",
115 isDraft: false,
116 mergeability: "conflicting",
117 baseBranch: "main",
118 }),
119 ).toEqual({
120 Icon: PullRequestGlyph.conflicting,
121 label: "Conflicts with main",
122 toneClassName: "text-destructive",
123 });
124 });
125
126 it("reports a known conflict without inventing a base branch", () => {
127 expect(
128 resolvePullRequestConflict({
129 state: "open",
130 isDraft: false,
131 mergeability: "conflicting",
132 }),
133 ).toEqual({
134 Icon: PullRequestGlyph.conflicting,
135 label: "Has conflicts",
136 toneClassName: "text-destructive",
137 });
138 });
139});