testDebugging
debugging from the editor: launch configurations for a definition, a test and an app
import { plainEnv, tcmBin, tempDir, withChildren } from "#codebase/tcmts/cli/test/e2e/harness"; import { client } from "#codebase/tcmts/cli/test/e2e/lsp"; import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import { pathToFileURL } from "node:url"; export const testDebugging = () => withChildren(async (keep) => { const dir6 = tempDir("lsp debug"); const tcm = (...args: string[]) => spawnSync(process.execPath, [tcmBin(), ...args], { cwd: dir6, env: plainEnv(), encoding: "utf8" }); tcm("init"); fs.writeFileSync( path.join(dir6, "scratch.ts"), `// tcm: namespace lib\nimport { expect } from "vitest";\n\nexport const answer = (): number => 42;\n\nexport const testAnswer = () => {\n expect(answer()).toBe(42);\n};\n\nexport function main() {\n document.title = String(answer());\n}\n`, ); assert.equal(tcm("add").status, 0); const c = client(keep); await c.request("initialize", { processId: null, rootUri: pathToFileURL(dir6).href, capabilities: {}, clientInfo: { name: "Visual Studio Code" } }); c.notify("initialized", {}); const launch = (config: { runtimeExecutable: string; runtimeArgs?: string[]; program: string; args?: string[]; cwd: string }) => spawnSync(config.runtimeExecutable, [...(config.runtimeArgs ?? []), config.program, ...(config.args ?? [])], { cwd: config.cwd, env: plainEnv(), encoding: "utf8" }); // a definition: its runner under Node, with source maps on const run = await c.request("tcm/debug", { kind: "run", name: "lib.answer" }); assert.equal(run.type, "node"); assert.ok(run.sourceMaps && run.skipFiles.includes("<node_internals>/**")); assert.match(launch(run).stdout, /^42$/m); // a test: through Vitest, whose processes the debugger follows const t = await c.request("tcm/debug", { kind: "test", name: "lib.testAnswer" }); assert.equal(t.autoAttachChildProcesses, true); assert.equal(launch(t).status, 0); // an app: tcm dev under Node; its page in a Chrome debug session once it prints its URL const app = await c.request("tcm/debug", { kind: "app", name: "lib.main" }); assert.deepEqual(app.args, ["dev", "lib.main", "--port", "0"]); assert.equal(app.serverReadyAction.action, "debugWithChrome"); assert.ok(new RegExp(app.serverReadyAction.pattern).test(" url http://127.0.0.1:5173/")); // view files offer Debug for what can run const lenses = await c.request("textDocument/codeLens", { textDocument: { uri: pathToFileURL(path.join(dir6, ".tcm", "src", "lib", "testAnswer.ts")).href } }); assert.ok(lenses.some((l: { command: { title: string; command: string } }) => l.command.title === "Debug" && l.command.command === "tcm.debugTest")); c.child.kill(); })