Skip to content

Commit 5be495c

Browse files
committed
test(git): cover branch creation utility success and failure paths
1 parent d3231da commit 5be495c

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
3+
const { mockCreateBranchMutate, mockInvalidateGitBranchQueries } = vi.hoisted(
4+
() => ({
5+
mockCreateBranchMutate: vi.fn(),
6+
mockInvalidateGitBranchQueries: vi.fn(),
7+
}),
8+
);
9+
10+
vi.mock("@renderer/trpc", () => ({
11+
trpcClient: {
12+
git: {
13+
createBranch: {
14+
mutate: mockCreateBranchMutate,
15+
},
16+
},
17+
},
18+
}));
19+
20+
vi.mock("@features/git-interaction/utils/gitCacheKeys", () => ({
21+
invalidateGitBranchQueries: mockInvalidateGitBranchQueries,
22+
}));
23+
24+
import { createBranch, getBranchNameInputState } from "./branchCreation";
25+
26+
describe("branchCreation", () => {
27+
beforeEach(() => {
28+
vi.clearAllMocks();
29+
});
30+
31+
describe("getBranchNameInputState", () => {
32+
it("sanitizes spaces and returns no error for valid names", () => {
33+
expect(getBranchNameInputState("feature my branch")).toEqual({
34+
sanitized: "feature-my-branch",
35+
error: null,
36+
});
37+
});
38+
39+
it("returns validation errors for invalid names", () => {
40+
expect(getBranchNameInputState("feature..branch")).toEqual({
41+
sanitized: "feature..branch",
42+
error: 'Branch name cannot contain "..".',
43+
});
44+
});
45+
});
46+
47+
describe("createBranch", () => {
48+
it("returns missing-repo error when repo path is not provided", async () => {
49+
const result = await createBranch({
50+
repoPath: undefined,
51+
rawBranchName: "feature/test",
52+
});
53+
54+
expect(result).toEqual({
55+
success: false,
56+
error: "Select a repository folder first.",
57+
reason: "missing-repo",
58+
});
59+
expect(mockCreateBranchMutate).not.toHaveBeenCalled();
60+
expect(mockInvalidateGitBranchQueries).not.toHaveBeenCalled();
61+
});
62+
63+
it("returns validation error for empty branch name", async () => {
64+
const result = await createBranch({
65+
repoPath: "/repo",
66+
rawBranchName: " ",
67+
});
68+
69+
expect(result).toEqual({
70+
success: false,
71+
error: "Branch name is required.",
72+
reason: "validation",
73+
});
74+
expect(mockCreateBranchMutate).not.toHaveBeenCalled();
75+
expect(mockInvalidateGitBranchQueries).not.toHaveBeenCalled();
76+
});
77+
78+
it("returns validation error for invalid branch names", async () => {
79+
const result = await createBranch({
80+
repoPath: "/repo",
81+
rawBranchName: "feature..branch",
82+
});
83+
84+
expect(result).toEqual({
85+
success: false,
86+
error: 'Branch name cannot contain "..".',
87+
reason: "validation",
88+
});
89+
expect(mockCreateBranchMutate).not.toHaveBeenCalled();
90+
expect(mockInvalidateGitBranchQueries).not.toHaveBeenCalled();
91+
});
92+
93+
it("creates branch with trimmed name and invalidates branch queries", async () => {
94+
mockCreateBranchMutate.mockResolvedValueOnce(undefined);
95+
96+
const result = await createBranch({
97+
repoPath: "/repo",
98+
rawBranchName: " feature/test ",
99+
});
100+
101+
expect(mockCreateBranchMutate).toHaveBeenCalledWith({
102+
directoryPath: "/repo",
103+
branchName: "feature/test",
104+
});
105+
expect(mockInvalidateGitBranchQueries).toHaveBeenCalledWith("/repo");
106+
expect(result).toEqual({
107+
success: true,
108+
branchName: "feature/test",
109+
});
110+
});
111+
112+
it("returns request error with message when mutate throws Error", async () => {
113+
const error = new Error("boom");
114+
mockCreateBranchMutate.mockRejectedValueOnce(error);
115+
116+
const result = await createBranch({
117+
repoPath: "/repo",
118+
rawBranchName: "feature/test",
119+
});
120+
121+
expect(result).toEqual({
122+
success: false,
123+
error: "boom",
124+
reason: "request",
125+
rawError: error,
126+
});
127+
expect(mockInvalidateGitBranchQueries).not.toHaveBeenCalled();
128+
});
129+
130+
it("returns fallback error when mutate throws non-Error value", async () => {
131+
mockCreateBranchMutate.mockRejectedValueOnce("oops");
132+
133+
const result = await createBranch({
134+
repoPath: "/repo",
135+
rawBranchName: "feature/test",
136+
});
137+
138+
expect(result).toEqual({
139+
success: false,
140+
error: "Failed to create branch.",
141+
reason: "request",
142+
rawError: "oops",
143+
});
144+
expect(mockInvalidateGitBranchQueries).not.toHaveBeenCalled();
145+
});
146+
});
147+
});

0 commit comments

Comments
 (0)