kthulu/e2e/cli.test.ts
2026-03-06 17:17:19 -08:00

59 lines
1.9 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { resolve } from 'node:path';
const execFileAsync = promisify(execFile);
const PROJECT_ROOT = resolve(import.meta.dirname, '..');
async function runCli(args: string[]): Promise<{ stdout: string; stderr: string; exitCode: number }> {
try {
const { stdout, stderr } = await execFileAsync(
'pnpm',
['--filter', '@kthulu/cli', 'dev', '--', ...args],
{ cwd: PROJECT_ROOT, timeout: 15000 },
);
return { stdout, stderr, exitCode: 0 };
} catch (err) {
const error = err as { stdout?: string; stderr?: string; code?: number };
return {
stdout: error.stdout ?? '',
stderr: error.stderr ?? '',
exitCode: error.code ?? 1,
};
}
}
describe('kthulu CLI', () => {
it('shows help with no arguments', async () => {
const { stdout } = await runCli(['--help']);
expect(stdout).toContain('kthulu');
expect(stdout).toContain('local-first AI coding agent');
});
it('shows version', async () => {
const { stdout } = await runCli(['--version']);
expect(stdout.trim()).toBe('0.0.1');
});
it('session list runs without error', async () => {
const { exitCode } = await runCli(['session', 'list']);
expect(exitCode).toBe(0);
});
it('model status reports connection state', async () => {
const result = await runCli(['model', 'status']);
// Should either succeed (model-boss running) or fail gracefully
expect(result.stdout + result.stderr).toBeTruthy();
});
it('eval shows help with no model-boss', async () => {
const result = await runCli(['eval', '--help']);
expect(result.stdout).toContain('evaluation');
});
it('train export shows help', async () => {
const result = await runCli(['train', '--help']);
expect(result.stdout).toContain('Training');
});
});