We’re using UVU as the test runner for packages and applications. UVU works nicely in CommonJS projects using plain JavaScript and also with TypeScript using a require hook.
We used the ts-node/register
hook with UVU, but that one doesn't work anymore when migrating your code from CommonJS to ESM. With ESM and TypeScript, you need an import hook, related to the import
syntax used in ESM. And UVU doesn't support import hooks at this point.
Yet, you can still run your TypeScript tests with UVU’s test runner. This tutorial shows you how!
UVU Series Overview
- Run Tests with TypeScript and ESM
The Problem: ESM Wants import
Instead of require
Testing your CommonJS TypeScript code with UVU worked fine when using a require hook. A common require hook is ts-node/register
. Don’t worry if you’re using another require hook in your project: it’s fine if it’s working:
{
"name": "app-name",
"type": "commonjs",
"devDependencies": {
"ts-node": "~10.9.1",
"typescript": "~5.2.2",
"uvu": "~0.5.6"
},
"scripts": {
"start": "ts-node server.ts",
"test": "uvu -r ts-node/register"
}
}
You probably receive an error message like the following when migrating your code from CommonJS to ESM. The used ts-node/register
hook isn’t working anymore, you’re receiving an error related to require() of ES modules is not supported
:
$ npm test
> uvu -r ts-node/register
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/marcus/Projects/supercharge/superchargejs.com/test/show-docs.ts
require() of ES modules is not supported.
require() of /Users/marcus/Projects/supercharge/superchargejs.com/test/show-docs.ts from /Users/marcus/Projects/supercharge/superchargejs.com/node_modules/uvu/run/index.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules.
Instead change the requiring code to use import(), or remove "type": "module" from /Users/marcus/Projects/supercharge/superchargejs.com/package.json.
at createErrRequireEsm (/Users/marcus/Projects/supercharge/superchargejs.com/node_modules/ts-node/dist-raw/node-internal-errors.js:46:15)
at assertScriptCanLoadAsCJS (/Users/marcus/Projects/supercharge/superchargejs.com/node_modules/ts-node/dist-raw/node-internal-modules-cjs-loader.js:584:11)
…
That error is correct. The used ts-node/register
hook for on-the-fly TypeScript compilation isn’t working with ESM. Let’s make it work!
Run UVU Tests with TypeScript and ESM
We used ts-node
to run our TypeScript code while being CommonJS code. We expected there’s ESM support when using ts-node
, too. Yet, the ts-node/esm
import hook isn’t working as expected in ts-node 10.9.1. There’s an open GitHub issue for that.
If ts-node/esm
isn’t working, let’s find another import hook so that our TypeScript code with ESM works fine. There’s tsx, a tool to enhance Node.js supporting TypeScript and ESM with the help of esbuild.
tsx
comes with a command line interface allowing you to run TypeScript scripts. It also comes with an import hook. Here are two NPM scripts running the test suite:
1. using tsx
directly to run the UVU executable
2. using node
with the tsx
import hook running the UVU executable
Both ways are fine and run the test suite of TypeScript files in an ESM project:
{
"name": "app-name",
"type": "module",
"devDependencies": {
"tsx": "~4.3.0",
"typescript": "~5.2.2",
"uvu": "~0.5.6"
},
"scripts": {
"start": "tsx server.ts",
"test": "tsx ./node_modules/uvu/bin.js",
"test:alt": "node --import tsx ./node_modules/uvu/bin.js",
}
}
That’s it. UVU now processes the test files correctly:
$ npm test
> supercharge-homepage@2.0.0 test
> c8 tsx ./node_modules/uvu/bin.js
test/show-docs.ts
• • • • (4 / 4)
Enjoy testing your TypeScript test files in an ESM project with UVU!