@zjex/git-workflow 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/index.js +155 -71
- package/docs/commands/config.md +4 -1
- package/docs/commands/review.md +3 -0
- package/docs/config/config-file.md +19 -1
- package/docs/config/index.md +3 -1
- package/docs/guide/ai-review.md +6 -0
- package/docs/guide/tag-management.md +14 -1
- package/package.json +2 -2
- package/src/commands/init.ts +18 -0
- package/src/commands/review.ts +59 -16
- package/src/commands/tag.ts +39 -15
- package/src/config.ts +3 -0
- package/src/tag-utils.ts +37 -0
- package/src/update-notifier.ts +46 -42
- package/tests/config.test.ts +18 -0
- package/tests/init.test.ts +111 -275
- package/tests/tag.test.ts +67 -24
- package/tests/update-notifier.test.ts +29 -76
package/tests/init.test.ts
CHANGED
|
@@ -40,6 +40,74 @@ describe("Init 模块测试", () => {
|
|
|
40
40
|
const mockJoin = vi.mocked(join);
|
|
41
41
|
const mockHomedir = vi.mocked(homedir);
|
|
42
42
|
|
|
43
|
+
async function mockBasicInitFlow(options?: {
|
|
44
|
+
scope?: "global" | "project";
|
|
45
|
+
exists?: boolean;
|
|
46
|
+
overwrite?: boolean;
|
|
47
|
+
requireId?: boolean;
|
|
48
|
+
featureRequireDescription?: boolean;
|
|
49
|
+
hotfixRequireDescription?: boolean;
|
|
50
|
+
tagLookupStrategy?: "all" | "latest";
|
|
51
|
+
autoPushChoice?: "ask" | "yes" | "no";
|
|
52
|
+
autoStage?: boolean;
|
|
53
|
+
useEmoji?: boolean;
|
|
54
|
+
enableAI?: boolean;
|
|
55
|
+
inputs?: {
|
|
56
|
+
baseBranch?: string;
|
|
57
|
+
featurePrefix?: string;
|
|
58
|
+
hotfixPrefix?: string;
|
|
59
|
+
featureIdLabel?: string;
|
|
60
|
+
hotfixIdLabel?: string;
|
|
61
|
+
defaultTagPrefix?: string;
|
|
62
|
+
};
|
|
63
|
+
}) {
|
|
64
|
+
const {
|
|
65
|
+
scope = "project",
|
|
66
|
+
exists = false,
|
|
67
|
+
overwrite,
|
|
68
|
+
requireId = false,
|
|
69
|
+
featureRequireDescription = false,
|
|
70
|
+
hotfixRequireDescription = false,
|
|
71
|
+
tagLookupStrategy = "latest",
|
|
72
|
+
autoPushChoice = "ask",
|
|
73
|
+
autoStage = true,
|
|
74
|
+
useEmoji = true,
|
|
75
|
+
enableAI = false,
|
|
76
|
+
inputs = {},
|
|
77
|
+
} = options ?? {};
|
|
78
|
+
|
|
79
|
+
mockExistsSync.mockReturnValue(exists);
|
|
80
|
+
|
|
81
|
+
const { select, input } = await import("@inquirer/prompts");
|
|
82
|
+
const selectMock = vi.mocked(select);
|
|
83
|
+
const inputMock = vi.mocked(input);
|
|
84
|
+
|
|
85
|
+
selectMock.mockResolvedValueOnce(scope);
|
|
86
|
+
if (exists) {
|
|
87
|
+
selectMock.mockResolvedValueOnce(overwrite ?? true);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
selectMock
|
|
91
|
+
.mockResolvedValueOnce(requireId)
|
|
92
|
+
.mockResolvedValueOnce(featureRequireDescription)
|
|
93
|
+
.mockResolvedValueOnce(hotfixRequireDescription)
|
|
94
|
+
.mockResolvedValueOnce(tagLookupStrategy)
|
|
95
|
+
.mockResolvedValueOnce(autoPushChoice)
|
|
96
|
+
.mockResolvedValueOnce(autoStage)
|
|
97
|
+
.mockResolvedValueOnce(useEmoji)
|
|
98
|
+
.mockResolvedValueOnce(enableAI);
|
|
99
|
+
|
|
100
|
+
inputMock
|
|
101
|
+
.mockResolvedValueOnce(inputs.baseBranch ?? "")
|
|
102
|
+
.mockResolvedValueOnce(inputs.featurePrefix ?? "feature")
|
|
103
|
+
.mockResolvedValueOnce(inputs.hotfixPrefix ?? "hotfix")
|
|
104
|
+
.mockResolvedValueOnce(inputs.featureIdLabel ?? "Story ID")
|
|
105
|
+
.mockResolvedValueOnce(inputs.hotfixIdLabel ?? "Issue ID")
|
|
106
|
+
.mockResolvedValueOnce(inputs.defaultTagPrefix ?? "");
|
|
107
|
+
|
|
108
|
+
return { select: selectMock, input: inputMock };
|
|
109
|
+
}
|
|
110
|
+
|
|
43
111
|
beforeEach(() => {
|
|
44
112
|
vi.clearAllMocks();
|
|
45
113
|
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
@@ -53,24 +121,7 @@ describe("Init 模块测试", () => {
|
|
|
53
121
|
|
|
54
122
|
describe("配置范围选择", () => {
|
|
55
123
|
it("应该支持全局配置", async () => {
|
|
56
|
-
|
|
57
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
58
|
-
vi.mocked(select)
|
|
59
|
-
.mockResolvedValueOnce("global")
|
|
60
|
-
.mockResolvedValueOnce(false)
|
|
61
|
-
.mockResolvedValueOnce(false)
|
|
62
|
-
.mockResolvedValueOnce(false)
|
|
63
|
-
.mockResolvedValueOnce("ask")
|
|
64
|
-
.mockResolvedValueOnce(true)
|
|
65
|
-
.mockResolvedValueOnce(true)
|
|
66
|
-
.mockResolvedValueOnce(false);
|
|
67
|
-
vi.mocked(input)
|
|
68
|
-
.mockResolvedValueOnce("")
|
|
69
|
-
.mockResolvedValueOnce("feature")
|
|
70
|
-
.mockResolvedValueOnce("hotfix")
|
|
71
|
-
.mockResolvedValueOnce("Story ID")
|
|
72
|
-
.mockResolvedValueOnce("Issue ID")
|
|
73
|
-
.mockResolvedValueOnce("");
|
|
124
|
+
await mockBasicInitFlow({ scope: "global" });
|
|
74
125
|
const { init } = await import("../src/commands/init.js");
|
|
75
126
|
await init();
|
|
76
127
|
expect(mockJoin).toHaveBeenCalledWith("/home/user", ".gwrc.json");
|
|
@@ -81,24 +132,7 @@ describe("Init 模块测试", () => {
|
|
|
81
132
|
});
|
|
82
133
|
|
|
83
134
|
it("应该支持项目配置", async () => {
|
|
84
|
-
|
|
85
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
86
|
-
vi.mocked(select)
|
|
87
|
-
.mockResolvedValueOnce("project")
|
|
88
|
-
.mockResolvedValueOnce(false)
|
|
89
|
-
.mockResolvedValueOnce(false)
|
|
90
|
-
.mockResolvedValueOnce(false)
|
|
91
|
-
.mockResolvedValueOnce("ask")
|
|
92
|
-
.mockResolvedValueOnce(true)
|
|
93
|
-
.mockResolvedValueOnce(true)
|
|
94
|
-
.mockResolvedValueOnce(false);
|
|
95
|
-
vi.mocked(input)
|
|
96
|
-
.mockResolvedValueOnce("")
|
|
97
|
-
.mockResolvedValueOnce("feature")
|
|
98
|
-
.mockResolvedValueOnce("hotfix")
|
|
99
|
-
.mockResolvedValueOnce("Story ID")
|
|
100
|
-
.mockResolvedValueOnce("Issue ID")
|
|
101
|
-
.mockResolvedValueOnce("");
|
|
135
|
+
await mockBasicInitFlow({ scope: "project" });
|
|
102
136
|
const { init } = await import("../src/commands/init.js");
|
|
103
137
|
await init();
|
|
104
138
|
expect(mockWriteFileSync).toHaveBeenCalledWith(
|
|
@@ -110,25 +144,7 @@ describe("Init 模块测试", () => {
|
|
|
110
144
|
|
|
111
145
|
describe("配置文件覆盖", () => {
|
|
112
146
|
it("应该处理配置文件已存在的情况", async () => {
|
|
113
|
-
|
|
114
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
115
|
-
vi.mocked(select)
|
|
116
|
-
.mockResolvedValueOnce("global")
|
|
117
|
-
.mockResolvedValueOnce(true)
|
|
118
|
-
.mockResolvedValueOnce(false)
|
|
119
|
-
.mockResolvedValueOnce(false)
|
|
120
|
-
.mockResolvedValueOnce(false)
|
|
121
|
-
.mockResolvedValueOnce("ask")
|
|
122
|
-
.mockResolvedValueOnce(true)
|
|
123
|
-
.mockResolvedValueOnce(true)
|
|
124
|
-
.mockResolvedValueOnce(false);
|
|
125
|
-
vi.mocked(input)
|
|
126
|
-
.mockResolvedValueOnce("")
|
|
127
|
-
.mockResolvedValueOnce("feature")
|
|
128
|
-
.mockResolvedValueOnce("hotfix")
|
|
129
|
-
.mockResolvedValueOnce("Story ID")
|
|
130
|
-
.mockResolvedValueOnce("Issue ID")
|
|
131
|
-
.mockResolvedValueOnce("");
|
|
147
|
+
await mockBasicInitFlow({ scope: "global", exists: true, overwrite: true });
|
|
132
148
|
const { init } = await import("../src/commands/init.js");
|
|
133
149
|
await init();
|
|
134
150
|
expect(mockWriteFileSync).toHaveBeenCalled();
|
|
@@ -149,24 +165,16 @@ describe("Init 模块测试", () => {
|
|
|
149
165
|
|
|
150
166
|
describe("基础配置", () => {
|
|
151
167
|
it("应该正确配置分支前缀", async () => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
.mockResolvedValueOnce(false);
|
|
163
|
-
vi.mocked(input)
|
|
164
|
-
.mockResolvedValueOnce("develop")
|
|
165
|
-
.mockResolvedValueOnce("feat")
|
|
166
|
-
.mockResolvedValueOnce("fix")
|
|
167
|
-
.mockResolvedValueOnce("Jira ID")
|
|
168
|
-
.mockResolvedValueOnce("Bug ID")
|
|
169
|
-
.mockResolvedValueOnce("v");
|
|
168
|
+
await mockBasicInitFlow({
|
|
169
|
+
inputs: {
|
|
170
|
+
baseBranch: "develop",
|
|
171
|
+
featurePrefix: "feat",
|
|
172
|
+
hotfixPrefix: "fix",
|
|
173
|
+
featureIdLabel: "Jira ID",
|
|
174
|
+
hotfixIdLabel: "Bug ID",
|
|
175
|
+
defaultTagPrefix: "v",
|
|
176
|
+
},
|
|
177
|
+
});
|
|
170
178
|
const { init } = await import("../src/commands/init.js");
|
|
171
179
|
await init();
|
|
172
180
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -177,27 +185,11 @@ describe("Init 模块测试", () => {
|
|
|
177
185
|
expect(config.featureIdLabel).toBe("Jira ID");
|
|
178
186
|
expect(config.hotfixIdLabel).toBe("Bug ID");
|
|
179
187
|
expect(config.defaultTagPrefix).toBe("v");
|
|
188
|
+
expect(config.tagLookupStrategy).toBe("latest");
|
|
180
189
|
});
|
|
181
190
|
|
|
182
191
|
it("应该正确配置 ID 要求", async () => {
|
|
183
|
-
|
|
184
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
185
|
-
vi.mocked(select)
|
|
186
|
-
.mockResolvedValueOnce("project")
|
|
187
|
-
.mockResolvedValueOnce(true)
|
|
188
|
-
.mockResolvedValueOnce(false)
|
|
189
|
-
.mockResolvedValueOnce(false)
|
|
190
|
-
.mockResolvedValueOnce("ask")
|
|
191
|
-
.mockResolvedValueOnce(true)
|
|
192
|
-
.mockResolvedValueOnce(true)
|
|
193
|
-
.mockResolvedValueOnce(false);
|
|
194
|
-
vi.mocked(input)
|
|
195
|
-
.mockResolvedValueOnce("")
|
|
196
|
-
.mockResolvedValueOnce("feature")
|
|
197
|
-
.mockResolvedValueOnce("hotfix")
|
|
198
|
-
.mockResolvedValueOnce("Story ID")
|
|
199
|
-
.mockResolvedValueOnce("Issue ID")
|
|
200
|
-
.mockResolvedValueOnce("");
|
|
192
|
+
await mockBasicInitFlow({ requireId: true });
|
|
201
193
|
const { init } = await import("../src/commands/init.js");
|
|
202
194
|
await init();
|
|
203
195
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -206,57 +198,33 @@ describe("Init 模块测试", () => {
|
|
|
206
198
|
});
|
|
207
199
|
|
|
208
200
|
it("应该正确配置自动推送选项", async () => {
|
|
209
|
-
|
|
210
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
211
|
-
vi.mocked(select)
|
|
212
|
-
.mockResolvedValueOnce("project")
|
|
213
|
-
.mockResolvedValueOnce(false)
|
|
214
|
-
.mockResolvedValueOnce(false)
|
|
215
|
-
.mockResolvedValueOnce(false)
|
|
216
|
-
.mockResolvedValueOnce("yes")
|
|
217
|
-
.mockResolvedValueOnce(true)
|
|
218
|
-
.mockResolvedValueOnce(true)
|
|
219
|
-
.mockResolvedValueOnce(false);
|
|
220
|
-
vi.mocked(input)
|
|
221
|
-
.mockResolvedValueOnce("")
|
|
222
|
-
.mockResolvedValueOnce("feature")
|
|
223
|
-
.mockResolvedValueOnce("hotfix")
|
|
224
|
-
.mockResolvedValueOnce("Story ID")
|
|
225
|
-
.mockResolvedValueOnce("Issue ID")
|
|
226
|
-
.mockResolvedValueOnce("");
|
|
201
|
+
await mockBasicInitFlow({ autoPushChoice: "yes" });
|
|
227
202
|
const { init } = await import("../src/commands/init.js");
|
|
228
203
|
await init();
|
|
229
204
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
230
205
|
const config = JSON.parse(writtenConfig);
|
|
231
206
|
expect(config.autoPush).toBe(true);
|
|
232
207
|
});
|
|
208
|
+
|
|
209
|
+
it("应该支持配置 tagLookupStrategy 为 latest", async () => {
|
|
210
|
+
await mockBasicInitFlow({ tagLookupStrategy: "latest" });
|
|
211
|
+
const { init } = await import("../src/commands/init.js");
|
|
212
|
+
await init();
|
|
213
|
+
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
214
|
+
const config = JSON.parse(writtenConfig);
|
|
215
|
+
expect(config.tagLookupStrategy).toBe("latest");
|
|
216
|
+
});
|
|
233
217
|
});
|
|
234
218
|
|
|
235
219
|
describe("AI 配置", () => {
|
|
236
220
|
it("应该正确配置 GitHub Models", async () => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
vi.mocked(select)
|
|
240
|
-
.mockResolvedValueOnce("project")
|
|
241
|
-
.mockResolvedValueOnce(false)
|
|
242
|
-
.mockResolvedValueOnce(false)
|
|
243
|
-
.mockResolvedValueOnce(false)
|
|
244
|
-
.mockResolvedValueOnce("ask")
|
|
245
|
-
.mockResolvedValueOnce(true)
|
|
246
|
-
.mockResolvedValueOnce(true)
|
|
247
|
-
.mockResolvedValueOnce(true)
|
|
221
|
+
const { select, input } = await mockBasicInitFlow({ enableAI: true });
|
|
222
|
+
select
|
|
248
223
|
.mockResolvedValueOnce("github")
|
|
249
224
|
.mockResolvedValueOnce("zh-CN")
|
|
250
225
|
.mockResolvedValueOnce(true)
|
|
251
226
|
.mockResolvedValueOnce(true);
|
|
252
|
-
|
|
253
|
-
.mockResolvedValueOnce("")
|
|
254
|
-
.mockResolvedValueOnce("feature")
|
|
255
|
-
.mockResolvedValueOnce("hotfix")
|
|
256
|
-
.mockResolvedValueOnce("Story ID")
|
|
257
|
-
.mockResolvedValueOnce("Issue ID")
|
|
258
|
-
.mockResolvedValueOnce("")
|
|
259
|
-
.mockResolvedValueOnce("ghp_test_token");
|
|
227
|
+
input.mockResolvedValueOnce("ghp_test_token");
|
|
260
228
|
const { init } = await import("../src/commands/init.js");
|
|
261
229
|
await init();
|
|
262
230
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -269,29 +237,13 @@ describe("Init 模块测试", () => {
|
|
|
269
237
|
});
|
|
270
238
|
|
|
271
239
|
it("应该正确配置 OpenAI", async () => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
vi.mocked(select)
|
|
275
|
-
.mockResolvedValueOnce("project")
|
|
276
|
-
.mockResolvedValueOnce(false)
|
|
277
|
-
.mockResolvedValueOnce(false)
|
|
278
|
-
.mockResolvedValueOnce(false)
|
|
279
|
-
.mockResolvedValueOnce("ask")
|
|
280
|
-
.mockResolvedValueOnce(true)
|
|
281
|
-
.mockResolvedValueOnce(true)
|
|
282
|
-
.mockResolvedValueOnce(true)
|
|
240
|
+
const { select, input } = await mockBasicInitFlow({ enableAI: true });
|
|
241
|
+
select
|
|
283
242
|
.mockResolvedValueOnce("openai")
|
|
284
243
|
.mockResolvedValueOnce("en-US")
|
|
285
244
|
.mockResolvedValueOnce(true)
|
|
286
245
|
.mockResolvedValueOnce(true);
|
|
287
|
-
|
|
288
|
-
.mockResolvedValueOnce("")
|
|
289
|
-
.mockResolvedValueOnce("feature")
|
|
290
|
-
.mockResolvedValueOnce("hotfix")
|
|
291
|
-
.mockResolvedValueOnce("Story ID")
|
|
292
|
-
.mockResolvedValueOnce("Issue ID")
|
|
293
|
-
.mockResolvedValueOnce("")
|
|
294
|
-
.mockResolvedValueOnce("sk-test-key");
|
|
246
|
+
input.mockResolvedValueOnce("sk-test-key");
|
|
295
247
|
const { init } = await import("../src/commands/init.js");
|
|
296
248
|
await init();
|
|
297
249
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -304,28 +256,12 @@ describe("Init 模块测试", () => {
|
|
|
304
256
|
});
|
|
305
257
|
|
|
306
258
|
it("应该正确配置 Ollama", async () => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
vi.mocked(select)
|
|
310
|
-
.mockResolvedValueOnce("project")
|
|
311
|
-
.mockResolvedValueOnce(false)
|
|
312
|
-
.mockResolvedValueOnce(false)
|
|
313
|
-
.mockResolvedValueOnce(false)
|
|
314
|
-
.mockResolvedValueOnce("ask")
|
|
315
|
-
.mockResolvedValueOnce(true)
|
|
316
|
-
.mockResolvedValueOnce(true)
|
|
317
|
-
.mockResolvedValueOnce(true)
|
|
259
|
+
const { select } = await mockBasicInitFlow({ enableAI: true });
|
|
260
|
+
select
|
|
318
261
|
.mockResolvedValueOnce("ollama")
|
|
319
262
|
.mockResolvedValueOnce("zh-CN")
|
|
320
263
|
.mockResolvedValueOnce(true)
|
|
321
264
|
.mockResolvedValueOnce(true);
|
|
322
|
-
vi.mocked(input)
|
|
323
|
-
.mockResolvedValueOnce("")
|
|
324
|
-
.mockResolvedValueOnce("feature")
|
|
325
|
-
.mockResolvedValueOnce("hotfix")
|
|
326
|
-
.mockResolvedValueOnce("Story ID")
|
|
327
|
-
.mockResolvedValueOnce("Issue ID")
|
|
328
|
-
.mockResolvedValueOnce("");
|
|
329
265
|
const { init } = await import("../src/commands/init.js");
|
|
330
266
|
await init();
|
|
331
267
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -338,24 +274,7 @@ describe("Init 模块测试", () => {
|
|
|
338
274
|
});
|
|
339
275
|
|
|
340
276
|
it("应该正确配置禁用 AI", async () => {
|
|
341
|
-
|
|
342
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
343
|
-
vi.mocked(select)
|
|
344
|
-
.mockResolvedValueOnce("project")
|
|
345
|
-
.mockResolvedValueOnce(false)
|
|
346
|
-
.mockResolvedValueOnce(false)
|
|
347
|
-
.mockResolvedValueOnce(false)
|
|
348
|
-
.mockResolvedValueOnce("ask")
|
|
349
|
-
.mockResolvedValueOnce(true)
|
|
350
|
-
.mockResolvedValueOnce(true)
|
|
351
|
-
.mockResolvedValueOnce(false);
|
|
352
|
-
vi.mocked(input)
|
|
353
|
-
.mockResolvedValueOnce("")
|
|
354
|
-
.mockResolvedValueOnce("feature")
|
|
355
|
-
.mockResolvedValueOnce("hotfix")
|
|
356
|
-
.mockResolvedValueOnce("Story ID")
|
|
357
|
-
.mockResolvedValueOnce("Issue ID")
|
|
358
|
-
.mockResolvedValueOnce("");
|
|
277
|
+
await mockBasicInitFlow({ enableAI: false });
|
|
359
278
|
const { init } = await import("../src/commands/init.js");
|
|
360
279
|
await init();
|
|
361
280
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -366,29 +285,13 @@ describe("Init 模块测试", () => {
|
|
|
366
285
|
|
|
367
286
|
describe("配置验证", () => {
|
|
368
287
|
it("应该验证 GitHub Token 不为空", async () => {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
vi.mocked(select)
|
|
372
|
-
.mockResolvedValueOnce("project")
|
|
373
|
-
.mockResolvedValueOnce(false)
|
|
374
|
-
.mockResolvedValueOnce(false)
|
|
375
|
-
.mockResolvedValueOnce(false)
|
|
376
|
-
.mockResolvedValueOnce("ask")
|
|
377
|
-
.mockResolvedValueOnce(true)
|
|
378
|
-
.mockResolvedValueOnce(true)
|
|
379
|
-
.mockResolvedValueOnce(true)
|
|
288
|
+
const { select, input } = await mockBasicInitFlow({ enableAI: true });
|
|
289
|
+
select
|
|
380
290
|
.mockResolvedValueOnce("github")
|
|
381
291
|
.mockResolvedValueOnce("zh-CN")
|
|
382
292
|
.mockResolvedValueOnce(true)
|
|
383
293
|
.mockResolvedValueOnce(true);
|
|
384
|
-
|
|
385
|
-
.mockResolvedValueOnce("")
|
|
386
|
-
.mockResolvedValueOnce("feature")
|
|
387
|
-
.mockResolvedValueOnce("hotfix")
|
|
388
|
-
.mockResolvedValueOnce("Story ID")
|
|
389
|
-
.mockResolvedValueOnce("Issue ID")
|
|
390
|
-
.mockResolvedValueOnce("")
|
|
391
|
-
.mockResolvedValueOnce("ghp_valid_token");
|
|
294
|
+
input.mockResolvedValueOnce("ghp_valid_token");
|
|
392
295
|
const { init } = await import("../src/commands/init.js");
|
|
393
296
|
await init();
|
|
394
297
|
const inputCalls = vi.mocked(input).mock.calls;
|
|
@@ -403,29 +306,13 @@ describe("Init 模块测试", () => {
|
|
|
403
306
|
});
|
|
404
307
|
|
|
405
308
|
it("应该验证 OpenAI API Key 不为空", async () => {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
vi.mocked(select)
|
|
409
|
-
.mockResolvedValueOnce("project")
|
|
410
|
-
.mockResolvedValueOnce(false)
|
|
411
|
-
.mockResolvedValueOnce(false)
|
|
412
|
-
.mockResolvedValueOnce(false)
|
|
413
|
-
.mockResolvedValueOnce("ask")
|
|
414
|
-
.mockResolvedValueOnce(true)
|
|
415
|
-
.mockResolvedValueOnce(true)
|
|
416
|
-
.mockResolvedValueOnce(true)
|
|
309
|
+
const { select, input } = await mockBasicInitFlow({ enableAI: true });
|
|
310
|
+
select
|
|
417
311
|
.mockResolvedValueOnce("openai")
|
|
418
312
|
.mockResolvedValueOnce("en-US")
|
|
419
313
|
.mockResolvedValueOnce(true)
|
|
420
314
|
.mockResolvedValueOnce(true);
|
|
421
|
-
|
|
422
|
-
.mockResolvedValueOnce("")
|
|
423
|
-
.mockResolvedValueOnce("feature")
|
|
424
|
-
.mockResolvedValueOnce("hotfix")
|
|
425
|
-
.mockResolvedValueOnce("Story ID")
|
|
426
|
-
.mockResolvedValueOnce("Issue ID")
|
|
427
|
-
.mockResolvedValueOnce("")
|
|
428
|
-
.mockResolvedValueOnce("sk-valid-key");
|
|
315
|
+
input.mockResolvedValueOnce("sk-valid-key");
|
|
429
316
|
const { init } = await import("../src/commands/init.js");
|
|
430
317
|
await init();
|
|
431
318
|
const inputCalls = vi.mocked(input).mock.calls;
|
|
@@ -442,24 +329,7 @@ describe("Init 模块测试", () => {
|
|
|
442
329
|
|
|
443
330
|
describe("配置输出", () => {
|
|
444
331
|
it("应该包含默认的 commit emojis", async () => {
|
|
445
|
-
|
|
446
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
447
|
-
vi.mocked(select)
|
|
448
|
-
.mockResolvedValueOnce("project")
|
|
449
|
-
.mockResolvedValueOnce(false)
|
|
450
|
-
.mockResolvedValueOnce(false)
|
|
451
|
-
.mockResolvedValueOnce(false)
|
|
452
|
-
.mockResolvedValueOnce("ask")
|
|
453
|
-
.mockResolvedValueOnce(true)
|
|
454
|
-
.mockResolvedValueOnce(true)
|
|
455
|
-
.mockResolvedValueOnce(false);
|
|
456
|
-
vi.mocked(input)
|
|
457
|
-
.mockResolvedValueOnce("")
|
|
458
|
-
.mockResolvedValueOnce("feature")
|
|
459
|
-
.mockResolvedValueOnce("hotfix")
|
|
460
|
-
.mockResolvedValueOnce("Story ID")
|
|
461
|
-
.mockResolvedValueOnce("Issue ID")
|
|
462
|
-
.mockResolvedValueOnce("");
|
|
332
|
+
await mockBasicInitFlow();
|
|
463
333
|
const { init } = await import("../src/commands/init.js");
|
|
464
334
|
await init();
|
|
465
335
|
const writtenConfig = mockWriteFileSync.mock.calls[0][1] as string;
|
|
@@ -471,24 +341,7 @@ describe("Init 模块测试", () => {
|
|
|
471
341
|
});
|
|
472
342
|
|
|
473
343
|
it("应该显示成功消息", async () => {
|
|
474
|
-
|
|
475
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
476
|
-
vi.mocked(select)
|
|
477
|
-
.mockResolvedValueOnce("global")
|
|
478
|
-
.mockResolvedValueOnce(false)
|
|
479
|
-
.mockResolvedValueOnce(false)
|
|
480
|
-
.mockResolvedValueOnce(false)
|
|
481
|
-
.mockResolvedValueOnce("ask")
|
|
482
|
-
.mockResolvedValueOnce(true)
|
|
483
|
-
.mockResolvedValueOnce(true)
|
|
484
|
-
.mockResolvedValueOnce(false);
|
|
485
|
-
vi.mocked(input)
|
|
486
|
-
.mockResolvedValueOnce("")
|
|
487
|
-
.mockResolvedValueOnce("feature")
|
|
488
|
-
.mockResolvedValueOnce("hotfix")
|
|
489
|
-
.mockResolvedValueOnce("Story ID")
|
|
490
|
-
.mockResolvedValueOnce("Issue ID")
|
|
491
|
-
.mockResolvedValueOnce("");
|
|
344
|
+
await mockBasicInitFlow({ scope: "global" });
|
|
492
345
|
const { init } = await import("../src/commands/init.js");
|
|
493
346
|
await init();
|
|
494
347
|
expect(console.log).toHaveBeenCalledWith(
|
|
@@ -497,24 +350,7 @@ describe("Init 模块测试", () => {
|
|
|
497
350
|
});
|
|
498
351
|
|
|
499
352
|
it("应该显示全局配置的提示信息", async () => {
|
|
500
|
-
|
|
501
|
-
const { select, input } = await import("@inquirer/prompts");
|
|
502
|
-
vi.mocked(select)
|
|
503
|
-
.mockResolvedValueOnce("global")
|
|
504
|
-
.mockResolvedValueOnce(false)
|
|
505
|
-
.mockResolvedValueOnce(false)
|
|
506
|
-
.mockResolvedValueOnce(false)
|
|
507
|
-
.mockResolvedValueOnce("ask")
|
|
508
|
-
.mockResolvedValueOnce(true)
|
|
509
|
-
.mockResolvedValueOnce(true)
|
|
510
|
-
.mockResolvedValueOnce(false);
|
|
511
|
-
vi.mocked(input)
|
|
512
|
-
.mockResolvedValueOnce("")
|
|
513
|
-
.mockResolvedValueOnce("feature")
|
|
514
|
-
.mockResolvedValueOnce("hotfix")
|
|
515
|
-
.mockResolvedValueOnce("Story ID")
|
|
516
|
-
.mockResolvedValueOnce("Issue ID")
|
|
517
|
-
.mockResolvedValueOnce("");
|
|
353
|
+
await mockBasicInitFlow({ scope: "global" });
|
|
518
354
|
const { init } = await import("../src/commands/init.js");
|
|
519
355
|
await init();
|
|
520
356
|
expect(console.log).toHaveBeenCalledWith(
|