tests/cli.test.js (1855 bytes)
1 import assert from 'node:assert/strict'; 2 import { spawnSync } from 'node:child_process'; 3 import fs from 'node:fs'; 4 import os from 'node:os'; 5 import path from 'node:path'; 6 import { beforeEach, test } from 'node:test'; 7 import { fileURLToPath } from 'node:url'; 8 9 const BIN = fileURLToPath(new URL('../bin/ideamine.js', import.meta.url)); 10 11 beforeEach(() => { 12 process.env.IDEAMINE_HOME = fs.mkdtempSync(path.join(os.tmpdir(), 'ideamine-cli-')); 13 process.env.IDEAMINE_CLAUDE_BIN = fileURLToPath(new URL('./fixtures/fake-claude.js', import.meta.url)); 14 process.env.CLAUDE_CONFIG_DIR = process.env.IDEAMINE_HOME; 15 }); 16 17 test('ideamine watch turns the watcher on and off, and watch-pass runs one pass', () => { 18 assert.match(cli('watch').out, /^ideamine watch: on since /); 19 assert.equal(cli('add', 'one').code, 0); 20 assert.equal(cli('watch-pass').code, 0); 21 assert.match(cli('cat', '1').out, /triaged .* by haiku \(headless\)/); 22 assert.match(cli('watch', 'off').out, /^ideamine watch: off/); 23 }); 24 25 function cli(...args) { 26 const r = spawnSync(process.execPath, [BIN, ...args], { encoding: 'utf8', env: process.env }); 27 return { out: r.stdout, err: r.stderr, code: r.status }; 28 } 29 30 test('the CLI uses the same unix verbs as /ideas: ls, cat, rm, sort', () => { 31 for (const idea of ['alpha', 'beta', 'gamma']) assert.equal(cli('add', idea).code, 0); 32 assert.match(cli('cat', '1', '#3').out, /^#1 alpha\n[\s\S]*\n\n#3 gamma\n/); 33 assert.equal(cli('rm', '2').out, 'Removed #2 beta\n'); 34 35 const missing = cli('rm', '1', '9'); 36 assert.equal(missing.code, 1); 37 assert.match(missing.err, /no idea #9/); // and #1 is still there 38 39 const all = cli('ls', '-a').out; 40 assert.match(all, /\[showing: all\][\s\S]*#3[\s\S]*#1/); 41 assert.doesNotMatch(all, /#2 /); 42 assert.match(cli('sort', '--dry-run').out, / -p --model sonnet [\s\S]*Ideas to triage \(2\)/); 43 });