bbk-cli 1.1.2 → 1.2.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.
Files changed (39) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/README.md +113 -132
  4. package/dist/cli/wrapper.d.ts +0 -1
  5. package/dist/cli/wrapper.d.ts.map +1 -1
  6. package/dist/cli/wrapper.js +19 -54
  7. package/dist/cli/wrapper.js.map +1 -1
  8. package/dist/commands/helpers.js +1 -1
  9. package/dist/commands/runner.d.ts.map +1 -1
  10. package/dist/commands/runner.js +22 -18
  11. package/dist/commands/runner.js.map +1 -1
  12. package/dist/config/constants.d.ts.map +1 -1
  13. package/dist/config/constants.js +37 -52
  14. package/dist/config/constants.js.map +1 -1
  15. package/dist/utils/arg-parser.d.ts.map +1 -1
  16. package/dist/utils/arg-parser.js +23 -8
  17. package/dist/utils/arg-parser.js.map +1 -1
  18. package/dist/utils/bitbucket-client.d.ts +24 -37
  19. package/dist/utils/bitbucket-client.d.ts.map +1 -1
  20. package/dist/utils/bitbucket-client.js +38 -52
  21. package/dist/utils/bitbucket-client.js.map +1 -1
  22. package/dist/utils/bitbucket-utils.d.ts +48 -68
  23. package/dist/utils/bitbucket-utils.d.ts.map +1 -1
  24. package/dist/utils/bitbucket-utils.js +100 -125
  25. package/dist/utils/bitbucket-utils.js.map +1 -1
  26. package/dist/utils/config-loader.d.ts +10 -29
  27. package/dist/utils/config-loader.d.ts.map +1 -1
  28. package/dist/utils/config-loader.js +277 -51
  29. package/dist/utils/config-loader.js.map +1 -1
  30. package/dist/utils/index.d.ts +1 -1
  31. package/dist/utils/index.d.ts.map +1 -1
  32. package/dist/utils/index.js +1 -1
  33. package/dist/utils/index.js.map +1 -1
  34. package/package.json +1 -3
  35. package/tests/integration/cli-integration.test.ts +96 -217
  36. package/tests/unit/cli/wrapper.test.ts +28 -137
  37. package/tests/unit/commands/runner.test.ts +69 -197
  38. package/tests/unit/utils/arg-parser.test.ts +53 -4
  39. package/tests/unit/utils/config-loader.test.ts +441 -106
@@ -1,4 +1,4 @@
1
- import { beforeEach, describe, expect, it, vi } from 'vitest';
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
2
 
3
3
  import { runCommand } from '../../../src/commands/runner.js';
4
4
 
@@ -19,6 +19,7 @@ vi.mock('../../../src/utils/index.js', () => ({
19
19
  testConnection: vi.fn(),
20
20
  loadConfig: vi.fn(),
21
21
  clearClients: vi.fn(),
22
+ setupConfig: vi.fn(),
22
23
  }));
23
24
 
24
25
  // Mock process.env
@@ -34,14 +35,17 @@ describe('commands/runner', () => {
34
35
  process.env = originalEnv;
35
36
  });
36
37
 
38
+ const mockConfig = {
39
+ email: 'user@example.com',
40
+ apiToken: 'test_token',
41
+ defaultWorkspace: 'myworkspace',
42
+ defaultFormat: 'json' as const,
43
+ };
44
+
37
45
  describe('runCommand', () => {
38
46
  it('should execute list-repositories command', async () => {
39
47
  const { listRepositories, loadConfig, clearClients } = await import('../../../src/utils/index.js');
40
- loadConfig.mockReturnValue({
41
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
42
- defaultProfile: 'cloud',
43
- defaultFormat: 'json',
44
- });
48
+ loadConfig.mockReturnValue(mockConfig);
45
49
  listRepositories.mockResolvedValue({ success: true, result: '{"repositories": []}' });
46
50
 
47
51
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -51,7 +55,7 @@ describe('commands/runner', () => {
51
55
  await runCommand('list-repositories', '{"workspace":"myworkspace"}', null);
52
56
 
53
57
  expect(loadConfig).toHaveBeenCalled();
54
- expect(listRepositories).toHaveBeenCalledWith('cloud', 'myworkspace', 'json');
58
+ expect(listRepositories).toHaveBeenCalledWith('myworkspace', 'json');
55
59
  expect(consoleLogSpy).toHaveBeenCalledWith('{"repositories": []}');
56
60
  expect(clearClients).toHaveBeenCalled();
57
61
  expect(exitSpy).toHaveBeenCalledWith(0);
@@ -61,24 +65,17 @@ describe('commands/runner', () => {
61
65
  consoleErrorSpy.mockRestore();
62
66
  });
63
67
 
64
- it('should execute list-repositories with custom profile and format', async () => {
68
+ it('should execute list-repositories with custom format', async () => {
65
69
  const { listRepositories, loadConfig } = await import('../../../src/utils/index.js');
66
- loadConfig.mockReturnValue({
67
- profiles: {
68
- cloud: { username: 'test@test.com', password: 'password123' },
69
- staging: { username: 'staging@test.com', password: 'staging-password' },
70
- },
71
- defaultProfile: 'cloud',
72
- defaultFormat: 'json',
73
- });
70
+ loadConfig.mockReturnValue(mockConfig);
74
71
  listRepositories.mockResolvedValue({ success: true, result: '{"repositories": []}' });
75
72
 
76
73
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
77
74
  const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
78
75
 
79
- await runCommand('list-repositories', '{"workspace":"myworkspace","profile":"staging","format":"toon"}', null);
76
+ await runCommand('list-repositories', '{"workspace":"myworkspace","format":"toon"}', null);
80
77
 
81
- expect(listRepositories).toHaveBeenCalledWith('staging', 'myworkspace', 'toon');
78
+ expect(listRepositories).toHaveBeenCalledWith('myworkspace', 'toon');
82
79
  expect(consoleLogSpy).toHaveBeenCalledWith('{"repositories": []}');
83
80
  expect(exitSpy).toHaveBeenCalledWith(0);
84
81
 
@@ -88,11 +85,7 @@ describe('commands/runner', () => {
88
85
 
89
86
  it('should execute get-repository command with workspace and repoSlug', async () => {
90
87
  const { getRepository, loadConfig } = await import('../../../src/utils/index.js');
91
- loadConfig.mockReturnValue({
92
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
93
- defaultProfile: 'cloud',
94
- defaultFormat: 'json',
95
- });
88
+ loadConfig.mockReturnValue(mockConfig);
96
89
  getRepository.mockResolvedValue({ success: true, result: '{"name":"my-repo"}' });
97
90
 
98
91
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -101,7 +94,7 @@ describe('commands/runner', () => {
101
94
 
102
95
  await runCommand('get-repository', '{"workspace":"myworkspace","repoSlug":"my-repo"}', null);
103
96
 
104
- expect(getRepository).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', 'json');
97
+ expect(getRepository).toHaveBeenCalledWith('myworkspace', 'my-repo', 'json');
105
98
  expect(consoleLogSpy).toHaveBeenCalledWith('{"name":"my-repo"}');
106
99
  expect(consoleErrorSpy).not.toHaveBeenCalled();
107
100
  expect(exitSpy).toHaveBeenCalledWith(0);
@@ -113,11 +106,7 @@ describe('commands/runner', () => {
113
106
 
114
107
  it('should exit with error if get-repository missing parameters', async () => {
115
108
  const { loadConfig } = await import('../../../src/utils/index.js');
116
- loadConfig.mockReturnValue({
117
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
118
- defaultProfile: 'cloud',
119
- defaultFormat: 'json',
120
- });
109
+ loadConfig.mockReturnValue(mockConfig);
121
110
 
122
111
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
123
112
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -133,11 +122,7 @@ describe('commands/runner', () => {
133
122
 
134
123
  it('should execute list-pullrequests command with all parameters', async () => {
135
124
  const { listPullRequests, loadConfig } = await import('../../../src/utils/index.js');
136
- loadConfig.mockReturnValue({
137
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
138
- defaultProfile: 'cloud',
139
- defaultFormat: 'json',
140
- });
125
+ loadConfig.mockReturnValue(mockConfig);
141
126
  listPullRequests.mockResolvedValue({ success: true, result: '{"pullrequests": []}' });
142
127
 
143
128
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -145,7 +130,7 @@ describe('commands/runner', () => {
145
130
 
146
131
  await runCommand('list-pullrequests', '{"workspace":"myworkspace","repoSlug":"my-repo","state":"OPEN"}', null);
147
132
 
148
- expect(listPullRequests).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', 'OPEN', 'json');
133
+ expect(listPullRequests).toHaveBeenCalledWith('myworkspace', 'my-repo', 'OPEN', 'json');
149
134
  expect(consoleLogSpy).toHaveBeenCalledWith('{"pullrequests": []}');
150
135
  expect(exitSpy).toHaveBeenCalledWith(0);
151
136
 
@@ -155,11 +140,7 @@ describe('commands/runner', () => {
155
140
 
156
141
  it('should execute list-pullrequests with minimal parameters', async () => {
157
142
  const { listPullRequests, loadConfig } = await import('../../../src/utils/index.js');
158
- loadConfig.mockReturnValue({
159
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
160
- defaultProfile: 'cloud',
161
- defaultFormat: 'json',
162
- });
143
+ loadConfig.mockReturnValue(mockConfig);
163
144
  listPullRequests.mockResolvedValue({ success: true, result: '{"pullrequests": []}' });
164
145
 
165
146
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -167,7 +148,7 @@ describe('commands/runner', () => {
167
148
 
168
149
  await runCommand('list-pullrequests', '{"workspace":"myworkspace","repoSlug":"my-repo"}', null);
169
150
 
170
- expect(listPullRequests).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', undefined, 'json');
151
+ expect(listPullRequests).toHaveBeenCalledWith('myworkspace', 'my-repo', undefined, 'json');
171
152
  expect(consoleLogSpy).toHaveBeenCalledWith('{"pullrequests": []}');
172
153
  expect(exitSpy).toHaveBeenCalledWith(0);
173
154
 
@@ -177,11 +158,7 @@ describe('commands/runner', () => {
177
158
 
178
159
  it('should execute get-pullrequest command', async () => {
179
160
  const { getPullRequest, loadConfig } = await import('../../../src/utils/index.js');
180
- loadConfig.mockReturnValue({
181
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
182
- defaultProfile: 'cloud',
183
- defaultFormat: 'json',
184
- });
161
+ loadConfig.mockReturnValue(mockConfig);
185
162
  getPullRequest.mockResolvedValue({ success: true, result: '{"id":"123","title":"Test PR"}' });
186
163
 
187
164
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -193,7 +170,7 @@ describe('commands/runner', () => {
193
170
  null
194
171
  );
195
172
 
196
- expect(getPullRequest).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', '123', 'json');
173
+ expect(getPullRequest).toHaveBeenCalledWith('myworkspace', 'my-repo', '123', 'json');
197
174
  expect(consoleLogSpy).toHaveBeenCalledWith('{"id":"123","title":"Test PR"}');
198
175
  expect(exitSpy).toHaveBeenCalledWith(0);
199
176
 
@@ -203,11 +180,7 @@ describe('commands/runner', () => {
203
180
 
204
181
  it('should exit with error if get-pullrequest missing parameters', async () => {
205
182
  const { loadConfig } = await import('../../../src/utils/index.js');
206
- loadConfig.mockReturnValue({
207
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
208
- defaultProfile: 'cloud',
209
- defaultFormat: 'json',
210
- });
183
+ loadConfig.mockReturnValue(mockConfig);
211
184
 
212
185
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
213
186
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -223,11 +196,7 @@ describe('commands/runner', () => {
223
196
 
224
197
  it('should execute create-pullrequest command', async () => {
225
198
  const { createPullRequest, loadConfig } = await import('../../../src/utils/index.js');
226
- loadConfig.mockReturnValue({
227
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
228
- defaultProfile: 'cloud',
229
- defaultFormat: 'json',
230
- });
199
+ loadConfig.mockReturnValue(mockConfig);
231
200
  createPullRequest.mockResolvedValue({ success: true, result: '{"id":"456","title":"New PR"}' });
232
201
 
233
202
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -240,7 +209,6 @@ describe('commands/runner', () => {
240
209
  );
241
210
 
242
211
  expect(createPullRequest).toHaveBeenCalledWith(
243
- 'cloud',
244
212
  'myworkspace',
245
213
  'my-repo',
246
214
  'New PR',
@@ -258,11 +226,7 @@ describe('commands/runner', () => {
258
226
 
259
227
  it('should execute create-pullrequest with description', async () => {
260
228
  const { createPullRequest, loadConfig } = await import('../../../src/utils/index.js');
261
- loadConfig.mockReturnValue({
262
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
263
- defaultProfile: 'cloud',
264
- defaultFormat: 'json',
265
- });
229
+ loadConfig.mockReturnValue(mockConfig);
266
230
  createPullRequest.mockResolvedValue({ success: true, result: '{"id":"456","title":"New PR"}' });
267
231
 
268
232
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -275,7 +239,6 @@ describe('commands/runner', () => {
275
239
  );
276
240
 
277
241
  expect(createPullRequest).toHaveBeenCalledWith(
278
- 'cloud',
279
242
  'myworkspace',
280
243
  'my-repo',
281
244
  'New PR',
@@ -292,11 +255,7 @@ describe('commands/runner', () => {
292
255
 
293
256
  it('should exit with error if create-pullrequest missing required parameters', async () => {
294
257
  const { loadConfig } = await import('../../../src/utils/index.js');
295
- loadConfig.mockReturnValue({
296
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
297
- defaultProfile: 'cloud',
298
- defaultFormat: 'json',
299
- });
258
+ loadConfig.mockReturnValue(mockConfig);
300
259
 
301
260
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
302
261
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -314,11 +273,7 @@ describe('commands/runner', () => {
314
273
 
315
274
  it('should execute list-branches command', async () => {
316
275
  const { listBranches, loadConfig } = await import('../../../src/utils/index.js');
317
- loadConfig.mockReturnValue({
318
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
319
- defaultProfile: 'cloud',
320
- defaultFormat: 'json',
321
- });
276
+ loadConfig.mockReturnValue(mockConfig);
322
277
  listBranches.mockResolvedValue({ success: true, result: '{"branches": []}' });
323
278
 
324
279
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -326,7 +281,7 @@ describe('commands/runner', () => {
326
281
 
327
282
  await runCommand('list-branches', '{"workspace":"myworkspace","repoSlug":"my-repo"}', null);
328
283
 
329
- expect(listBranches).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', undefined, undefined, 'json');
284
+ expect(listBranches).toHaveBeenCalledWith('myworkspace', 'my-repo', undefined, undefined, 'json');
330
285
  expect(consoleLogSpy).toHaveBeenCalledWith('{"branches": []}');
331
286
  expect(exitSpy).toHaveBeenCalledWith(0);
332
287
 
@@ -336,11 +291,7 @@ describe('commands/runner', () => {
336
291
 
337
292
  it('should execute list-commits command', async () => {
338
293
  const { listCommits, loadConfig } = await import('../../../src/utils/index.js');
339
- loadConfig.mockReturnValue({
340
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
341
- defaultProfile: 'cloud',
342
- defaultFormat: 'json',
343
- });
294
+ loadConfig.mockReturnValue(mockConfig);
344
295
  listCommits.mockResolvedValue({ success: true, result: '{"commits": []}' });
345
296
 
346
297
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -348,7 +299,7 @@ describe('commands/runner', () => {
348
299
 
349
300
  await runCommand('list-commits', '{"workspace":"myworkspace","repoSlug":"my-repo"}', null);
350
301
 
351
- expect(listCommits).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', undefined, 'json');
302
+ expect(listCommits).toHaveBeenCalledWith('myworkspace', 'my-repo', undefined, 'json');
352
303
  expect(consoleLogSpy).toHaveBeenCalledWith('{"commits": []}');
353
304
  expect(exitSpy).toHaveBeenCalledWith(0);
354
305
 
@@ -358,11 +309,7 @@ describe('commands/runner', () => {
358
309
 
359
310
  it('should execute list-issues command', async () => {
360
311
  const { listIssues, loadConfig } = await import('../../../src/utils/index.js');
361
- loadConfig.mockReturnValue({
362
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
363
- defaultProfile: 'cloud',
364
- defaultFormat: 'json',
365
- });
312
+ loadConfig.mockReturnValue(mockConfig);
366
313
  listIssues.mockResolvedValue({ success: true, result: '{"issues": []}' });
367
314
 
368
315
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -370,7 +317,7 @@ describe('commands/runner', () => {
370
317
 
371
318
  await runCommand('list-issues', '{"workspace":"myworkspace","repoSlug":"my-repo"}', null);
372
319
 
373
- expect(listIssues).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', 'json');
320
+ expect(listIssues).toHaveBeenCalledWith('myworkspace', 'my-repo', 'json');
374
321
  expect(consoleLogSpy).toHaveBeenCalledWith('{"issues": []}');
375
322
  expect(exitSpy).toHaveBeenCalledWith(0);
376
323
 
@@ -380,11 +327,7 @@ describe('commands/runner', () => {
380
327
 
381
328
  it('should execute get-issue command', async () => {
382
329
  const { getIssue, loadConfig } = await import('../../../src/utils/index.js');
383
- loadConfig.mockReturnValue({
384
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
385
- defaultProfile: 'cloud',
386
- defaultFormat: 'json',
387
- });
330
+ loadConfig.mockReturnValue(mockConfig);
388
331
  getIssue.mockResolvedValue({ success: true, result: '{"id":"123","title":"Test Issue"}' });
389
332
 
390
333
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -392,7 +335,7 @@ describe('commands/runner', () => {
392
335
 
393
336
  await runCommand('get-issue', '{"workspace":"myworkspace","repoSlug":"my-repo","issueId":"123"}', null);
394
337
 
395
- expect(getIssue).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', '123', 'json');
338
+ expect(getIssue).toHaveBeenCalledWith('myworkspace', 'my-repo', '123', 'json');
396
339
  expect(consoleLogSpy).toHaveBeenCalledWith('{"id":"123","title":"Test Issue"}');
397
340
  expect(exitSpy).toHaveBeenCalledWith(0);
398
341
 
@@ -402,11 +345,7 @@ describe('commands/runner', () => {
402
345
 
403
346
  it('should exit with error if get-issue missing parameters', async () => {
404
347
  const { loadConfig } = await import('../../../src/utils/index.js');
405
- loadConfig.mockReturnValue({
406
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
407
- defaultProfile: 'cloud',
408
- defaultFormat: 'json',
409
- });
348
+ loadConfig.mockReturnValue(mockConfig);
410
349
 
411
350
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
412
351
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -422,11 +361,7 @@ describe('commands/runner', () => {
422
361
 
423
362
  it('should execute create-issue command', async () => {
424
363
  const { createIssue, loadConfig } = await import('../../../src/utils/index.js');
425
- loadConfig.mockReturnValue({
426
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
427
- defaultProfile: 'cloud',
428
- defaultFormat: 'json',
429
- });
364
+ loadConfig.mockReturnValue(mockConfig);
430
365
  createIssue.mockResolvedValue({ success: true, result: '{"id":"456","title":"New Issue"}' });
431
366
 
432
367
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -435,7 +370,6 @@ describe('commands/runner', () => {
435
370
  await runCommand('create-issue', '{"workspace":"myworkspace","repoSlug":"my-repo","title":"New Issue"}', null);
436
371
 
437
372
  expect(createIssue).toHaveBeenCalledWith(
438
- 'cloud',
439
373
  'myworkspace',
440
374
  'my-repo',
441
375
  'New Issue',
@@ -453,11 +387,7 @@ describe('commands/runner', () => {
453
387
 
454
388
  it('should execute create-issue with optional parameters', async () => {
455
389
  const { createIssue, loadConfig } = await import('../../../src/utils/index.js');
456
- loadConfig.mockReturnValue({
457
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
458
- defaultProfile: 'cloud',
459
- defaultFormat: 'json',
460
- });
390
+ loadConfig.mockReturnValue(mockConfig);
461
391
  createIssue.mockResolvedValue({ success: true, result: '{"id":"789"}' });
462
392
 
463
393
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -469,7 +399,6 @@ describe('commands/runner', () => {
469
399
  );
470
400
 
471
401
  expect(createIssue).toHaveBeenCalledWith(
472
- 'cloud',
473
402
  'myworkspace',
474
403
  'my-repo',
475
404
  'Bug report',
@@ -485,11 +414,7 @@ describe('commands/runner', () => {
485
414
 
486
415
  it('should exit with error if create-issue missing required parameters', async () => {
487
416
  const { loadConfig } = await import('../../../src/utils/index.js');
488
- loadConfig.mockReturnValue({
489
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
490
- defaultProfile: 'cloud',
491
- defaultFormat: 'json',
492
- });
417
+ loadConfig.mockReturnValue(mockConfig);
493
418
 
494
419
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
495
420
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -505,11 +430,7 @@ describe('commands/runner', () => {
505
430
 
506
431
  it('should execute list-pipelines command', async () => {
507
432
  const { listPipelines, loadConfig } = await import('../../../src/utils/index.js');
508
- loadConfig.mockReturnValue({
509
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
510
- defaultProfile: 'cloud',
511
- defaultFormat: 'json',
512
- });
433
+ loadConfig.mockReturnValue(mockConfig);
513
434
  listPipelines.mockResolvedValue({ success: true, result: '{"pipelines": []}' });
514
435
 
515
436
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -517,7 +438,7 @@ describe('commands/runner', () => {
517
438
 
518
439
  await runCommand('list-pipelines', '{"workspace":"myworkspace","repoSlug":"my-repo"}', null);
519
440
 
520
- expect(listPipelines).toHaveBeenCalledWith('cloud', 'myworkspace', 'my-repo', 'json');
441
+ expect(listPipelines).toHaveBeenCalledWith('myworkspace', 'my-repo', 'json');
521
442
  expect(consoleLogSpy).toHaveBeenCalledWith('{"pipelines": []}');
522
443
  expect(exitSpy).toHaveBeenCalledWith(0);
523
444
 
@@ -527,11 +448,7 @@ describe('commands/runner', () => {
527
448
 
528
449
  it('should execute get-user with userId', async () => {
529
450
  const { getUser, loadConfig } = await import('../../../src/utils/index.js');
530
- loadConfig.mockReturnValue({
531
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
532
- defaultProfile: 'cloud',
533
- defaultFormat: 'json',
534
- });
451
+ loadConfig.mockReturnValue(mockConfig);
535
452
  getUser.mockResolvedValue({ success: true, result: '{"displayName":"User"}' });
536
453
 
537
454
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -539,7 +456,7 @@ describe('commands/runner', () => {
539
456
 
540
457
  await runCommand('get-user', '{"userId":"5b10a2844c20165700ede21g"}', null);
541
458
 
542
- expect(getUser).toHaveBeenCalledWith('cloud', '5b10a2844c20165700ede21g', 'json');
459
+ expect(getUser).toHaveBeenCalledWith('5b10a2844c20165700ede21g', 'json');
543
460
  expect(consoleLogSpy).toHaveBeenCalledWith('{"displayName":"User"}');
544
461
  expect(exitSpy).toHaveBeenCalledWith(0);
545
462
 
@@ -549,11 +466,7 @@ describe('commands/runner', () => {
549
466
 
550
467
  it('should execute get-user without parameters (current user)', async () => {
551
468
  const { getUser, loadConfig } = await import('../../../src/utils/index.js');
552
- loadConfig.mockReturnValue({
553
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
554
- defaultProfile: 'cloud',
555
- defaultFormat: 'json',
556
- });
469
+ loadConfig.mockReturnValue(mockConfig);
557
470
  getUser.mockResolvedValue({ success: true, result: '{"displayName":"Current User"}' });
558
471
 
559
472
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -561,7 +474,7 @@ describe('commands/runner', () => {
561
474
 
562
475
  await runCommand('get-user', null, null);
563
476
 
564
- expect(getUser).toHaveBeenCalledWith('cloud', undefined, 'json');
477
+ expect(getUser).toHaveBeenCalledWith(undefined, 'json');
565
478
  expect(consoleLogSpy).toHaveBeenCalledWith('{"displayName":"Current User"}');
566
479
  expect(exitSpy).toHaveBeenCalledWith(0);
567
480
 
@@ -571,11 +484,7 @@ describe('commands/runner', () => {
571
484
 
572
485
  it('should execute test-connection command', async () => {
573
486
  const { testConnection, loadConfig } = await import('../../../src/utils/index.js');
574
- loadConfig.mockReturnValue({
575
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
576
- defaultProfile: 'cloud',
577
- defaultFormat: 'json',
578
- });
487
+ loadConfig.mockReturnValue(mockConfig);
579
488
  testConnection.mockResolvedValue({ success: true, result: 'Connected successfully' });
580
489
 
581
490
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -583,7 +492,7 @@ describe('commands/runner', () => {
583
492
 
584
493
  await runCommand('test-connection', null, null);
585
494
 
586
- expect(testConnection).toHaveBeenCalledWith('cloud');
495
+ expect(testConnection).toHaveBeenCalledWith();
587
496
  expect(consoleLogSpy).toHaveBeenCalledWith('Connected successfully');
588
497
  expect(exitSpy).toHaveBeenCalledWith(0);
589
498
 
@@ -593,11 +502,7 @@ describe('commands/runner', () => {
593
502
 
594
503
  it('should handle command failure', async () => {
595
504
  const { getRepository, loadConfig } = await import('../../../src/utils/index.js');
596
- loadConfig.mockReturnValue({
597
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
598
- defaultProfile: 'cloud',
599
- defaultFormat: 'json',
600
- });
505
+ loadConfig.mockReturnValue(mockConfig);
601
506
  getRepository.mockResolvedValue({ success: false, error: 'Repository not found' });
602
507
 
603
508
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -614,11 +519,7 @@ describe('commands/runner', () => {
614
519
 
615
520
  it('should handle unknown command', async () => {
616
521
  const { loadConfig } = await import('../../../src/utils/index.js');
617
- loadConfig.mockReturnValue({
618
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
619
- defaultProfile: 'cloud',
620
- defaultFormat: 'json',
621
- });
522
+ loadConfig.mockReturnValue(mockConfig);
622
523
 
623
524
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
624
525
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -634,11 +535,7 @@ describe('commands/runner', () => {
634
535
 
635
536
  it('should handle JSON parse error in arguments', async () => {
636
537
  const { loadConfig, clearClients } = await import('../../../src/utils/index.js');
637
- loadConfig.mockReturnValue({
638
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
639
- defaultProfile: 'cloud',
640
- defaultFormat: 'json',
641
- });
538
+ loadConfig.mockReturnValue(mockConfig);
642
539
 
643
540
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
644
541
  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
@@ -656,51 +553,9 @@ describe('commands/runner', () => {
656
553
  consoleErrorSpy.mockRestore();
657
554
  });
658
555
 
659
- it('should use CLAUDE_PROJECT_ROOT from environment if set', async () => {
660
- process.env.CLAUDE_PROJECT_ROOT = '/custom/project/root';
661
- const { loadConfig, listRepositories } = await import('../../../src/utils/index.js');
662
- loadConfig.mockReturnValue({
663
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
664
- defaultProfile: 'cloud',
665
- defaultFormat: 'json',
666
- });
667
- listRepositories.mockResolvedValue({ success: true, result: '{"repositories": []}' });
668
-
669
- const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
670
-
671
- await runCommand('list-repositories', '{"workspace":"myworkspace"}', null);
672
-
673
- expect(loadConfig).toHaveBeenCalledWith('/custom/project/root');
674
-
675
- exitSpy.mockRestore();
676
- });
677
-
678
- it('should use current directory if CLAUDE_PROJECT_ROOT not set', async () => {
679
- delete process.env.CLAUDE_PROJECT_ROOT;
680
- const { loadConfig, listRepositories } = await import('../../../src/utils/index.js');
681
- loadConfig.mockReturnValue({
682
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
683
- defaultProfile: 'cloud',
684
- defaultFormat: 'json',
685
- });
686
- listRepositories.mockResolvedValue({ success: true, result: '{"repositories": []}' });
687
-
688
- const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
689
-
690
- await runCommand('list-repositories', '{"workspace":"myworkspace"}', null);
691
-
692
- expect(loadConfig).toHaveBeenCalledWith(process.cwd());
693
-
694
- exitSpy.mockRestore();
695
- });
696
-
697
556
  it('should clear clients on successful execution', async () => {
698
557
  const { listRepositories, loadConfig, clearClients } = await import('../../../src/utils/index.js');
699
- loadConfig.mockReturnValue({
700
- profiles: { cloud: { username: 'test@test.com', password: 'password123' } },
701
- defaultProfile: 'cloud',
702
- defaultFormat: 'json',
703
- });
558
+ loadConfig.mockReturnValue(mockConfig);
704
559
  listRepositories.mockResolvedValue({ success: true, result: '{}' });
705
560
 
706
561
  const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
@@ -748,5 +603,22 @@ describe('commands/runner', () => {
748
603
  exitSpy.mockRestore();
749
604
  consoleErrorSpy.mockRestore();
750
605
  });
606
+
607
+ it('should handle config command and call setupConfig', async () => {
608
+ const { setupConfig, clearClients } = await import('../../../src/utils/index.js');
609
+ setupConfig.mockResolvedValue(undefined);
610
+
611
+ const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {});
612
+ const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
613
+
614
+ await runCommand('config', null, null);
615
+
616
+ expect(setupConfig).toHaveBeenCalled();
617
+ expect(clearClients).toHaveBeenCalled();
618
+ expect(exitSpy).toHaveBeenCalledWith(0);
619
+
620
+ exitSpy.mockRestore();
621
+ consoleLogSpy.mockRestore();
622
+ });
751
623
  });
752
624
  });