diff --git a/package-lock.json b/package-lock.json index 6191163..a33c24e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "acorn-loose": "^8.4.0", "ansi-colors": "^4.1.3", "data-uri-to-buffer": "^6.0.2", + "dotenv": "^16.4.5", "estraverse": "^5.3.0", "picomatch": "^4.0.1", "pretty-format": "^29.7.0", @@ -1525,6 +1526,17 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -5251,6 +5263,11 @@ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/package.json b/package.json index 0feade7..4433ee2 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,19 @@ } } } + }, + "nodejs-testing.envFile": { + "type": "string", + "markdownDescription": "Absolute path to a file containing environment variable definitions.\n\nNote: template parameters like ${workspaceFolder} will be resolved.", + "default": "" + }, + "nodejs-testing.env": { + "type": "object", + "markdownDescription": "Environment variables passed to the program. The value null removes the variable from the environment.\n\nNote: This takes precedence over envFile.", + "additionalProperties": { + "type": "string" + }, + "default": {} } } } @@ -184,6 +197,7 @@ "acorn-loose": "^8.4.0", "ansi-colors": "^4.1.3", "data-uri-to-buffer": "^6.0.2", + "dotenv": "^16.4.5", "estraverse": "^5.3.0", "picomatch": "^4.0.1", "pretty-format": "^29.7.0", diff --git a/src/extension.ts b/src/extension.ts index abad0bd..61db698 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -24,6 +24,8 @@ export async function activate(context: vscode.ExtensionContext) { new ConfigValue("style", Style.Spec), context.extensionUri.fsPath, new ConfigValue("nodejsParameters", []), + new ConfigValue("envFile", ""), + new ConfigValue("env", {}), extensions, ); diff --git a/src/runner-protocol.ts b/src/runner-protocol.ts index b993685..626bfeb 100644 --- a/src/runner-protocol.ts +++ b/src/runner-protocol.ts @@ -92,6 +92,7 @@ export const contract = makeContract({ parameters: s.sArrayOf(s.sString()), }), ), + extraEnv: s.sMap(s.sString()), }), result: s.sObject({ status: s.sNumber(), diff --git a/src/runner-worker.ts b/src/runner-worker.ts index 90b190a..bebb732 100644 --- a/src/runner-worker.ts +++ b/src/runner-worker.ts @@ -42,6 +42,7 @@ const start: (typeof contract)["TClientHandler"]["start"] = async ({ files, extensions, verbose, + extraEnv, }) => { const majorVersion = /^v([0-9]+)/.exec(process.version); if (!majorVersion || Number(majorVersion[1]) < 19) { @@ -51,7 +52,7 @@ const start: (typeof contract)["TClientHandler"]["start"] = async ({ const todo: Promise[] = []; for (let i = 0; i < concurrency && i < files.length; i++) { const prefix = colors[i % colors.length](`worker${i + 1}> `); - todo.push(doWork(prefix, files, extensions, verbose)); + todo.push(doWork(prefix, files, extensions, verbose, extraEnv)); } await Promise.all(todo); @@ -63,6 +64,7 @@ async function doWork( queue: ITestRunFile[], extensions: ExtensionConfig[], verbose: boolean, + extraEnv: Record, ) { while (queue.length) { const next = queue.pop()!; @@ -96,6 +98,7 @@ async function doWork( // enable color for modules that use `supports-color` or similar FORCE_COLOR: "true", ...process.env, + ...extraEnv, }, }); diff --git a/src/runner.ts b/src/runner.ts index 82b0062..08b8596 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -2,7 +2,8 @@ import { replaceVariables } from "@c4312/vscode-variables"; import { Contract } from "@hediet/json-rpc"; import { NodeJsMessageStream } from "@hediet/json-rpc-streams/src"; import { spawn } from "child_process"; -import { promises as fs } from "fs"; +import { parse as parseEnv } from "dotenv"; +import fs from "fs/promises"; import { createServer } from "net"; import { cpus, tmpdir } from "os"; import { join } from "path"; @@ -36,6 +37,8 @@ export class TestRunner { private readonly style: ConfigValue