23fc852321
Remove generated `.ui-contract.md` and `.bdd.md` outputs from the scan pipeline and documentation so downstream consumers rely on structured JSON artifacts instead. Also drop unused API `fieldRules` catalog output and remove stale app-map references to UI contract files. Update legacy flow matching to preserve only the nodes that directly matched the current entry.refactor(scan): stop emitting markdown contract artifacts Remove generated `.ui-contract.md` and `.bdd.md` outputs from the scan pipeline and documentation so downstream consumers rely on structured JSON artifacts instead. Also drop unused API `fieldRules` catalog output and remove stale app-map references to UI contract files. Update legacy flow matching to preserve only the nodes that directly matched the current entry.
91 lines
3.5 KiB
JavaScript
91 lines
3.5 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 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.equal(spec.pageContract.title, null)
|
|
assert.equal(spec.bddContract.feature, 'Customer portal entry')
|
|
assert.equal(spec.bddContract.scenarios[0].type, 'application-submit')
|
|
assert.match(spec.captureArtifacts.domSummary, /\.ht\/cache\/prototype\/index\/dom-summary\.json$/)
|
|
assert.match(spec.captureArtifacts.accessibilityTree, /\.ht\/cache\/prototype\/index\/accessibility-tree\.json$/)
|
|
assert.equal(Array.isArray(spec.browserEvidence.externalResourceFailures), true)
|
|
assert.deepEqual(pick(spec.pageContract.forms[0].fields[0], ['name', 'label', 'type', 'required']), {
|
|
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].recommendedTemplate, undefined)
|
|
assert.equal(appMap.routes[0].evidence.recommendedTemplate, undefined)
|
|
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')
|
|
})
|
|
|
|
function pick(object, keys) {
|
|
return Object.fromEntries(keys.map((key) => [key, object[key]]))
|
|
}
|
|
|
|
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
|
|
}
|
|
)
|
|
})
|