|
9 | 9 | import { mkdtempSync } from 'node:fs'; |
10 | 10 | import { tmpdir } from 'node:os'; |
11 | 11 | import { join } from 'node:path'; |
| 12 | +import { Command } from 'commander'; |
12 | 13 | import { beforeEach, describe, expect, it, vi } from 'vitest'; |
13 | | -import { CLIError } from '../lib/errors.js'; |
| 14 | +import { ApiError, CLIError } from '../lib/errors.js'; |
14 | 15 | import { writeProfile } from '../lib/credentials.js'; |
15 | 16 | import type { DoctorDeps, DoctorReport } from './doctor.js'; |
16 | 17 | import { createDoctorCommand, runDoctor } from './doctor.js'; |
@@ -56,6 +57,14 @@ function healthyDeps(credentialsPath: string, extra: Partial<DoctorDeps> = {}): |
56 | 57 | }; |
57 | 58 | } |
58 | 59 |
|
| 60 | +function makeDoctorProgram(deps: DoctorDeps = {}): Command { |
| 61 | + const program = new Command(); |
| 62 | + program.exitOverride(); |
| 63 | + program.option('--output <mode>', 'output', 'text'); |
| 64 | + program.addCommand(createDoctorCommand(deps)); |
| 65 | + return program; |
| 66 | +} |
| 67 | + |
59 | 68 | let credentialsPath: string; |
60 | 69 |
|
61 | 70 | beforeEach(() => { |
@@ -226,4 +235,36 @@ describe('createDoctorCommand wiring', () => { |
226 | 235 | it('--help describes the diagnostic', () => { |
227 | 236 | expect(createDoctorCommand().helpInformation()).toContain('Diagnose'); |
228 | 237 | }); |
| 238 | + |
| 239 | + it('rejects invalid --output with the shared VALIDATION_ERROR', async () => { |
| 240 | + const rejection = await makeDoctorProgram() |
| 241 | + .parseAsync(['node', 'ts', '--output', 'yaml', 'doctor']) |
| 242 | + .catch((error: unknown) => error); |
| 243 | + expect(rejection).toBeInstanceOf(ApiError); |
| 244 | + expect(rejection).toMatchObject({ |
| 245 | + code: 'VALIDATION_ERROR', |
| 246 | + exitCode: 5, |
| 247 | + nextAction: 'Flag `--output` is invalid: must be one of: json, text.', |
| 248 | + }); |
| 249 | + }); |
| 250 | + |
| 251 | + it('accepts valid --output modes through command wiring', async () => { |
| 252 | + writeProfile('default', { apiKey: 'sk-abc' }, { path: credentialsPath }); |
| 253 | + for (const mode of ['text', 'json'] as const) { |
| 254 | + const { capture, deps } = makeCapture(); |
| 255 | + await makeDoctorProgram({ ...healthyDeps(credentialsPath), ...deps }).parseAsync([ |
| 256 | + 'node', |
| 257 | + 'ts', |
| 258 | + '--output', |
| 259 | + mode, |
| 260 | + 'doctor', |
| 261 | + ]); |
| 262 | + const raw = capture.stdout.join(''); |
| 263 | + if (mode === 'json') { |
| 264 | + expect((JSON.parse(raw) as DoctorReport).failures).toBe(0); |
| 265 | + } else { |
| 266 | + expect(raw).toContain('All checks passed.'); |
| 267 | + } |
| 268 | + } |
| 269 | + }); |
229 | 270 | }); |
0 commit comments