tcmts.cli.test.e2e.harness

Server

installedPackage (name: string) => string
Where a package tcm runs with is installed (its directory): beside the tcm being tested (a packed one), or in the cache of the codebase these tests run in, where tcm provides it under an alias (the codebase's own tcm).
okIn (dir: string, ...args: string[]) => string
Run tcm in `dir`, failing the test if it fails: what it printed.
plainEnv () => ProcessEnv
The environment tcm runs in here: no colours, so its output reads as text.
stopWhenThisEnds (c: ChildProcess) => void
Stop a process this one started once this one ends, however it ends: killed (SIGKILL, a hung test's time limit), it can't stop anything itself, and what it started would run on for good, orphaned. A watchdog process (one for this process, started with the first it's told of: `WATCHDOG`) is told each process kept and each that ends; this process's end closes the pipe to it, and it stops those still running: asked to (SIGTERM), then made to (SIGKILL) if one hasn't in 5 seconds. (Something kept that isn't a child process, a server in this one, is withChildren's.)
strip (s: string) => string
Text without terminal escapes.
tcmBin () => string
The tcm under test: `tcm test` sets TCM_BIN to the codebase's own build.
tcmIn (dir: string, ...args: string[]) => { status: number | null; out: string; }
Run tcm in `dir`: its exit status, and what it printed on both streams.
tcmInBackground (keep: <C extends ChildProcess>(c: C) => C, dir: string, ...args: string[]) => Promise<{ status: nu…
Run tcm in `dir` alongside other things (another tcm, a server it calls), as `tcmIn` does, kept by `withChildren`'s `keep`: its exit status, and what it printed on both streams, once it has ended.
tempDir (name: string) => string
A new empty directory, resolved through symlinks; the space in its name catches quoting bugs.
withChildren <T>(fn: (keep: <C extends ChildProcess>(c: C) => C) => T | Promise<T>) => Promise<T>
Run `fn` with a way to keep the processes it starts (servers, watchers), and stop them when it's done, waiting until they have: a tcm stopped so writes what code it ran as it exits (coverage, which the suite reads once this test's process ends), and one still writing would be missed, its suite's result cached as though that code hadn't run. One that doesn't stop in 10 seconds is killed. And if this process ends first, however it ends (a test that hangs is killed by its suite's time limit, and its `finally` never runs), they're stopped all the same (`stopWhenThisEnds`).

Shared

WATCHDOG "\nconst pids = new Set();\nlet buf = \"\";\nprocess.stdin.setEncoding(\"utf8\");\nprocess.stdin.on…
The watchdog's program: reads `+<pid>` (kept) and `-<pid>` (ended) lines; when what it reads ends (the process that started it has), stops those still running: SIGTERM, then SIGKILL after 5 seconds.
watchdogs Map<number, ChildProcess>
The watchdog `stopWhenThisEnds` starts, for each process (by pid).

Tests

testServersStopWhenTheirTestDoes (role?: string | undefined) => Promise<void>
A test's servers stop when it does, however it ends: one that fails midway stops them as it fails, and one that hangs, killed by its suite's time limit (SIGKILL: its `finally` never runs), has them stopped by its watchdog rather than left running for good. (This test is both: run again as a program of its own, with `role` saying which, it keeps a tcm server and fails, or hangs.)