Files
orca/mobile/scripts/build-terminal-document-script.test.ts
T
Jinwoo-H c9880d9f67 refactor(mobile): extract the terminal path-tap group into a module
The ninth named group, and a pure query: it reads no shared state, so it has
no qualifier sites at all.

Two things this group forced. The generator now drops lint directive lines
before the transform, because a directive inside an expression makes esbuild
parenthesise that expression to keep the comment where it was, and those
parentheses are tokens the document does not have. And the two regexes keep
their `no-useless-escape` escapes behind a line-scoped disable, for the same
reason the theme group keeps `Math.pow`.

One name the document declares twice in one function stays `var`. Two
block-scoped declarations would be two bindings where the document has one,
and esbuild renames the inner one to say so.

Counts: qualified 0, scope declarations 0, rebindings 31, braced bodies 20,
unbound catches 0, number properties 2.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-20 09:15:35 -04:00

87 lines
3.4 KiB
TypeScript

import { mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { emitTerminalDocumentModule } from './build-terminal-document-script.mjs'
import { terminalBackgroundFallback } from '../src/terminal/document/document-constants'
/**
* What the generator drops, what it keeps, and how it puts a module back into the document.
*
* The per-group tests compare a real module against the string the document carries, which says
* the two agree; these say why, on inputs small enough to read. The import and export cases are
* the ones that bit: esbuild wraps a long list across lines, and skipping only the first line
* leaves the rest of the names loose in the document.
*/
let directory: string
async function emit(source: string): Promise<string> {
const path = join(directory, `module-${Math.random().toString(36).slice(2)}.ts`)
await writeFile(path, source)
return emitTerminalDocumentModule(path)
}
beforeAll(async () => {
directory = await mkdtemp(join(tmpdir(), 'orca-terminal-document-'))
})
afterAll(async () => {
await rm(directory, { recursive: true, force: true })
})
describe('emitting one terminal document module', () => {
it('unmarks an export and indents it into the document scope', async () => {
expect(await emit('export function f() {\n return 1\n}\n')).toBe(
' function f() {\n return 1;\n }'
)
})
it('drops an import that fits on one line', async () => {
expect(await emit("import { a } from './x'\nexport const b = 1\n")).toBe(' const b = 1;')
})
it('drops an import esbuild wrapped across lines', async () => {
// The case that produced an unparseable document: the names after the first line stayed.
const source =
"import { alpha, beta, gamma, delta, epsilon, zeta, eta, theta } from './document-externals'\n" +
'export const b = alpha\n'
expect(await emit(source)).toBe(' const b = alpha;')
})
it('drops the trailing export block esbuild prints, not just its keyword', async () => {
// Left behind it is a bare block statement, which parses and does nothing.
const emitted = await emit('function f() {}\nfunction g() {}\nexport { f, g }\n')
expect(emitted).not.toContain('{ f, g }')
expect(emitted).toBe(' function f() {\n }\n function g() {\n }')
})
it('erases types without touching the program', async () => {
expect(
await emit(
'export type T = { a: number }\nexport function f(v: T): number {\n return v.a\n}\n'
)
).toBe(' function f(v) {\n return v.a;\n }')
})
it('substitutes a build-time constant the document carries as a literal', async () => {
const emitted = await emit(
"import { terminalBackgroundFallback } from '../src/terminal/document/document-constants'\n" +
'export function paint() {\n' +
' return terminalBackgroundFallback\n' +
'}\n'
)
expect(emitted).toContain(JSON.stringify(terminalBackgroundFallback))
expect(emitted).not.toContain('terminalBackgroundFallback')
})
it('drops a lint directive rather than let it parenthesise the expression it guards', async () => {
expect(
await emit(
'export const R =\n' +
' // oxlint-disable-next-line no-useless-escape\n' +
' /a/g\n'
)
).toBe(' const R = /a/g;')
})
})