runTestInScratch
uses node:util
Run one test a scratch file holds (path, text being what the file holds), as tcm test runs it, again: its
outcome, as the notebook shows it under the test.
import { classify } from "#codebase/tcmts/cli/main"; import { isTestPath, runCached } from "#codebase/tcmts/cli/testing"; import { HttpError } from "#codebase/tcmts/server"; import { analyzedScratch, editableCodebase, scratchPath } from "#codebase/tcmts/studio"; import type { ScratchValue } from "#codebase/tcmts/studio"; import { stripVTControlCharacters } from "node:util"; export async function runTestInScratch( file: string, text: string, path: string, ): Promise<ScratchValue> { const cb = editableCodebase(); const abs = scratchPath(cb, file, text); const a = analyzedScratch(cb, abs, text); if (a.diagnostics.length || a.errors.length) throw new HttpError(409, `${file} has problems: fix them first.`); const row = classify(cb, a.defs, a.namespace ?? "").find( (r) => r.path === path && isTestPath(r.path), ); if (!row) throw new HttpError(404, `${file} has no test ${path}.`); const src = cb.source([...a.defs, ...a.watches]); const o = runCached(cb, [{ path: row.path, rec: row.def }], src, true)[0]; if (!o) throw new HttpError(500, `${path} didn't run.`); const def = row.def as typeof row.def & { range?: { start: number; nameStart?: number } }; return { line: text.slice(0, def.range?.nameStart ?? def.range?.start ?? 0).split("\n").length, ok: o.result.ok, value: o.result.ok ? `passes (${Math.round(o.result.ms)}ms)` : stripVTControlCharacters(o.result.message), test: path, }; }
uses
- tcmts.cli.main.classify
- tcmts.cli.testing.isTestPath
- tcmts.cli.testing.runCached
- tcmts.server.HttpError
- tcmts.studio.ScratchValue
- tcmts.studio.analyzedScratch
- tcmts.studio.editableCodebase
- tcmts.studio.scratchPath