From b2ee7d1440135c140ea9d15825c3a172c72411ce Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Wed, 4 Mar 2026 21:40:12 +0300 Subject: [PATCH 1/4] test: refactor config format test + more --- eslint.config.mjs | 2 +- test/build/config-format/auto/auto.test.mjs | 44 ++++++++ .../main.ts => auto/main.js} | 0 .../package.json | 1 - .../config-format/auto/webpack.config.cjs | 13 +++ .../config-format/auto/webpack.config.js | 13 +++ .../config-format/auto/webpack.config.mjs | 13 +++ .../disable-interpret.test.js | 8 +- .../esm-require-await/index.test.js | 18 ---- .../config-format/esm-require/index.test.js | 18 ---- test/build/config-format/esm-require/main.js | 1 - .../esm-require/webpack.config.js | 11 -- .../esm-top-level-await/index.test.js | 11 ++ .../main.js | 0 .../webpack.config.mjs} | 5 +- .../main.ts | 0 .../package.json | 1 - .../typescript-auto/typescript.test.mjs | 74 +++++++++++++ .../webpack.config.cts} | 0 .../webpack.config.mts} | 0 .../webpack.config.ts | 0 .../typescript.test.mjs | 26 ----- .../main.ts | 0 .../package.json | 0 .../tsconfig.json | 0 .../typescript-cjs/typescript.test.mjs | 93 ++++++++++++++++ .../webpack.config.ts | 6 +- .../typescript.test.mjs | 29 ----- .../main.ts | 0 .../package.json | 0 .../tsconfig.json | 0 .../typescript-mjs/typescript.test.mjs | 101 ++++++++++++++++++ .../webpack.config.ts | 0 .../typescript-ts-node-loader/tsconfig.json | 6 -- .../typescript.test.mjs | 27 ----- .../typescript-ts-node-require/main.ts | 1 - .../typescript-ts-node-require/tsconfig.json | 5 - .../typescript.test.js | 21 ---- .../typescript-using-nodejs/package.json | 6 -- .../typescript-using-nodejs/tsconfig.json | 8 -- .../typescript.test.mjs | 29 ----- 41 files changed, 376 insertions(+), 215 deletions(-) create mode 100644 test/build/config-format/auto/auto.test.mjs rename test/build/config-format/{typescript-cjs-using-nodejs/main.ts => auto/main.js} (100%) rename test/build/config-format/{typescript-mjs-using-nodejs => auto}/package.json (70%) create mode 100644 test/build/config-format/auto/webpack.config.cjs create mode 100644 test/build/config-format/auto/webpack.config.js create mode 100644 test/build/config-format/auto/webpack.config.mjs delete mode 100644 test/build/config-format/esm-require-await/index.test.js delete mode 100644 test/build/config-format/esm-require/index.test.js delete mode 100644 test/build/config-format/esm-require/main.js delete mode 100644 test/build/config-format/esm-require/webpack.config.js create mode 100644 test/build/config-format/esm-top-level-await/index.test.js rename test/build/config-format/{esm-require-await => esm-top-level-await}/main.js (100%) rename test/build/config-format/{esm-require-await/webpack.config.js => esm-top-level-await/webpack.config.mjs} (62%) rename test/build/config-format/{typescript-mjs-using-nodejs => typescript-auto}/main.ts (100%) rename test/build/config-format/{typescript-ts-node-loader => typescript-auto}/package.json (70%) create mode 100644 test/build/config-format/typescript-auto/typescript.test.mjs rename test/build/config-format/{typescript-cjs-using-nodejs/webpack.config.ts => typescript-auto/webpack.config.cts} (100%) rename test/build/config-format/{typescript-mjs-using-nodejs/webpack.config.ts => typescript-auto/webpack.config.mts} (100%) rename test/build/config-format/{typescript-ts-node-loader => typescript-auto}/webpack.config.ts (100%) delete mode 100644 test/build/config-format/typescript-cjs-using-nodejs/typescript.test.mjs rename test/build/config-format/{typescript-ts-node-loader => typescript-cjs}/main.ts (100%) rename test/build/config-format/{typescript-cjs-using-nodejs => typescript-cjs}/package.json (100%) rename test/build/config-format/{typescript-cjs-using-nodejs => typescript-cjs}/tsconfig.json (100%) create mode 100644 test/build/config-format/typescript-cjs/typescript.test.mjs rename test/build/config-format/{typescript-ts-node-require => typescript-cjs}/webpack.config.ts (68%) delete mode 100644 test/build/config-format/typescript-mjs-using-nodejs/typescript.test.mjs rename test/build/config-format/{typescript-using-nodejs => typescript-mjs}/main.ts (100%) rename test/build/config-format/{babel-esm => typescript-mjs}/package.json (100%) rename test/build/config-format/{typescript-mjs-using-nodejs => typescript-mjs}/tsconfig.json (100%) create mode 100644 test/build/config-format/typescript-mjs/typescript.test.mjs rename test/build/config-format/{typescript-using-nodejs => typescript-mjs}/webpack.config.ts (100%) delete mode 100644 test/build/config-format/typescript-ts-node-loader/tsconfig.json delete mode 100644 test/build/config-format/typescript-ts-node-loader/typescript.test.mjs delete mode 100644 test/build/config-format/typescript-ts-node-require/main.ts delete mode 100644 test/build/config-format/typescript-ts-node-require/tsconfig.json delete mode 100644 test/build/config-format/typescript-ts-node-require/typescript.test.js delete mode 100644 test/build/config-format/typescript-using-nodejs/package.json delete mode 100644 test/build/config-format/typescript-using-nodejs/tsconfig.json delete mode 100644 test/build/config-format/typescript-using-nodejs/typescript.test.mjs diff --git a/eslint.config.mjs b/eslint.config.mjs index 9c51bae9331..960d43d6927 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -15,7 +15,7 @@ export default defineConfig([ "test/build/config/error-array/webpack.config.js", "test/build/config-format/esm-require-await/webpack.config.js", "test/configtest/with-config-path/syntax-error.config.js", - "test/build/config-format/esm-require/webpack.config.js", + "test/build/config-format/auto/webpack.config.js", ]), { extends: [config], diff --git a/test/build/config-format/auto/auto.test.mjs b/test/build/config-format/auto/auto.test.mjs new file mode 100644 index 00000000000..da5ace9657b --- /dev/null +++ b/test/build/config-format/auto/auto.test.mjs @@ -0,0 +1,44 @@ +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { run } from "../../../utils/test-utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +describe("auto loading different formats of configuration", () => { + it("should support configuration (Node.js build-in support)", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.js"], { + nodeOptions: [], + }); + + expect(stderr).toContain( + "Reparsing as ES module because module syntax was detected. This incurs a performance overhead.", + ); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support configuration (Node.js build-in support) with `mjs` extension", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.mjs"], { + nodeOptions: [], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support configuration (Node.js build-in support) with `cjs` extension", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.cjs"], { + nodeOptions: [], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); +}); diff --git a/test/build/config-format/typescript-cjs-using-nodejs/main.ts b/test/build/config-format/auto/main.js similarity index 100% rename from test/build/config-format/typescript-cjs-using-nodejs/main.ts rename to test/build/config-format/auto/main.js diff --git a/test/build/config-format/typescript-mjs-using-nodejs/package.json b/test/build/config-format/auto/package.json similarity index 70% rename from test/build/config-format/typescript-mjs-using-nodejs/package.json rename to test/build/config-format/auto/package.json index 2921f73c914..c49ae366fdc 100644 --- a/test/build/config-format/typescript-mjs-using-nodejs/package.json +++ b/test/build/config-format/auto/package.json @@ -1,5 +1,4 @@ { - "type": "module", "engines": { "node": ">=18.12.0" } diff --git a/test/build/config-format/auto/webpack.config.cjs b/test/build/config-format/auto/webpack.config.cjs new file mode 100644 index 00000000000..abfcb5385b0 --- /dev/null +++ b/test/build/config-format/auto/webpack.config.cjs @@ -0,0 +1,13 @@ +const path = require("node:path"); + +const mode = "development"; +const config = { + mode, + entry: "./main.js", + output: { + path: path.resolve("dist"), + filename: "foo.bundle.js", + }, +}; + +module.exports = config; diff --git a/test/build/config-format/auto/webpack.config.js b/test/build/config-format/auto/webpack.config.js new file mode 100644 index 00000000000..b00f4bdc850 --- /dev/null +++ b/test/build/config-format/auto/webpack.config.js @@ -0,0 +1,13 @@ +import * as path from "node:path"; + +const mode = "development"; +const config = { + mode, + entry: "./main.js", + output: { + path: path.resolve("dist"), + filename: "foo.bundle.js", + }, +}; + +export default config; diff --git a/test/build/config-format/auto/webpack.config.mjs b/test/build/config-format/auto/webpack.config.mjs new file mode 100644 index 00000000000..b00f4bdc850 --- /dev/null +++ b/test/build/config-format/auto/webpack.config.mjs @@ -0,0 +1,13 @@ +import * as path from "node:path"; + +const mode = "development"; +const config = { + mode, + entry: "./main.js", + output: { + path: path.resolve("dist"), + filename: "foo.bundle.js", + }, +}; + +export default config; diff --git a/test/build/config-format/disable-interpret/disable-interpret.test.js b/test/build/config-format/disable-interpret/disable-interpret.test.js index 5bbca3a227d..8033092e58c 100644 --- a/test/build/config-format/disable-interpret/disable-interpret.test.js +++ b/test/build/config-format/disable-interpret/disable-interpret.test.js @@ -21,7 +21,13 @@ describe("webpack cli", () => { }); it("should log error without transpilation", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["--disable-interpret"]); + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["--disable-interpret"], { + nodeOptions: [ + // Disable typescript strip types for tests + ...(major >= 24 ? ["--no-experimental-strip-types"] : []), + ], + }); expect(exitCode).toBe(2); expect(stderr).toContain(`Failed to load '${resolve(__dirname, "webpack.config.ts")}' config`); diff --git a/test/build/config-format/esm-require-await/index.test.js b/test/build/config-format/esm-require-await/index.test.js deleted file mode 100644 index 002daf8c301..00000000000 --- a/test/build/config-format/esm-require-await/index.test.js +++ /dev/null @@ -1,18 +0,0 @@ -const { run } = require("../../../utils/test-utils"); - -describe("webpack cli", () => { - it("should support mjs config format using `require`", async () => { - const { exitCode, stdout } = await run(__dirname, ["-c", "webpack.config.js"]); - - const [major, minor] = process.versions.node.split(".").map(Number); - - if ((major >= 20 && minor >= 19) || major >= 22 || major >= 23) { - expect(exitCode).toBe(0); - // stderr contains - Support for loading ES Module in require() is an experimental feature and might change at any time - // expect(stderr).toBeFalsy(); - expect(stdout).toBeTruthy(); - } else { - expect(exitCode).toBe(2); - } - }); -}); diff --git a/test/build/config-format/esm-require/index.test.js b/test/build/config-format/esm-require/index.test.js deleted file mode 100644 index 770ed8238bd..00000000000 --- a/test/build/config-format/esm-require/index.test.js +++ /dev/null @@ -1,18 +0,0 @@ -const { run } = require("../../../utils/test-utils"); - -describe("webpack cli", () => { - it("should support mjs config format using `require`", async () => { - const { exitCode, stdout } = await run(__dirname, ["-c", "webpack.config.js"]); - - const [major, minor] = process.versions.node.split(".").map(Number); - - if ((major >= 20 && minor >= 17) || major >= 22 || major >= 23) { - expect(exitCode).toBe(0); - // stderr contains - Support for loading ES Module in require() is an experimental feature and might change at any time - // expect(stderr).toBeFalsy(); - expect(stdout).toBeTruthy(); - } else { - expect(exitCode).toBe(2); - } - }); -}); diff --git a/test/build/config-format/esm-require/main.js b/test/build/config-format/esm-require/main.js deleted file mode 100644 index ecbe8cd001a..00000000000 --- a/test/build/config-format/esm-require/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log("You know who"); diff --git a/test/build/config-format/esm-require/webpack.config.js b/test/build/config-format/esm-require/webpack.config.js deleted file mode 100644 index 224ee8485a4..00000000000 --- a/test/build/config-format/esm-require/webpack.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { fileURLToPath } from "url"; -import path from "path"; - -export default { - mode: "development", - entry: "./main.js", - output: { - path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), "dist"), - filename: "foo.bundle.js", - }, -}; diff --git a/test/build/config-format/esm-top-level-await/index.test.js b/test/build/config-format/esm-top-level-await/index.test.js new file mode 100644 index 00000000000..59f39b19680 --- /dev/null +++ b/test/build/config-format/esm-top-level-await/index.test.js @@ -0,0 +1,11 @@ +const { run } = require("../../../utils/test-utils"); + +describe("webpack cli", () => { + it("should support mjs config format using `require`", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "webpack.config.mjs"]); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + }); +}); diff --git a/test/build/config-format/esm-require-await/main.js b/test/build/config-format/esm-top-level-await/main.js similarity index 100% rename from test/build/config-format/esm-require-await/main.js rename to test/build/config-format/esm-top-level-await/main.js diff --git a/test/build/config-format/esm-require-await/webpack.config.js b/test/build/config-format/esm-top-level-await/webpack.config.mjs similarity index 62% rename from test/build/config-format/esm-require-await/webpack.config.js rename to test/build/config-format/esm-top-level-await/webpack.config.mjs index 44d22682863..5bc8a2105fd 100644 --- a/test/build/config-format/esm-require-await/webpack.config.js +++ b/test/build/config-format/esm-top-level-await/webpack.config.mjs @@ -1,6 +1,7 @@ -import { fileURLToPath } from "url"; -import path from "path"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +// eslint-disable-next-line unicorn/no-unnecessary-await const mode = await "development"; export default { diff --git a/test/build/config-format/typescript-mjs-using-nodejs/main.ts b/test/build/config-format/typescript-auto/main.ts similarity index 100% rename from test/build/config-format/typescript-mjs-using-nodejs/main.ts rename to test/build/config-format/typescript-auto/main.ts diff --git a/test/build/config-format/typescript-ts-node-loader/package.json b/test/build/config-format/typescript-auto/package.json similarity index 70% rename from test/build/config-format/typescript-ts-node-loader/package.json rename to test/build/config-format/typescript-auto/package.json index 2921f73c914..c49ae366fdc 100644 --- a/test/build/config-format/typescript-ts-node-loader/package.json +++ b/test/build/config-format/typescript-auto/package.json @@ -1,5 +1,4 @@ { - "type": "module", "engines": { "node": ">=18.12.0" } diff --git a/test/build/config-format/typescript-auto/typescript.test.mjs b/test/build/config-format/typescript-auto/typescript.test.mjs new file mode 100644 index 00000000000..c6e1792d7d2 --- /dev/null +++ b/test/build/config-format/typescript-auto/typescript.test.mjs @@ -0,0 +1,74 @@ +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { run } from "../../../utils/test-utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +describe("typescript configuration", () => { + it("should support typescript configuration (Node.js build-in support)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + // Fallback to `ts-node/esm` for old Node.js versions + nodeOptions: + major >= 22 + ? [] + : [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ], + }); + + if (major >= 22) { + // No `type` in `the package.json` but Node.js support `require` ECMA modules + expect(stderr).toContain( + "Reparsing as ES module because module syntax was detected. This incurs a performance overhead.", + ); + } else { + expect(stderr).toBeFalsy(); + } + + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript configuration (Node.js build-in support) with `mts` extension", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.mts"], { + // Fallback to `ts-node/esm` for old Node.js versions + nodeOptions: + major >= 22 + ? [] + : [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript configuration (Node.js build-in support) with `cts` extension", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.cts"], { + // Fallback to `ts-node/esm` for old Node.js versions + nodeOptions: + major >= 22 + ? [] + : [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); +}); diff --git a/test/build/config-format/typescript-cjs-using-nodejs/webpack.config.ts b/test/build/config-format/typescript-auto/webpack.config.cts similarity index 100% rename from test/build/config-format/typescript-cjs-using-nodejs/webpack.config.ts rename to test/build/config-format/typescript-auto/webpack.config.cts diff --git a/test/build/config-format/typescript-mjs-using-nodejs/webpack.config.ts b/test/build/config-format/typescript-auto/webpack.config.mts similarity index 100% rename from test/build/config-format/typescript-mjs-using-nodejs/webpack.config.ts rename to test/build/config-format/typescript-auto/webpack.config.mts diff --git a/test/build/config-format/typescript-ts-node-loader/webpack.config.ts b/test/build/config-format/typescript-auto/webpack.config.ts similarity index 100% rename from test/build/config-format/typescript-ts-node-loader/webpack.config.ts rename to test/build/config-format/typescript-auto/webpack.config.ts diff --git a/test/build/config-format/typescript-cjs-using-nodejs/typescript.test.mjs b/test/build/config-format/typescript-cjs-using-nodejs/typescript.test.mjs deleted file mode 100644 index 6cf4dd1c201..00000000000 --- a/test/build/config-format/typescript-cjs-using-nodejs/typescript.test.mjs +++ /dev/null @@ -1,26 +0,0 @@ -import { existsSync } from "node:fs"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; -import { run } from "../../../utils/test-utils.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -describe("webpack cli", () => { - it("should support typescript esnext file", async () => { - const [major] = process.versions.node.split(".").map(Number); - const { exitCode, stderr, stdout } = await run( - __dirname, - ["-c", "./webpack.config.ts", "--disable-interpret"], - { - // Fallback to `ts-node/esm` for old Node.js versions - nodeOptions: major >= 24 ? [] : ["--require=ts-node/register"], - }, - ); - - expect(stderr).toBeFalsy(); // Deprecation warning logs on stderr - expect(stdout).toBeTruthy(); - expect(exitCode).toBe(0); - expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); - }); -}); diff --git a/test/build/config-format/typescript-ts-node-loader/main.ts b/test/build/config-format/typescript-cjs/main.ts similarity index 100% rename from test/build/config-format/typescript-ts-node-loader/main.ts rename to test/build/config-format/typescript-cjs/main.ts diff --git a/test/build/config-format/typescript-cjs-using-nodejs/package.json b/test/build/config-format/typescript-cjs/package.json similarity index 100% rename from test/build/config-format/typescript-cjs-using-nodejs/package.json rename to test/build/config-format/typescript-cjs/package.json diff --git a/test/build/config-format/typescript-cjs-using-nodejs/tsconfig.json b/test/build/config-format/typescript-cjs/tsconfig.json similarity index 100% rename from test/build/config-format/typescript-cjs-using-nodejs/tsconfig.json rename to test/build/config-format/typescript-cjs/tsconfig.json diff --git a/test/build/config-format/typescript-cjs/typescript.test.mjs b/test/build/config-format/typescript-cjs/typescript.test.mjs new file mode 100644 index 00000000000..b578226de94 --- /dev/null +++ b/test/build/config-format/typescript-cjs/typescript.test.mjs @@ -0,0 +1,93 @@ +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { run } from "../../../utils/test-utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +describe("typescript commonjs configuration", () => { + it("should support typescript commonjs configuration (Node.js build-in support)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + // Fallback to `ts-node/register` for old Node.js versions + nodeOptions: major >= 22 ? [] : ["--require=ts-node/register"], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript commonjs configuration (using `--require=ts-node/register`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + nodeOptions: [ + "--require=ts-node/register", + // Disable typescript strip types for tests + ...(major >= 22 ? ["--no-experimental-strip-types"] : []), + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript commonjs configuration (using `--require=ts-node/register` and disable `interpret`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run( + __dirname, + ["-c", "./webpack.config.ts", "--disable-interpret"], + { + nodeOptions: [ + "--require=ts-node/register", + // Disable typescript strip types for tests + ...(major >= 22 ? ["--no-experimental-strip-types"] : []), + ], + }, + ); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript commonjs configuration (using `--import=ts-node/register` and disable `interpret`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run( + __dirname, + ["-c", "./webpack.config.ts", "--disable-interpret"], + { + nodeOptions: [ + "--import=ts-node/register", + // Disable typescript strip types for tests + ...(major >= 22 ? ["--no-experimental-strip-types"] : []), + ], + }, + ); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript commonjs configuration (using `interpret`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + nodeOptions: [ + // Disable typescript strip types for tests + ...(major >= 22 ? ["--no-experimental-strip-types"] : []), + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); +}); diff --git a/test/build/config-format/typescript-ts-node-require/webpack.config.ts b/test/build/config-format/typescript-cjs/webpack.config.ts similarity index 68% rename from test/build/config-format/typescript-ts-node-require/webpack.config.ts rename to test/build/config-format/typescript-cjs/webpack.config.ts index f53400f9b25..586bd1b1cf3 100644 --- a/test/build/config-format/typescript-ts-node-require/webpack.config.ts +++ b/test/build/config-format/typescript-cjs/webpack.config.ts @@ -1,4 +1,4 @@ -import * as path from "node:path"; +const path = require("node:path"); /* eslint-disable no-useless-concat */ @@ -8,9 +8,9 @@ const config = { mode, entry: "./main.ts", output: { - path: path.resolve(__dirname, "dist"), + path: path.resolve("dist"), filename: "foo.bundle.js", }, }; -export = config; +module.exports = config; diff --git a/test/build/config-format/typescript-mjs-using-nodejs/typescript.test.mjs b/test/build/config-format/typescript-mjs-using-nodejs/typescript.test.mjs deleted file mode 100644 index 33638220420..00000000000 --- a/test/build/config-format/typescript-mjs-using-nodejs/typescript.test.mjs +++ /dev/null @@ -1,29 +0,0 @@ -import { existsSync } from "node:fs"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; -import { run } from "../../../utils/test-utils.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -describe("webpack cli", () => { - it("should support typescript esnext file", async () => { - const [major] = process.versions.node.split(".").map(Number); - const { exitCode, stderr, stdout } = await run( - __dirname, - ["-c", "./webpack.config.ts", "--disable-interpret"], - { - env: { - NODE_NO_WARNINGS: 1, - }, - // Fallback to `ts-node/esm` for old Node.js versions - nodeOptions: major >= 24 ? [] : ["--experimental-loader=ts-node/esm"], - }, - ); - - expect(stderr).toBeFalsy(); // Deprecation warning logs on stderr - expect(stdout).toBeTruthy(); - expect(exitCode).toBe(0); - expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); - }); -}); diff --git a/test/build/config-format/typescript-using-nodejs/main.ts b/test/build/config-format/typescript-mjs/main.ts similarity index 100% rename from test/build/config-format/typescript-using-nodejs/main.ts rename to test/build/config-format/typescript-mjs/main.ts diff --git a/test/build/config-format/babel-esm/package.json b/test/build/config-format/typescript-mjs/package.json similarity index 100% rename from test/build/config-format/babel-esm/package.json rename to test/build/config-format/typescript-mjs/package.json diff --git a/test/build/config-format/typescript-mjs-using-nodejs/tsconfig.json b/test/build/config-format/typescript-mjs/tsconfig.json similarity index 100% rename from test/build/config-format/typescript-mjs-using-nodejs/tsconfig.json rename to test/build/config-format/typescript-mjs/tsconfig.json diff --git a/test/build/config-format/typescript-mjs/typescript.test.mjs b/test/build/config-format/typescript-mjs/typescript.test.mjs new file mode 100644 index 00000000000..03acf17b9a9 --- /dev/null +++ b/test/build/config-format/typescript-mjs/typescript.test.mjs @@ -0,0 +1,101 @@ +import { existsSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { run } from "../../../utils/test-utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +describe("typescript ecma modules configuration", () => { + it("should support typescript ecma modules configuration (Node.js build-in support)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + // Fallback to `ts-node/esm` for old Node.js versions + nodeOptions: + major >= 22 + ? [] + : [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript ecma modules configuration (Node.js build-in support using `--experimental-transform-types`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + // Fallback to `ts-node/esm` for old Node.js versions + nodeOptions: + major >= 22 + ? ["--experimental-transform-types", "--no-warnings"] + : [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript ecma modules configuration (using `--import` and prefer `--import` over built-in feature)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + // Fallback to `ts-node/esm` for old Node.js versions + nodeOptions: + major >= 22 + ? [] + : [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript ecma modules configuration (using `--import=ts-node/esm`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + nodeOptions: [ + "--no-deprecation", + "--import=data:text/javascript,import { register } from 'node:module'; import { pathToFileURL } from 'node:url'; register('ts-node/esm', pathToFileURL('./'));", + ...(major >= 22 ? ["--no-experimental-strip-types"] : []), + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); + + it("should support typescript ecma modules configuration (using `--experimental-loader=ts-node/esm`)", async () => { + const [major] = process.versions.node.split(".").map(Number); + const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + env: { + NODE_NO_WARNINGS: 1, + }, + nodeOptions: [ + "--no-deprecation", + "--experimental-loader=ts-node/esm", + ...(major >= 22 ? ["--no-experimental-strip-types"] : []), + ], + }); + + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); + }); +}); diff --git a/test/build/config-format/typescript-using-nodejs/webpack.config.ts b/test/build/config-format/typescript-mjs/webpack.config.ts similarity index 100% rename from test/build/config-format/typescript-using-nodejs/webpack.config.ts rename to test/build/config-format/typescript-mjs/webpack.config.ts diff --git a/test/build/config-format/typescript-ts-node-loader/tsconfig.json b/test/build/config-format/typescript-ts-node-loader/tsconfig.json deleted file mode 100644 index e0ba2dc7a46..00000000000 --- a/test/build/config-format/typescript-ts-node-loader/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "module": "esnext", - "allowSyntheticDefaultImports": true - } -} diff --git a/test/build/config-format/typescript-ts-node-loader/typescript.test.mjs b/test/build/config-format/typescript-ts-node-loader/typescript.test.mjs deleted file mode 100644 index 8653ad72ae8..00000000000 --- a/test/build/config-format/typescript-ts-node-loader/typescript.test.mjs +++ /dev/null @@ -1,27 +0,0 @@ -import { existsSync } from "node:fs"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; -import { run } from "../../../utils/test-utils.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -describe("webpack cli", () => { - it("should support typescript esnext file", async () => { - const [major, minor] = process.versions.node.split(".").map(Number); - const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { - env: { - NODE_NO_WARNINGS: 1, - }, - nodeOptions: - major >= 22 && minor >= 6 - ? ["--no-experimental-strip-types", "--experimental-loader=ts-node/esm"] - : ["--experimental-loader=ts-node/esm"], - }); - - expect(stderr).toBeFalsy(); // Deprecation warning logs on stderr - expect(stdout).toBeTruthy(); - expect(exitCode).toBe(0); - expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); - }); -}); diff --git a/test/build/config-format/typescript-ts-node-require/main.ts b/test/build/config-format/typescript-ts-node-require/main.ts deleted file mode 100644 index 41d13d1a9a1..00000000000 --- a/test/build/config-format/typescript-ts-node-require/main.ts +++ /dev/null @@ -1 +0,0 @@ -console.log("Main typescript file"); diff --git a/test/build/config-format/typescript-ts-node-require/tsconfig.json b/test/build/config-format/typescript-ts-node-require/tsconfig.json deleted file mode 100644 index 391488ab17f..00000000000 --- a/test/build/config-format/typescript-ts-node-require/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/test/build/config-format/typescript-ts-node-require/typescript.test.js b/test/build/config-format/typescript-ts-node-require/typescript.test.js deleted file mode 100644 index 4041596d9fd..00000000000 --- a/test/build/config-format/typescript-ts-node-require/typescript.test.js +++ /dev/null @@ -1,21 +0,0 @@ -const { existsSync } = require("node:fs"); -const { resolve } = require("node:path"); -const { run } = require("../../../utils/test-utils"); - -describe("webpack cli", () => { - it("should support typescript file", async () => { - const [major, minor] = process.versions.node.split(".").map(Number); - const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { - env: { NODE_NO_WARNINGS: 1 }, - nodeOptions: - major >= 22 && minor >= 6 - ? ["--no-experimental-strip-types", "--require=ts-node/register"] - : ["--require=ts-node/register"], - }); - - expect(stderr).toBeFalsy(); - expect(stdout).toBeTruthy(); - expect(exitCode).toBe(0); - expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); - }); -}); diff --git a/test/build/config-format/typescript-using-nodejs/package.json b/test/build/config-format/typescript-using-nodejs/package.json deleted file mode 100644 index 2921f73c914..00000000000 --- a/test/build/config-format/typescript-using-nodejs/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "module", - "engines": { - "node": ">=18.12.0" - } -} diff --git a/test/build/config-format/typescript-using-nodejs/tsconfig.json b/test/build/config-format/typescript-using-nodejs/tsconfig.json deleted file mode 100644 index 3cf557d8735..00000000000 --- a/test/build/config-format/typescript-using-nodejs/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "target": "esnext", - "allowImportingTsExtensions": true, - "rewriteRelativeImportExtensions": true, - "module": "esnext" - } -} diff --git a/test/build/config-format/typescript-using-nodejs/typescript.test.mjs b/test/build/config-format/typescript-using-nodejs/typescript.test.mjs deleted file mode 100644 index 33638220420..00000000000 --- a/test/build/config-format/typescript-using-nodejs/typescript.test.mjs +++ /dev/null @@ -1,29 +0,0 @@ -import { existsSync } from "node:fs"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; -import { run } from "../../../utils/test-utils.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -describe("webpack cli", () => { - it("should support typescript esnext file", async () => { - const [major] = process.versions.node.split(".").map(Number); - const { exitCode, stderr, stdout } = await run( - __dirname, - ["-c", "./webpack.config.ts", "--disable-interpret"], - { - env: { - NODE_NO_WARNINGS: 1, - }, - // Fallback to `ts-node/esm` for old Node.js versions - nodeOptions: major >= 24 ? [] : ["--experimental-loader=ts-node/esm"], - }, - ); - - expect(stderr).toBeFalsy(); // Deprecation warning logs on stderr - expect(stdout).toBeTruthy(); - expect(exitCode).toBe(0); - expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); - }); -}); From c5efdffde7147d589a91fe15f62b8e89159a6083 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Thu, 5 Mar 2026 18:27:59 +0300 Subject: [PATCH 2/4] ci: debug --- packages/webpack-cli/src/webpack-cli.ts | 5 +++++ test/build/config-format/typescript-cjs/typescript.test.mjs | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/webpack-cli/src/webpack-cli.ts b/packages/webpack-cli/src/webpack-cli.ts index 977f8904ab8..91ee8441084 100644 --- a/packages/webpack-cli/src/webpack-cli.ts +++ b/packages/webpack-cli/src/webpack-cli.ts @@ -2199,6 +2199,11 @@ class WebpackCLI { throw err; } + if (process.env.WEBPACK_DEBUG_CONFIGURATION_LOADING) { + this.logger.error(loadingError); + this.logger.error(err); + } + throw new ConfigurationLoadingError([loadingError, err]); } } diff --git a/test/build/config-format/typescript-cjs/typescript.test.mjs b/test/build/config-format/typescript-cjs/typescript.test.mjs index b578226de94..14da523522e 100644 --- a/test/build/config-format/typescript-cjs/typescript.test.mjs +++ b/test/build/config-format/typescript-cjs/typescript.test.mjs @@ -76,9 +76,12 @@ describe("typescript commonjs configuration", () => { expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); }); - it("should support typescript commonjs configuration (using `interpret`)", async () => { + it.only("should support typescript commonjs configuration (using `interpret`)", async () => { const [major] = process.versions.node.split(".").map(Number); const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { + env: { + WEBPACK_DEBUG_CONFIGURATION_LOADING: true, + }, nodeOptions: [ // Disable typescript strip types for tests ...(major >= 22 ? ["--no-experimental-strip-types"] : []), From b6f6d5f03e5e409655ac51e10c841f284ceea44a Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Thu, 5 Mar 2026 19:02:45 +0300 Subject: [PATCH 3/4] ci: debug --- test/build/config-format/typescript-cjs/typescript.test.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/build/config-format/typescript-cjs/typescript.test.mjs b/test/build/config-format/typescript-cjs/typescript.test.mjs index 14da523522e..9561ddfd58f 100644 --- a/test/build/config-format/typescript-cjs/typescript.test.mjs +++ b/test/build/config-format/typescript-cjs/typescript.test.mjs @@ -88,6 +88,9 @@ describe("typescript commonjs configuration", () => { ], }); + console.log(stderr); + console.log(stdout); + expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); expect(exitCode).toBe(0); From 6c542f354bbfb0a66d62c5dec52b8d4e86d2f148 Mon Sep 17 00:00:00 2001 From: alexander-akait Date: Thu, 5 Mar 2026 19:41:04 +0300 Subject: [PATCH 4/4] refactor: fix nyc --- .nycrc | 1 + packages/webpack-cli/src/webpack-cli.ts | 5 ----- .../config-format/typescript-cjs/typescript.test.mjs | 8 +------- test/build/custom-webpack/custom-webpack.test.js | 3 --- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/.nycrc b/.nycrc index 36cd87040de..540462ce0a4 100644 --- a/.nycrc +++ b/.nycrc @@ -2,5 +2,6 @@ "include": ["packages/**"], "reporter": ["html", "json", "cobertura"], "source-map": true, + "hook-require": false, "exclude-after-remap": false } diff --git a/packages/webpack-cli/src/webpack-cli.ts b/packages/webpack-cli/src/webpack-cli.ts index 91ee8441084..977f8904ab8 100644 --- a/packages/webpack-cli/src/webpack-cli.ts +++ b/packages/webpack-cli/src/webpack-cli.ts @@ -2199,11 +2199,6 @@ class WebpackCLI { throw err; } - if (process.env.WEBPACK_DEBUG_CONFIGURATION_LOADING) { - this.logger.error(loadingError); - this.logger.error(err); - } - throw new ConfigurationLoadingError([loadingError, err]); } } diff --git a/test/build/config-format/typescript-cjs/typescript.test.mjs b/test/build/config-format/typescript-cjs/typescript.test.mjs index 9561ddfd58f..b578226de94 100644 --- a/test/build/config-format/typescript-cjs/typescript.test.mjs +++ b/test/build/config-format/typescript-cjs/typescript.test.mjs @@ -76,21 +76,15 @@ describe("typescript commonjs configuration", () => { expect(existsSync(resolve(__dirname, "dist/foo.bundle.js"))).toBeTruthy(); }); - it.only("should support typescript commonjs configuration (using `interpret`)", async () => { + it("should support typescript commonjs configuration (using `interpret`)", async () => { const [major] = process.versions.node.split(".").map(Number); const { exitCode, stderr, stdout } = await run(__dirname, ["-c", "./webpack.config.ts"], { - env: { - WEBPACK_DEBUG_CONFIGURATION_LOADING: true, - }, nodeOptions: [ // Disable typescript strip types for tests ...(major >= 22 ? ["--no-experimental-strip-types"] : []), ], }); - console.log(stderr); - console.log(stdout); - expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); expect(exitCode).toBe(0); diff --git a/test/build/custom-webpack/custom-webpack.test.js b/test/build/custom-webpack/custom-webpack.test.js index a8764c4c1f8..94b2c54486e 100644 --- a/test/build/custom-webpack/custom-webpack.test.js +++ b/test/build/custom-webpack/custom-webpack.test.js @@ -19,9 +19,6 @@ describe("custom-webpack", () => { env: { WEBPACK_PACKAGE: resolve(__dirname, "./custom-webpack.js") }, }); - console.log(stderr); - console.log(stdout); - expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); expect(stdout).toContain("main.js");