Files
html-transform/test/cli-e2e.test.js
T
2026-05-07 14:46:14 +08:00

82 lines
2.9 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { execFile } from 'node:child_process'
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { tmpdir } from 'node:os'
import { mkdtemp } from 'node:fs/promises'
import { promisify } from 'node:util'
const exec = promisify(execFile)
const cli = new URL('../src/cli.js', import.meta.url).pathname
test('CLI runs doctor and scan against one prototype', async () => {
const cwd = await mkdtemp(join(tmpdir(), 'ht-e2e-'))
await mkdir(join(cwd, 'packages/prototype'), { recursive: true })
await writeFile(join(cwd, 'packages/prototype/index.html'), `
<main>
<h1>Customer Portal</h1>
<form>
<label>Email</label>
<input name="email" required>
<button>Submit</button>
</form>
</main>
`)
await writeFile(join(cwd, 'packages/prototype/portal.md'), `
# Portal Guide
| 雛型檔 | 舊 JSP 來源 | 功能 |
| --- | --- | --- |
| [\`index.html\`](index.html) | \`legacy/index.jsp\` | Customer portal entry |
`)
const doctor = await exec('node', [cli, 'doctor'], { cwd })
await exec('node', [cli, 'scan'], { cwd })
const contract = await readFile(join(cwd, '.ht/spec/index.ui-contract.md'), 'utf8')
const spec = JSON.parse(await readFile(join(cwd, '.ht/spec/index.spec.json'), 'utf8'))
const validation = JSON.parse(await readFile(join(cwd, '.ht/spec/index.validation.json'), 'utf8'))
const appMap = JSON.parse(await readFile(join(cwd, '.ht/app-map.json'), 'utf8'))
assert.match(doctor.stdout, /ok prototype directory/)
assert.match(contract, /Customer Portal/)
assert.equal(spec.pageContract.title, null)
assert.deepEqual(spec.pageContract.forms[0].fields[0], {
name: 'email',
label: 'Email',
type: 'input',
required: true
})
assert.equal(validation.requiresHumanReview, false)
assert.equal(appMap.routes[0].prototype, 'index.html')
assert.equal(appMap.routes[0].kind, 'feature-page')
assert.equal(appMap.routes[0].layout, 'template-app')
assert.equal(appMap.routes[0].guide.legacyJsp, 'legacy/index.jsp')
assert.equal(appMap.routes[0].guide.description, 'Customer portal entry')
assert.equal(appMap.guideSources[0].source, 'portal.md')
})
test('CLI help only exposes MVP commands', async () => {
const result = await exec('node', [cli, 'help'])
assert.match(result.stdout, /doctor/)
assert.match(result.stdout, /scan/)
assert.doesNotMatch(result.stdout, /plan/)
assert.doesNotMatch(result.stdout, /run/)
assert.doesNotMatch(result.stdout, /diff/)
assert.doesNotMatch(result.stdout, /verify/)
})
test('CLI rejects removed pipeline commands', async () => {
await assert.rejects(
exec('node', [cli, 'plan']),
(error) => {
assert.equal(error.code, 1)
assert.match(error.stdout, /doctor/)
assert.match(error.stdout, /scan/)
return true
}
)
})