The ultimate Node Test Runner + TypeScript + ENV variables guide

RMAG news

This also works in a monorepo 😉

First install dotenv-cli, tsx and glob:

# Use whatever package manager you prefer
pnpm add -D dotenv-cli tsx glob

# For a single app in a monorepo
# pnpm add -F your-app -D dotenv-cli tsx glob

# For the global package.json in a monorepo
# pnpm add -wD dotenv-cli tsx glob

Assuming you want environment variable control, create a .env and a .env.test at the root of the app you want to configure (optional, since dotenv-cli doesn’t throw an error if they don’t exist).

Add this to your app’s package.json:

“scripts”: {
//…
“test”: “dotenv -e .env -e env.test — glob -c tsx –test –test-reporter spec ./test/**/*.test.ts,
“build”: “tsc -p tsconfig.build.json”,

What that test script does is load your .env and .env.test files (the latter overwrites the first in case of conflict), then asks glob to process the “./test/**/*.test.ts” (which will load all Typescript files in the ./test folder ending in .test.ts) and runs the tests via tsx and with a more human-readable output (–test-reporter spec). This last step is equivalent to node –test –import tsx.

Finally, adapt your tsconfig.json to include your tests if you want decent imports, linting and others (in my case I had to split my tsconfig into 2: tsconfig.json and tsconfig.build.json, both in the root folder of the app):

// tsconfig.json
{
“extends”: “../../tsconfig.json”, // Since I work in a monorepo, this one contains all generic compiler options. You can write them in this file if you prefer
“compilerOptions”: { // These are for shorter, non-relative imports in tests. Completely optional
“baseUrl”: “./”,
“paths”: {
“@src/*”: [“./src/*”],
},
“noEmit”: true, // Avoid compiling by mistake
},
“include”: [“./src/**/*”, “./test/**/*”], // Important so tests also benefit from TS support
}

// tsconfig.build.json
{
“extends”: “./tsconfig.json”, // The file above. You can also just extend the base `tsconfig.json` (in the root of the monorepo) instead, adding `include: [ “./src/**/*”]`, or write the `compilerOptions` here
“compilerOptions”: {
“noEmit”: false,
“outDir”: “./dist”,
},
“exclude”: [ // This way we avoid compiling tests into JS
“**/*.spec.ts”,
“**/*.test.ts”
]
}

And that should be it, really. Hope it is of help when setting up your TypeScript testing environment!

For more information, check this GitHub issue

Leave a Reply

Your email address will not be published. Required fields are marked *