Skip to content

Instantly share code, notes, and snippets.

@jasonk
Last active June 4, 2022 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasonk/8616825033ba94cc77840c8c872497d9 to your computer and use it in GitHub Desktop.
Save jasonk/8616825033ba94cc77840c8c872497d9 to your computer and use it in GitHub Desktop.
IstanbulJS + Babel + TypeScript + ESM workaround

This works around an issue where using Istanbul with the noop instrumenter means it will try to parse your code with a hard-coded Babel config that may not work (especially if the code it's trying to parse is TypeScript).

This kludges the problem away by using patch-package in a post-install script to patch istanbul-lib-instrument to look for an environment variable pointing to your Babel config file, and a one-line patch to nyc to make it pass the filename when calling the patched functions in istanbul-lib-instrment (otherwise it will fail if your babel config includes overrides).

To use this, setup patch-package as shown in their README, then make a patches directory in your repo and drop these two patch files into it. Then just running yarn (or npm install) should be enough to do the patching. Then you just have to make sure that $ISTANBUL_BABEL_CONFIG is set to the path to your babel config file when you run your tests.

TL;DR:

yarn add -DW patch-package
jq '.scripts.postinstall = "patch-package"' package.json | sponge package.json
mkdir patches
curl -LO https://gist.github.com/jasonk/.../istanbul-lib-instrument+4.0.3.patch
curl -LO https://gist.github.com/jasonk/.../nyc+15.1.0.patch
# (Get the right URLs by right-clicking on the "Raw" buttons for each file below)
cd ..
yarn
export ISTANBUL_BABEL_CONFIG="$(realpath -P ./babel.config.js)"
# now you can run your tests or whatever...

Note that the patch files have package version embedded in them, so these patches will only work with those specific versions of the packages they patch.

diff --git a/node_modules/istanbul-lib-instrument/dist/read-coverage.js b/node_modules/istanbul-lib-instrument/dist/read-coverage.js
index cb95c28..33d3090 100644
--- a/node_modules/istanbul-lib-instrument/dist/read-coverage.js
+++ b/node_modules/istanbul-lib-instrument/dist/read-coverage.js
@@ -11,7 +11,7 @@ var _schema = require("@istanbuljs/schema");
var _constants = require("./constants");
-function getAst(code) {
+function getAst(code, filename) {
if (typeof code === 'object' && typeof code.type === 'string') {
// Assume code is already a babel ast.
return code;
@@ -21,6 +21,13 @@ function getAst(code) {
throw new Error('Code must be a string');
} // Parse as leniently as possible
+ if ( process.env.ISTANBUL_BABEL_CONFIG ) {
+ return (0, _core.parseSync)(code, {
+ babelrc: false,
+ configFile: process.env.ISTANBUL_BABEL_CONFIG,
+ filename,
+ });
+ }
return (0, _core.parseSync)(code, {
babelrc: false,
@@ -35,8 +42,8 @@ function getAst(code) {
});
}
-function readInitialCoverage(code) {
- const ast = getAst(code);
+function readInitialCoverage(code, filename) {
+ const ast = getAst(code, filename);
let covScope;
(0, _core.traverse)(ast, {
ObjectProperty(path) {
diff --git a/node_modules/nyc/lib/instrumenters/noop.js b/node_modules/nyc/lib/instrumenters/noop.js
index b0c9f70..91dbfdd 100644
--- a/node_modules/nyc/lib/instrumenters/noop.js
+++ b/node_modules/nyc/lib/instrumenters/noop.js
@@ -5,7 +5,7 @@ function NOOP () {
return {
instrumentSync (code, filename) {
- const extracted = readInitialCoverage(code)
+ const extracted = readInitialCoverage(code, filename)
if (extracted) {
this.fileCoverage = extracted.coverageData
} else {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment