/** * lib/spec-arg — shared `--spec` / `--spec-file` resolution (adopted by the * 11 frontend CLIs; six backend CLIs carried the pattern individually). */ import { describe, it, expect } from 'vitest' import { mkdtempSync, writeFileSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { readSpecArg } from '../spec-arg.js' describe('lib/spec-arg — readSpecArg', () => { it('inline --spec passes through verbatim', () => { expect(readSpecArg({ spec: '{"a":1}' })).toEqual({ raw: '{"a":1}' }) }) it('--spec-file reads the file and WINS over --spec', () => { const dir = mkdtempSync(join(tmpdir(), 'specarg-')) try { const f = join(dir, 'spec.json') writeFileSync(f, '{"fromFile":true}') expect(readSpecArg({ spec: '{"inline":true}', 'spec-file': f })).toEqual({ raw: '{"fromFile":true}' }) } finally { rmSync(dir, { recursive: true, force: true }) } }) it('an unreadable --spec-file yields a named error, not a throw', () => { const r = readSpecArg({ 'spec-file': join(tmpdir(), 'specarg-missing', 'nope.json') }) expect('error' in r && r.error).toMatch(/Failed to read --spec-file/) }) it('neither flag yields the either-or error', () => { const r = readSpecArg({}) expect('error' in r && r.error).toBe('Either --spec or --spec-file is required') }) })