@zjex/git-workflow 0.4.5 → 0.4.7

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.
@@ -7,20 +7,48 @@ import { join } from "path";
7
7
  // Mock 所有外部依赖
8
8
  vi.mock("child_process", () => ({
9
9
  execSync: vi.fn(),
10
- spawn: vi.fn(() => ({
11
- on: vi.fn(),
12
- stdin: {
13
- write: vi.fn(),
14
- end: vi.fn(),
15
- on: vi.fn(),
16
- },
17
- stdout: {
18
- on: vi.fn(),
19
- },
20
- stderr: {
21
- on: vi.fn(),
22
- },
23
- })),
10
+ spawn: vi.fn((command: string, args: string[]) => {
11
+ // 检查是否是 npm view 命令
12
+ if (command === "npm" && args[0] === "view") {
13
+ const mockProcess = {
14
+ stdout: {
15
+ on: vi.fn((event: string, callback: (data: Buffer) => void) => {
16
+ if (event === "data") {
17
+ // 立即同步调用回调,避免异步问题
18
+ callback(Buffer.from("1.2.4\n"));
19
+ }
20
+ }),
21
+ },
22
+ on: vi.fn((event: string, callback: (code?: number) => void) => {
23
+ if (event === "close") {
24
+ // 使用 queueMicrotask 而不是 setTimeout,确保在当前测试上下文中执行
25
+ queueMicrotask(() => callback(0));
26
+ }
27
+ }),
28
+ };
29
+ return mockProcess;
30
+ }
31
+
32
+ // 其他 spawn 调用(如 npm install)
33
+ return {
34
+ on: vi.fn((event: string, callback: (code?: number) => void) => {
35
+ if (event === "close") {
36
+ queueMicrotask(() => callback(0));
37
+ }
38
+ }),
39
+ stdin: {
40
+ write: vi.fn(),
41
+ end: vi.fn(),
42
+ on: vi.fn(),
43
+ },
44
+ stdout: {
45
+ on: vi.fn(),
46
+ },
47
+ stderr: {
48
+ on: vi.fn(),
49
+ },
50
+ };
51
+ }),
24
52
  }));
25
53
 
26
54
  vi.mock("fs", () => ({
@@ -79,9 +107,10 @@ describe("Update 模块测试", () => {
79
107
  vi.clearAllMocks();
80
108
  // Mock console methods
81
109
  vi.spyOn(console, "log").mockImplementation(() => {});
82
- vi.spyOn(process, "exit").mockImplementation(() => {
83
- throw new Error("process.exit called");
84
- });
110
+ // Mock process.exit 但不抛出错误,只是阻止退出
111
+ vi.spyOn(process, "exit").mockImplementation((() => {
112
+ // 不做任何事,只是阻止进程退出
113
+ }) as any);
85
114
 
86
115
  // Default mocks
87
116
  mockHomedir.mockReturnValue("/home/user");
@@ -94,8 +123,6 @@ describe("Update 模块测试", () => {
94
123
 
95
124
  describe("版本检查", () => {
96
125
  it("应该正确获取最新版本", async () => {
97
- mockExecSync.mockReturnValueOnce("1.2.4\n");
98
-
99
126
  const semver = await import("semver");
100
127
  vi.mocked(semver.default.gte).mockReturnValue(true);
101
128
 
@@ -103,19 +130,35 @@ describe("Update 模块测试", () => {
103
130
 
104
131
  await update("1.2.3");
105
132
 
106
- expect(mockExecSync).toHaveBeenCalledWith(
107
- "npm view @zjex/git-workflow version",
133
+ // 验证调用了 spawn 来获取版本
134
+ const { spawn } = await import("child_process");
135
+ expect(spawn).toHaveBeenCalledWith(
136
+ "npm",
137
+ ["view", "@zjex/git-workflow", "version"],
108
138
  expect.objectContaining({
109
- encoding: "utf-8",
110
- timeout: 3000,
111
- stdio: ["pipe", "pipe", "ignore"],
139
+ stdio: ["ignore", "pipe", "ignore"],
112
140
  }),
113
141
  );
114
142
  });
115
143
 
116
144
  it("应该处理网络错误", async () => {
117
- mockExecSync.mockImplementation(() => {
118
- throw new Error("Network error");
145
+ // 临时修改 spawn mock 来模拟错误
146
+ const { spawn } = await import("child_process");
147
+ vi.mocked(spawn).mockImplementationOnce(() => {
148
+ const mockProcess: any = {
149
+ stdout: {
150
+ on: vi.fn(),
151
+ },
152
+ on: vi.fn((event: string, callback: (code?: number) => void) => {
153
+ if (event === "error") {
154
+ setTimeout(() => callback(), 0);
155
+ }
156
+ if (event === "close") {
157
+ setTimeout(() => callback(1), 10);
158
+ }
159
+ }),
160
+ };
161
+ return mockProcess;
119
162
  });
120
163
 
121
164
  const { update } = await import("../src/commands/update.js");
@@ -128,10 +171,7 @@ describe("Update 模块测试", () => {
128
171
  });
129
172
 
130
173
  it("应该正确比较版本号", async () => {
131
- mockExecSync
132
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw (isUsingVolta)
133
- .mockReturnValueOnce("1.2.4\n") // npm view
134
- .mockReturnValueOnce("update success"); // npm install
174
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw (isUsingVolta)
135
175
 
136
176
  const semver = await import("semver");
137
177
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -151,9 +191,7 @@ describe("Update 模块测试", () => {
151
191
 
152
192
  describe("Volta 检测", () => {
153
193
  it("应该正确检测 Volta 环境", async () => {
154
- mockExecSync
155
- .mockReturnValueOnce("/home/user/.volta/bin/gw\n") // which gw (isUsingVolta)
156
- .mockReturnValueOnce("1.2.4\n"); // npm view
194
+ mockExecSync.mockReturnValueOnce("/home/user/.volta/bin/gw\n"); // which gw (isUsingVolta)
157
195
 
158
196
  const semver = await import("semver");
159
197
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -172,9 +210,7 @@ describe("Update 模块测试", () => {
172
210
  });
173
211
 
174
212
  it("应该正确检测非 Volta 环境", async () => {
175
- mockExecSync
176
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
177
- .mockReturnValueOnce("1.2.4\n"); // npm view
213
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
178
214
 
179
215
  const semver = await import("semver");
180
216
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -193,12 +229,10 @@ describe("Update 模块测试", () => {
193
229
  });
194
230
 
195
231
  it("应该处理 which 命令失败", async () => {
196
- mockExecSync
197
- .mockImplementationOnce(() => {
198
- // which gw (isUsingVolta)
199
- throw new Error("Command not found");
200
- })
201
- .mockReturnValueOnce("1.2.4\n"); // npm view
232
+ mockExecSync.mockImplementationOnce(() => {
233
+ // which gw (isUsingVolta)
234
+ throw new Error("Command not found");
235
+ });
202
236
 
203
237
  const semver = await import("semver");
204
238
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -219,9 +253,7 @@ describe("Update 模块测试", () => {
219
253
 
220
254
  describe("更新流程", () => {
221
255
  it("应该在已是最新版本时显示提示", async () => {
222
- mockExecSync
223
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw (isUsingVolta)
224
- .mockReturnValueOnce("1.2.3\n"); // npm view (same version)
256
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw (isUsingVolta)
225
257
 
226
258
  const semver = await import("semver");
227
259
  vi.mocked(semver.default.gte).mockReturnValue(true);
@@ -236,9 +268,7 @@ describe("Update 模块测试", () => {
236
268
  });
237
269
 
238
270
  it("应该成功执行更新", async () => {
239
- mockExecSync
240
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
241
- .mockReturnValueOnce("1.2.4\n"); // npm view
271
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
242
272
 
243
273
  const semver = await import("semver");
244
274
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -258,9 +288,7 @@ describe("Update 模块测试", () => {
258
288
  });
259
289
 
260
290
  it("应该处理更新失败", async () => {
261
- mockExecSync
262
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
263
- .mockReturnValueOnce("1.2.4\n"); // npm view
291
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
264
292
 
265
293
  const semver = await import("semver");
266
294
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -284,9 +312,7 @@ describe("Update 模块测试", () => {
284
312
  describe("缓存管理", () => {
285
313
  it("应该在更新成功后清理缓存", async () => {
286
314
  mockExistsSync.mockReturnValue(true);
287
- mockExecSync
288
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
289
- .mockReturnValueOnce("1.2.4\n"); // npm view
315
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
290
316
 
291
317
  const semver = await import("semver");
292
318
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -307,9 +333,7 @@ describe("Update 模块测试", () => {
307
333
 
308
334
  it("应该处理缓存文件不存在的情况", async () => {
309
335
  mockExistsSync.mockReturnValue(false);
310
- mockExecSync
311
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
312
- .mockReturnValueOnce("1.2.4\n"); // npm view
336
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
313
337
 
314
338
  const semver = await import("semver");
315
339
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -332,9 +356,7 @@ describe("Update 模块测试", () => {
332
356
  throw new Error("Permission denied");
333
357
  });
334
358
 
335
- mockExecSync
336
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
337
- .mockReturnValueOnce("1.2.4\n"); // npm view
359
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
338
360
 
339
361
  const semver = await import("semver");
340
362
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -352,9 +374,7 @@ describe("Update 模块测试", () => {
352
374
 
353
375
  describe("用户界面", () => {
354
376
  it("应该显示检查更新的提示", async () => {
355
- mockExecSync
356
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
357
- .mockReturnValueOnce("1.2.3\n");
377
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
358
378
 
359
379
  const semver = await import("semver");
360
380
  vi.mocked(semver.default.gte).mockReturnValue(true);
@@ -367,9 +387,7 @@ describe("Update 模块测试", () => {
367
387
  });
368
388
 
369
389
  it("应该显示版本比较信息", async () => {
370
- mockExecSync
371
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
372
- .mockReturnValueOnce("1.2.4\n"); // npm view
390
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
373
391
 
374
392
  const semver = await import("semver");
375
393
  vi.mocked(semver.default.gte).mockReturnValue(false);
@@ -390,9 +408,7 @@ describe("Update 模块测试", () => {
390
408
  });
391
409
 
392
410
  it("应该显示验证命令提示", async () => {
393
- mockExecSync
394
- .mockReturnValueOnce("/usr/local/bin/gw\n") // which gw
395
- .mockReturnValueOnce("1.2.4\n"); // npm view
411
+ mockExecSync.mockReturnValueOnce("/usr/local/bin/gw\n"); // which gw
396
412
 
397
413
  const semver = await import("semver");
398
414
  vi.mocked(semver.default.gte).mockReturnValue(false);