feat: projcet Initialization
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
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 scan, plan, run, diff, and verify against one prototype', async () => {
|
||||
const cwd = await mkdtemp(join(tmpdir(), 'ht-e2e-'))
|
||||
await mkdir(join(cwd, 'packages/prototype'), { recursive: true })
|
||||
await mkdir(join(cwd, 'packages/web/src'), { recursive: true })
|
||||
await mkdir(join(cwd, 'packages/api'), { 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/web/src/App.vue'), '<template><v-app /></template>')
|
||||
await writeFile(join(cwd, 'packages/api/openapi.json'), '{"openapi":"3.0.0","paths":{}}')
|
||||
await writeFile(join(cwd, 'ht.config.js'), `
|
||||
export default {
|
||||
plan: { interactiveReview: false },
|
||||
project: { qualityCommands: {} }
|
||||
}
|
||||
`)
|
||||
|
||||
for (const command of ['scan', 'plan', 'run', 'diff', 'verify']) {
|
||||
await exec('node', [cli, command], { cwd })
|
||||
}
|
||||
|
||||
const component = await readFile(join(cwd, 'packages/result/index/main-1.vue'), 'utf8')
|
||||
const report = JSON.parse(await readFile(join(cwd, '.ht/verify/verification-report.json'), 'utf8'))
|
||||
|
||||
assert.match(component, /Customer Portal/)
|
||||
assert.match(component, /v-text-field/)
|
||||
assert.equal(report.domChecks.status, 'passed')
|
||||
})
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { mkdtemp, writeFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { loadConfig } from '../src/lib/config.js'
|
||||
|
||||
test('loadConfig supports ht.config.ts defineConfig shape', async () => {
|
||||
const cwd = await mkdtemp(join(tmpdir(), 'ht-config-'))
|
||||
await writeFile(join(cwd, 'ht.config.ts'), `
|
||||
import { defineConfig } from 'html-transform'
|
||||
export default defineConfig({
|
||||
prototype: './proto',
|
||||
output: './out',
|
||||
plan: { interactiveReview: true }
|
||||
})
|
||||
`)
|
||||
|
||||
const config = await loadConfig(cwd)
|
||||
|
||||
assert.equal(config.prototypeDir, join(cwd, 'proto'))
|
||||
assert.equal(config.outputDir, join(cwd, 'out'))
|
||||
assert.equal(config.plan.interactiveReview, true)
|
||||
assert.equal(config.project.qualityCommands.lint, 'pnpm lint')
|
||||
})
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { extractRegions, inferRegionSpec, summarizeHtml } from '../src/lib/html.js'
|
||||
|
||||
test('summarizeHtml extracts user-visible contract evidence', () => {
|
||||
const summary = summarizeHtml(`
|
||||
<title>Orders</title>
|
||||
<main>
|
||||
<h1>Orders</h1>
|
||||
<form><label>Email</label><input name="email" required><button>Save</button></form>
|
||||
</main>
|
||||
`)
|
||||
|
||||
assert.equal(summary.title, 'Orders')
|
||||
assert.deepEqual(summary.labels, ['Email'])
|
||||
assert.deepEqual(summary.buttons, ['Save'])
|
||||
assert.equal(summary.inputs[0].name, 'email')
|
||||
assert.equal(summary.inputs[0].required, true)
|
||||
})
|
||||
|
||||
test('extractRegions falls back to a single page region', () => {
|
||||
const regions = extractRegions('<h1>Hello</h1><p>World</p>')
|
||||
|
||||
assert.equal(regions.length, 1)
|
||||
assert.equal(regions[0].id, 'page-1')
|
||||
})
|
||||
|
||||
test('inferRegionSpec maps forms to VForm', () => {
|
||||
const [region] = extractRegions('<main><form><input name="q"><button>Search</button></form></main>')
|
||||
const spec = inferRegionSpec(region)
|
||||
|
||||
assert.equal(spec.vuetifyComponent, 'VForm')
|
||||
assert.deepEqual(spec.uiContract.primaryActions, ['Search'])
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user