Skip to content

Commit c8c5646

Browse files
committed
feat(git): Add tests for generateCommitMessage
Adds a comprehensive suite of unit tests for the `generateCommitMessage` function. The tests cover the following scenarios: - Git extension not found - No Git repository found - No changes in the repository - AI provider not configured - Successful commit message generation for tracked files - Successful commit message generation for untracked files - Handling of errors when reading untracked files This ensures the stability and correctness of the commit message generation feature.
1 parent ee4623e commit c8c5646

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import * as vscode from "vscode"
2+
import { simpleGit, SimpleGit } from "simple-git"
3+
import { generateCommitMessage } from "../generateCommitMessage"
4+
import { ContextProxy } from "../../../core/config/ContextProxy"
5+
import { buildApiHandler } from "../../../api"
6+
import * as fs from "fs/promises"
7+
import { t } from "../../../i18n"
8+
9+
vi.mock("vscode", () => ({
10+
extensions: {
11+
getExtension: vi.fn(),
12+
},
13+
window: {
14+
showErrorMessage: vi.fn(),
15+
showInformationMessage: vi.fn(),
16+
withProgress: vi.fn((options, task) => task()),
17+
},
18+
ProgressLocation: {
19+
Notification: 15,
20+
},
21+
workspace: {
22+
workspaceFolders: [
23+
{
24+
uri: {
25+
fsPath: "/test/repo",
26+
},
27+
},
28+
],
29+
},
30+
}))
31+
32+
vi.mock("simple-git")
33+
vi.mock("../../../core/config/ContextProxy")
34+
vi.mock("../../../api")
35+
vi.mock("fs/promises")
36+
vi.mock("../../../i18n")
37+
38+
describe("generateCommitMessage", () => {
39+
let context: vscode.ExtensionContext
40+
let mockGit: any
41+
42+
beforeEach(() => {
43+
vi.clearAllMocks()
44+
45+
context = {
46+
globalState: {
47+
get: vi.fn(),
48+
update: vi.fn(),
49+
},
50+
} as any
51+
52+
mockGit = {
53+
diff: vi.fn(),
54+
status: vi.fn().mockResolvedValue({ not_added: [] }),
55+
} as any
56+
57+
vi.mocked(simpleGit).mockReturnValue(mockGit)
58+
59+
const mockGitExtension = {
60+
activate: vi.fn().mockResolvedValue(undefined),
61+
exports: {
62+
getAPI: vi.fn().mockReturnValue({
63+
repositories: [
64+
{
65+
rootUri: { fsPath: "/test/repo" },
66+
inputBox: { value: "" },
67+
},
68+
],
69+
}),
70+
},
71+
}
72+
vi.mocked(vscode.extensions.getExtension).mockReturnValue(mockGitExtension as any)
73+
74+
vi.mocked(ContextProxy.getInstance).mockResolvedValue({
75+
getProviderSettings: vi.fn().mockReturnValue({ provider: "test-provider" }),
76+
getGlobalSettings: vi.fn().mockReturnValue({ language: "en", commitLanguage: "en" }),
77+
} as any)
78+
79+
const mockProvider = {
80+
getModel: vi.fn().mockReturnValue({ id: "test-model" }),
81+
createMessage: vi.fn().mockImplementation(async function* () {
82+
yield { type: "text", text: "feat: Test commit" }
83+
}),
84+
}
85+
vi.mocked(buildApiHandler).mockReturnValue(mockProvider as any)
86+
vi.mocked(t).mockImplementation((key) => key)
87+
})
88+
89+
test("should show error if git extension is not found", async () => {
90+
vi.mocked(vscode.extensions.getExtension).mockReturnValue(undefined)
91+
await generateCommitMessage(context)
92+
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("Git extension not found.")
93+
})
94+
95+
test("should show error if no git repository is found", async () => {
96+
const mockGitExtension = {
97+
activate: vi.fn().mockResolvedValue(undefined),
98+
exports: {
99+
getAPI: vi.fn().mockReturnValue({ repositories: [] }),
100+
},
101+
}
102+
vi.mocked(vscode.extensions.getExtension).mockReturnValue(mockGitExtension as any)
103+
104+
await generateCommitMessage(context)
105+
106+
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("No Git repository found.")
107+
})
108+
109+
test("should show info if no changes are found", async () => {
110+
mockGit.diff.mockResolvedValue("")
111+
mockGit.status.mockResolvedValue({ not_added: [] })
112+
113+
await generateCommitMessage(context)
114+
115+
expect(vscode.window.showInformationMessage).toHaveBeenCalledWith("No changes found.")
116+
})
117+
118+
test("should show error if AI provider is not configured", async () => {
119+
vi.mocked(ContextProxy.getInstance).mockResolvedValue({
120+
getProviderSettings: vi.fn().mockReturnValue(null),
121+
} as any)
122+
123+
mockGit.diff.mockResolvedValue("diff --git a/file.txt b/file.txt")
124+
await generateCommitMessage(context)
125+
126+
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("AI provider not configured.")
127+
})
128+
129+
test("should generate commit message for tracked files", async () => {
130+
const diff = "diff --git a/file.txt b/file.txt\n--- a/file.txt\n+++ b/file.txt\n@@ -1 +1 @@\n-old\n+new"
131+
mockGit.diff.mockResolvedValue(diff)
132+
133+
await generateCommitMessage(context)
134+
135+
const api = vscode.extensions.getExtension("vscode.git")?.exports.getAPI(1)
136+
expect(api.repositories[0].inputBox.value).toBe("feat: Test commit")
137+
})
138+
139+
test("should generate commit message for untracked files", async () => {
140+
mockGit.diff.mockResolvedValue("")
141+
mockGit.status.mockResolvedValue({ not_added: ["new_file.txt"] })
142+
vi.mocked(fs.readFile).mockResolvedValue("new content")
143+
144+
await generateCommitMessage(context)
145+
146+
const api = vscode.extensions.getExtension("vscode.git")?.exports.getAPI(1)
147+
expect(api.repositories[0].inputBox.value).toBe("feat: Test commit")
148+
})
149+
150+
test("should generate commit message for both tracked and untracked files", async () => {
151+
const diff = "diff --git a/file.txt b/file.txt\n--- a/file.txt\n+++ b/file.txt\n@@ -1 +1 @@\n-old\n+new"
152+
mockGit.diff.mockResolvedValue(diff)
153+
mockGit.status.mockResolvedValue({ not_added: ["new_file.txt"] })
154+
vi.mocked(fs.readFile).mockResolvedValue("new content")
155+
156+
await generateCommitMessage(context)
157+
158+
const api = vscode.extensions.getExtension("vscode.git")?.exports.getAPI(1)
159+
expect(api.repositories[0].inputBox.value).toBe("feat: Test commit")
160+
})
161+
162+
test("should handle error when reading untracked file", async () => {
163+
mockGit.diff.mockResolvedValue("")
164+
mockGit.status.mockResolvedValue({ not_added: ["new_file.txt"] })
165+
vi.mocked(fs.readFile).mockRejectedValue(new Error("File not found"))
166+
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {})
167+
168+
await generateCommitMessage(context)
169+
170+
expect(consoleErrorSpy).toHaveBeenCalledWith("Could not read untracked file new_file.txt", expect.any(Error))
171+
expect(vscode.window.showInformationMessage).toHaveBeenCalledWith("No changes found.")
172+
const api = vscode.extensions.getExtension("vscode.git")?.exports.getAPI(1)
173+
expect(api.repositories[0].inputBox.value).toBe("")
174+
consoleErrorSpy.mockRestore()
175+
})
176+
})

0 commit comments

Comments
 (0)