import { describe, test, expect } from 'bun:test'; import { readFileSync } from 'fs'; // Read cli.ts source for structural checks const cliSource = readFileSync(new URL('../src/cli.ts', import.meta.url), 'utf-8'); describe('CLI structure', () => { test('imports operations from operations.ts', () => { expect(cliSource).toContain("from './core/operations.ts'"); }); test('builds cliOps map from operations', () => { expect(cliSource).toContain('cliOps'); }); test('CLI_ONLY set contains expected commands', () => { expect(cliSource).toContain("'init'"); expect(cliSource).toContain("'upgrade'"); expect(cliSource).toContain("'import'"); expect(cliSource).toContain("'export'"); expect(cliSource).toContain("'embed'"); expect(cliSource).toContain("'files'"); }); test('has formatResult function for CLI output', () => { expect(cliSource).toContain('function formatResult'); }); }); describe('CLI version', () => { test('VERSION matches package.json', async () => { const { VERSION } = await import('../src/version.ts'); const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8')); expect(VERSION).toBe(pkg.version); }); test('VERSION is a valid semver string', async () => { const { VERSION } = await import('../src/version.ts'); expect(VERSION).toMatch(/^\d+\.\d+\.\d+/); }); }); describe('CLI dispatch integration', () => { test('--version outputs version', async () => { const proc = Bun.spawn(['bun', 'run', 'src/cli.ts', '--version'], { cwd: new URL('..', import.meta.url).pathname, stdout: 'pipe', stderr: 'pipe', }); const stdout = await new Response(proc.stdout).text(); await proc.exited; expect(stdout.trim()).toMatch(/^gbrain \d+\.\d+\.\d+/); }); test('unknown command prints error and exits 1', async () => { const proc = Bun.spawn(['bun', 'run', 'src/cli.ts', 'notacommand'], { cwd: new URL('..', import.meta.url).pathname, stdout: 'pipe', stderr: 'pipe', }); const stderr = await new Response(proc.stderr).text(); const exitCode = await proc.exited; expect(stderr).toContain('Unknown command: notacommand'); expect(exitCode).toBe(1); }); test('per-command --help prints usage without DB connection', async () => { const proc = Bun.spawn(['bun', 'run', 'src/cli.ts', 'get', '--help'], { cwd: new URL('..', import.meta.url).pathname, stdout: 'pipe', stderr: 'pipe', }); const stdout = await new Response(proc.stdout).text(); const exitCode = await proc.exited; expect(stdout).toContain('Usage: gbrain get'); expect(exitCode).toBe(0); }); test('upgrade --help prints usage without running upgrade', async () => { const proc = Bun.spawn(['bun', 'run', 'src/cli.ts', 'upgrade', '--help'], { cwd: new URL('..', import.meta.url).pathname, stdout: 'pipe', stderr: 'pipe', }); const stdout = await new Response(proc.stdout).text(); const exitCode = await proc.exited; expect(stdout).toContain('Usage: gbrain upgrade'); expect(exitCode).toBe(0); }); test('--help prints global help', async () => { const proc = Bun.spawn(['bun', 'run', 'src/cli.ts', '--help'], { cwd: new URL('..', import.meta.url).pathname, stdout: 'pipe', stderr: 'pipe', }); const stdout = await new Response(proc.stdout).text(); const exitCode = await proc.exited; expect(stdout).toContain('USAGE'); expect(stdout).toContain('gbrain '); expect(exitCode).toBe(0); }); test('--tools-json outputs valid JSON with operations', async () => { const proc = Bun.spawn(['bun', 'run', 'src/cli.ts', '--tools-json'], { cwd: new URL('..', import.meta.url).pathname, stdout: 'pipe', stderr: 'pipe', }); const stdout = await new Response(proc.stdout).text(); await proc.exited; const tools = JSON.parse(stdout); expect(Array.isArray(tools)).toBe(true); expect(tools.length).toBeGreaterThanOrEqual(30); expect(tools[0]).toHaveProperty('name'); expect(tools[0]).toHaveProperty('description'); expect(tools[0]).toHaveProperty('parameters'); }); });