test(mobile): pin the terminal WebView document byte for byte

The document is already pinned as a digest, which says whether the emitted
bytes moved and nothing about where. C7.1 moves the hand-written script inside
it into modules the web page can import and rebuilds the document from them,
and the claim that has to hold through every one of those commits is that the
native screen kept the document it had. A digest cannot be the instrument for
that: it fails as two hexadecimal strings.

So the document is also committed as itself. The fixture is generated by
`scripts/build-terminal-document-fixture.mjs`, never pasted, and the test
rebuilds the comparison through that script's own substitution rather than
restating it, so a fixture written by one rule and read by another cannot agree
with itself.

The generated xterm engine is stored as two placeholders. It is already covered
by the digest test, postinstall regenerates it from whatever xterm the lockfile
holds, and inlining it would put 612 KiB of vendored bytes into the file whose
job is to isolate hand-written changes. Two further cases keep that from
becoming a hole: the placeholders must each appear exactly once and the engine
must not appear at all, and the restored document must equal the real one.

Regenerating the fixture is a review event. It is only correct when the emitted
document was meant to change, and the diff in that commit is the evidence.

Red-first: flipping one character inside a comment in `write-queue.ts` fails
both identity cases with a one-line diff naming the comment, where the digest
test reports a hash.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
This commit is contained in:
Jinwoo-H
2026-09-20 05:51:03 -04:00
parent 96c1dd8b70
commit 3006d8dfdf
3 changed files with 3065 additions and 0 deletions
@@ -0,0 +1,91 @@
import { writeFile } from 'node:fs/promises'
import path from 'node:path'
import * as esbuild from 'esbuild'
/**
* Writes the committed copy of the terminal WebView document that
* `terminal-document-identity.test.ts` diffs against.
*
* The document is a build artifact: fourteen source slices joined in a pinned order, with the
* generated xterm engine spliced into two of them. `terminal-webview-payload-hash.test.ts` already
* says *whether* it moved; what it cannot say is *where*, and a refactor whose whole claim is that
* the document did not move needs the diff, not the digest.
*
* The two generated engine strings are stored as placeholders rather than inline. They are already
* pinned by the hash test, they are regenerated by postinstall from whatever xterm version the
* lockfile holds, and inlining them would put 612 KiB of vendored bytes in the fixture and turn
* every xterm bump into an unreadable diff of the file that is supposed to isolate hand-written
* changes.
*
* Regenerating this fixture is a review event: it is only correct when the emitted document was
* meant to change, and the diff is the evidence for that. Run `node scripts/build-terminal-document-fixture.mjs`
* from `mobile/`.
*/
const mobileRoot = path.resolve(import.meta.dirname, '..')
const entry = path.join(mobileRoot, 'src', 'terminal', 'terminal-webview-html.ts')
const enginePath = path.join(mobileRoot, 'src', 'terminal', 'terminal-webview-engine.generated.ts')
export const TERMINAL_DOCUMENT_FIXTURE_PATH = path.join(
mobileRoot,
'src',
'terminal',
'terminal-document-golden.txt'
)
/** Chosen so the document cannot contain one by accident; asserted below and in the test. */
export const ENGINE_JS_PLACEHOLDER = '__ORCA_TERMINAL_ENGINE_JS__'
export const ENGINE_CSS_PLACEHOLDER = '__ORCA_TERMINAL_ENGINE_CSS__'
async function loadModule(entryPoint) {
const result = await esbuild.build({
entryPoints: [entryPoint],
bundle: true,
format: 'esm',
platform: 'node',
write: false,
logLevel: 'silent'
})
const code = result.outputFiles[0].text
return import(`data:text/javascript;base64,${Buffer.from(code, 'utf8').toString('base64')}`)
}
/**
* The document with both generated sections replaced by their placeholders.
*
* Exported so the test builds the same text the script writes, rather than restating the
* substitution and agreeing with a fixture that was written wrong.
*/
export function terminalDocumentFixture(document, engineJs, engineCss) {
for (const placeholder of [ENGINE_JS_PLACEHOLDER, ENGINE_CSS_PLACEHOLDER]) {
if (document.includes(placeholder)) {
throw new Error(`the document already contains ${placeholder}`)
}
}
for (const [name, value] of [
['XTERM_ENGINE_JS', engineJs],
['XTERM_ENGINE_CSS', engineCss]
]) {
if (document.split(value).length !== 2) {
throw new Error(`${name} does not appear exactly once in the document`)
}
}
return document
.replace(engineJs, ENGINE_JS_PLACEHOLDER)
.replace(engineCss, ENGINE_CSS_PLACEHOLDER)
}
async function main() {
const [{ XTERM_HTML }, { XTERM_ENGINE_JS, XTERM_ENGINE_CSS }] = await Promise.all([
loadModule(entry),
loadModule(enginePath)
])
const fixture = terminalDocumentFixture(XTERM_HTML, XTERM_ENGINE_JS, XTERM_ENGINE_CSS)
await writeFile(TERMINAL_DOCUMENT_FIXTURE_PATH, fixture)
console.log(
`[build-terminal-document-fixture] ${Buffer.byteLength(fixture, 'utf8')} bytes (document ${Buffer.byteLength(XTERM_HTML, 'utf8')})`
)
}
if (import.meta.filename === process.argv[1]) {
await main()
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,54 @@
import { readFileSync } from 'node:fs'
import { describe, expect, it } from 'vitest'
import {
ENGINE_CSS_PLACEHOLDER,
ENGINE_JS_PLACEHOLDER,
TERMINAL_DOCUMENT_FIXTURE_PATH,
terminalDocumentFixture
} from '../../scripts/build-terminal-document-fixture.mjs'
import { XTERM_ENGINE_CSS, XTERM_ENGINE_JS } from './terminal-webview-engine.generated'
import { XTERM_HTML } from './terminal-webview-html'
/**
* The emitted WebView document, byte for byte, against a committed copy of itself.
*
* `terminal-webview-payload-hash.test.ts` pins the same bytes as a digest, which answers whether
* the document moved. This answers where: the whole document is one assertion, so a slice that
* gained a character, lost an indent or changed order arrives as a diff of the line rather than as
* two hexadecimal strings. Both are kept — the digest also covers the generated engine, which this
* fixture deliberately does not.
*
* C7.1 moves the document's hand-written script into modules the web page can import, and a
* generator rebuilds the document from them. This is the instrument that says the native screen
* kept the document it had. Regenerate the fixture with
* `node scripts/build-terminal-document-fixture.mjs` only when the emitted document was meant to
* change; the diff in that commit is the evidence, and reviewing it is the point.
*/
const fixture = readFileSync(TERMINAL_DOCUMENT_FIXTURE_PATH, 'utf8')
describe('the terminal WebView document', () => {
it('is byte for byte the document the fixture holds', () => {
// Rebuilt through the script's own substitution rather than a second copy of it: a fixture
// written by a different rule than the one that reads it agrees with itself and with nothing.
expect(terminalDocumentFixture(XTERM_HTML, XTERM_ENGINE_JS, XTERM_ENGINE_CSS)).toBe(fixture)
})
it('holds the generated engine as placeholders, so an xterm bump is not a diff here', () => {
// Without this the fixture could lose a placeholder — inlining the engine, or dropping the
// section entirely — and the assertion above would still pass against whatever it became.
for (const placeholder of [ENGINE_JS_PLACEHOLDER, ENGINE_CSS_PLACEHOLDER]) {
expect(fixture.split(placeholder)).toHaveLength(2)
}
expect(fixture).not.toContain(XTERM_ENGINE_JS)
expect(fixture).not.toContain(XTERM_ENGINE_CSS)
})
it('is the whole document once the engine is put back', () => {
// The placeholder round trip, which is what makes the first case a claim about the document
// and not only about the hand-written part of it.
const restored = fixture
.replace(ENGINE_JS_PLACEHOLDER, () => XTERM_ENGINE_JS)
.replace(ENGINE_CSS_PLACEHOLDER, () => XTERM_ENGINE_CSS)
expect(restored).toBe(XTERM_HTML)
})
})