71 lines
2.6 KiB
JavaScript
71 lines
2.6 KiB
JavaScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import fs from 'node:fs'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
import { execFileSync } from 'node:child_process'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import { discoverGoalFiles } from '../src/goals.mjs'
|
|
|
|
const SCRIPT = fileURLToPath(new URL('../new-plan.mjs', import.meta.url))
|
|
|
|
function tmpProject() {
|
|
return fs.mkdtempSync(path.join(os.tmpdir(), 'kilo-new-plan-'))
|
|
}
|
|
|
|
function run(args, project) {
|
|
return execFileSync(process.execPath, [SCRIPT, ...args, '--project', project], { encoding: 'utf8' })
|
|
}
|
|
|
|
test('new-plan writes a discoverable plan from the project template', () => {
|
|
const project = tmpProject()
|
|
fs.mkdirSync(path.join(project, '.kilo', 'templates'), { recursive: true })
|
|
fs.writeFileSync(
|
|
path.join(project, '.kilo', 'templates', 'plan.md'),
|
|
'# {{TITLE}}\n\n## Stages (kilo-loop)\n\n- [ ] Ship it :: verify: echo ok :: acceptance: shipped\n',
|
|
)
|
|
|
|
const out = run(['My Feature'], project).trim()
|
|
const abs = path.join(project, out)
|
|
assert.ok(fs.existsSync(abs), `plan file exists: ${out}`)
|
|
assert.match(path.basename(out), /^\d+-my-feature\.md$/)
|
|
|
|
const body = fs.readFileSync(abs, 'utf8')
|
|
assert.match(body, /^# My Feature$/m)
|
|
assert.match(body, /- \[ \] Ship it/)
|
|
|
|
// The whole point: kilo-loop must discover it.
|
|
assert.ok(discoverGoalFiles(project).some((f) => path.resolve(f) === path.resolve(abs)))
|
|
})
|
|
|
|
test('new-plan falls back to a built-in template when the project has none', () => {
|
|
const project = tmpProject()
|
|
const out = run(['Standalone'], project).trim()
|
|
const body = fs.readFileSync(path.join(project, out), 'utf8')
|
|
assert.match(body, /^# Standalone$/m)
|
|
assert.match(body, /## Stages \(kilo-loop\)/)
|
|
assert.match(body, /- \[ \] Stage 1/)
|
|
})
|
|
|
|
test('new-plan --print does not write a file', () => {
|
|
const project = tmpProject()
|
|
const out = run(['Preview only', '--print'], project)
|
|
assert.match(out, /^# Preview only$/m)
|
|
assert.equal(fs.existsSync(path.join(project, '.kilo', 'plans')), false)
|
|
})
|
|
|
|
test('new-plan refuses to overwrite without --force', () => {
|
|
const project = tmpProject()
|
|
const first = run(['Same', '--slug', 'same', '--epoch', '1700000000000'], project).trim()
|
|
assert.equal(first, '.kilo/plans/1700000000000-same.md')
|
|
assert.throws(() => run(['Same', '--slug', 'same', '--epoch', '1700000000000'], project), /already exists/)
|
|
// --force makes it succeed again.
|
|
assert.doesNotThrow(() =>
|
|
execFileSync(process.execPath, [
|
|
SCRIPT, 'Same', '--slug', 'same', '--epoch', '1700000000000', '--force', '--project', project,
|
|
]),
|
|
)
|
|
assert.ok(fs.existsSync(path.join(project, first)))
|
|
})
|