From 17904ecede8fa709c75461bcec35812702774ae3 Mon Sep 17 00:00:00 2001 From: Avi Vahl Date: Thu, 21 Aug 2025 12:11:30 +0300 Subject: [PATCH] feat: support format=esm in esbuild config will use type="module" for tests.js when it is specified, allowing esm-specific syntax --- src/run-tests.ts | 11 +++++++---- .../with-esm-esbuild-config/esbuild.config.js | 4 ++++ .../with-esm-esbuild-config/with-import-meta.ts | 7 +++++++ test/mocha-web.spec.ts | 11 +++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/with-esm-esbuild-config/esbuild.config.js create mode 100644 test/fixtures/with-esm-esbuild-config/with-import-meta.ts diff --git a/src/run-tests.ts b/src/run-tests.ts index 3d1ad20..cad3608 100644 --- a/src/run-tests.ts +++ b/src/run-tests.ts @@ -38,7 +38,7 @@ export async function runTests(testFiles: string[], options: IRunTestsOptions = const indexContents = testFiles.map((f) => `require(${JSON.stringify(f)});`).join("\n"); const { onBuildEndPlugin, onBuildEnd } = captureBuildEnd(); - + const format = esbuildConfig?.format ?? "iife"; const combinedConfig = { ...esbuildConfig, stdin: { @@ -51,11 +51,11 @@ export async function runTests(testFiles: string[], options: IRunTestsOptions = write: false, sourcemap: true, bundle: true, - format: "iife", + format, logLevel: "info", plugins: [ ...(esbuildConfig?.plugins ?? []), - createOutputCapturePlugin(workingDir, buildFilesMap, options), + createOutputCapturePlugin(workingDir, buildFilesMap, options, format), onBuildEndPlugin, ], } satisfies esbuild.BuildOptions; @@ -121,6 +121,7 @@ function createOutputCapturePlugin( workingDir: string, buildFilesMap: Map, options: IRunTestsOptions, + format: esbuild.Format, ): esbuild.Plugin { return { name: "capture-output", @@ -132,6 +133,7 @@ function createOutputCapturePlugin( buildFilesMap.set("/" + path.relative(workingDir, outFile.path).replace("/\\/g", "/"), outFile); } const testsHTML = createTestsHTML( + format, "mocha tests", options.ui ?? "bdd", options.colors ?? true, @@ -195,6 +197,7 @@ async function waitForTestResults(page: playwright.Page): Promise { } function createTestsHTML( + format: esbuild.Format, title: string, ui: string, color: boolean, @@ -253,7 +256,7 @@ function createTestsHTML( .on('end', () => {(mochaStatus.finished = true)}); }); - + ${format === "esm" ? `` : ``} `; diff --git a/test/fixtures/with-esm-esbuild-config/esbuild.config.js b/test/fixtures/with-esm-esbuild-config/esbuild.config.js new file mode 100644 index 0000000..d509fd6 --- /dev/null +++ b/test/fixtures/with-esm-esbuild-config/esbuild.config.js @@ -0,0 +1,4 @@ +/** @type {import("esbuild").BuildOptions} */ +export default { + format: "esm", +}; diff --git a/test/fixtures/with-esm-esbuild-config/with-import-meta.ts b/test/fixtures/with-esm-esbuild-config/with-import-meta.ts new file mode 100644 index 0000000..b0a7e2e --- /dev/null +++ b/test/fixtures/with-esm-esbuild-config/with-import-meta.ts @@ -0,0 +1,7 @@ +describe("suite", () => { + it("passes when esm is supported", () => { + if (typeof import.meta.url !== "string") { + throw new Error("import.meta.url is not a string"); + } + }); +}); diff --git a/test/mocha-web.spec.ts b/test/mocha-web.spec.ts index 88d1b15..139cc52 100644 --- a/test/mocha-web.spec.ts +++ b/test/mocha-web.spec.ts @@ -153,4 +153,15 @@ describe("mocha-web", function () { expect(output, output).to.include("body background-color: rgb(0, 255, 0)"); expect(status).to.equal(0); }); + + it("supports esm syntax when esbuild config specifies format=esm", () => { + const { output, status } = runMochaPlay({ + args: ["./with-import-meta.ts"], + fixture: "with-esm-esbuild-config", + }); + + expect(output).to.include("Found 1 test files"); + expect(output).to.include("1 passing"); + expect(status).to.equal(0); + }); });