CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-babel-plugin-istanbul

A Babel plugin that instruments JavaScript code with Istanbul coverage tracking for testing and code coverage analysis

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

babel-plugin-istanbul

babel-plugin-istanbul is a Babel plugin that automatically instruments JavaScript code with Istanbul coverage tracking during compilation. It enables code coverage analysis for ES6+ code by transforming the source code to include coverage counters, making it compatible with testing frameworks like Mocha and Karma.

Package Information

  • Package Name: babel-plugin-istanbul
  • Package Type: npm
  • Language: JavaScript/TypeScript
  • Installation: npm install --save-dev babel-plugin-istanbul

Core Imports

// ESM import (for programmatic usage)
import babelPluginIstanbul from "babel-plugin-istanbul";

// CommonJS (for programmatic usage)
const babelPluginIstanbul = require("babel-plugin-istanbul");

Basic Usage

Babel Configuration

Add the plugin to your .babelrc or babel.config.js in test mode:

{
  "env": {
    "test": {
      "plugins": ["istanbul"]
    }
  }
}

With options:

{
  "env": {
    "test": {
      "plugins": [
        ["istanbul", {
          "exclude": ["**/*.spec.js", "test/**"],
          "useInlineSourceMaps": false
        }]
      ]
    }
  }
}

Programmatic Usage

import babel from "@babel/core";
import babelPluginIstanbul from "babel-plugin-istanbul";

const result = babel.transform(sourceCode, {
  filename: "example.js",
  plugins: [
    [babelPluginIstanbul, {
      include: ["src/**/*.js"],
      exclude: ["src/**/*.test.js"],
      onCover: (filePath, fileCoverage) => {
        console.log(`Instrumented: ${filePath}`);
      }
    }]
  ]
});

Architecture

The plugin operates as a Babel AST visitor that:

  • Configuration Resolution: Loads configuration from plugin options, nyc config, or environment variables
  • File Filtering: Uses test-exclude patterns to determine which files to instrument
  • AST Instrumentation: Wraps the istanbul-lib-instrument programVisitor to inject coverage tracking code
  • Source Map Handling: Preserves and processes source maps for accurate coverage reporting
  • Integration Points: Provides callbacks and works with karma-coverage and nyc

Capabilities

Babel Plugin Export

The main export that creates the Babel plugin for code instrumentation.

/**
 * Creates a Babel plugin that instruments code with Istanbul coverage
 * @param {Object} api - Babel API object
 * @returns {Object} Babel plugin object with visitor pattern
 */
function babelPluginIstanbul(api: BabelAPI): BabelPlugin;

interface BabelPlugin {
  visitor: {
    Program: {
      enter(path: NodePath): void;
      exit(path: NodePath): void;
    };
  };
}

interface BabelAPI {
  types: Object;
  assertVersion(version: number): void;
}

Plugin Configuration Options

Configuration object passed as the second parameter to the plugin:

interface PluginOptions {
  /** Array of glob patterns for files to include */
  include?: string[];
  /** Array of glob patterns for files to exclude */
  exclude?: string[];
  /** Whether to exclude node_modules (default: true) */
  excludeNodeModules?: boolean;
  /** File extensions to consider for instrumentation */
  extension?: string[];
  /** Global variable name for coverage data (default: '__coverage__') */
  coverageVariable?: string;
  /** Scope for coverage variable ('window', 'global', etc.) */
  coverageGlobalScope?: string;
  /** Whether to use function to determine global scope (default: true) */
  coverageGlobalScopeFunc?: boolean;
  /** Whether to use inline source maps (default: true) */
  useInlineSourceMaps?: boolean;
  /** Explicitly provided source map object */
  inputSourceMap?: Object;
  /** Array of class method names to ignore in instrumentation */
  ignoreClassMethods?: string[];
  /** Current working directory for config resolution */
  cwd?: string;
  /** Path to .nycrc configuration file */
  nycrcPath?: string;
  /** Callback executed when a file is instrumented */
  onCover?: (filePath: string, fileCoverage: Object) => void;
}

File Coverage Callback

The onCover callback provides access to coverage data for each instrumented file:

/**
 * Callback executed when a file is instrumented
 * @param {string} filePath - Absolute path to the instrumented file
 * @param {Object} fileCoverage - Istanbul file coverage object
 */
function onCover(filePath: string, fileCoverage: FileCoverage): void;

interface FileCoverage {
  /** Mapping of statement locations */
  statementMap: { [key: string]: Location };
  /** Mapping of function locations */
  fnMap: { [key: string]: FunctionLocation };
  /** Mapping of branch locations */
  branchMap: { [key: string]: BranchLocation };
  /** Statement execution counts */
  s: { [key: string]: number };
  /** Function execution counts */
  f: { [key: string]: number };
  /** Branch execution counts */
  b: { [key: string]: number[] };
}

interface Location {
  start: { line: number; column: number };
  end: { line: number; column: number };
}

interface FunctionLocation extends Location {
  name: string;
  decl: Location;
  loc: Location;
}

interface BranchLocation {
  loc: Location;
  type: string;
  locations: Location[];
}

Integration with Testing Frameworks

Karma Integration

Works automatically with karma-coverage when Babel transpilation is already configured:

// karma.conf.js
module.exports = function(config) {
  config.set({
    preprocessors: {
      'src/**/*.js': ['babel'] // Don't add 'coverage' preprocessor
    },
    coverageReporter: {
      type: 'html',
      dir: 'coverage/'
    }
  });
};

NYC Integration

Configure NYC to not instrument code (plugin handles instrumentation):

{
  "nyc": {
    "sourceMap": false,
    "instrument": false,
    "include": ["src/**/*.js"],
    "exclude": ["src/**/*.test.js"]
  }
}

Configuration Resolution

The plugin resolves configuration from multiple sources in order of precedence:

  1. Plugin Options: Explicit options passed to the plugin
  2. Environment Variables: NYC_CONFIG environment variable
  3. NYC Configuration: .nycrc, .nycrc.json, or package.json nyc section
  4. Default Values: Built-in defaults from @istanbuljs/schema
/**
 * Resolves final configuration from multiple sources
 * @param {Object} opts - Plugin options
 * @returns {Object} Resolved configuration object
 */
function findConfig(opts: PluginOptions): ResolvedConfig;

interface ResolvedConfig extends PluginOptions {
  cwd: string;
  include: string[];
  exclude: string[];
  excludeNodeModules: boolean;
  extension: string[];
  coverageVariable: string;
  useInlineSourceMaps: boolean;
}

Source Map Integration

The plugin handles source maps to maintain coverage accuracy across build steps:

/**
 * Source map options for coverage instrumentation
 */
interface SourceMapOptions {
  /** Whether to use inline source maps from the source code */
  useInlineSourceMaps?: boolean;
  /** Explicitly provided source map object */
  inputSourceMap?: {
    version: number;
    sources: string[];
    names: string[];
    mappings: string;
    sourcesContent?: string[];
  };
}

Usage Examples

Custom Coverage Variable

// babel.config.js
module.exports = {
  env: {
    test: {
      plugins: [
        ["istanbul", {
          coverageVariable: "__MY_COVERAGE__"
        }]
      ]
    }
  }
};

File Filtering

// .babelrc
{
  "env": {
    "test": {
      "plugins": [
        ["istanbul", {
          "include": ["src/**/*.js"],
          "exclude": [
            "src/**/*.test.js",
            "src/**/*.spec.js",
            "src/test-utils/**"
          ]
        }]
      ]
    }
  }
}

Coverage Callback Usage

import babel from "@babel/core";
import babelPluginIstanbul from "babel-plugin-istanbul";

const coverageData = new Map();

babel.transform(code, {
  plugins: [
    [babelPluginIstanbul, {
      onCover: (filePath, fileCoverage) => {
        coverageData.set(filePath, fileCoverage);
        console.log(`Instrumented ${filePath} with ${Object.keys(fileCoverage.statementMap).length} statements`);
      }
    }]
  ]
});

Ignoring Class Methods

// babel.config.js
module.exports = {
  env: {
    test: {
      plugins: [
        ["istanbul", {
          ignoreClassMethods: ["render", "componentDidMount"]
        }]
      ]
    }
  }
};

Browser vs Node.js Configuration

// For browser testing (with window global)
{
  "plugins": [
    ["istanbul", {
      "coverageGlobalScope": "window"
    }]
  ]
}

// For Node.js testing (with global object)
{
  "plugins": [
    ["istanbul", {
      "coverageGlobalScope": "global"
    }]
  ]
}

Error Handling

The plugin handles several error scenarios gracefully:

  • File Resolution Errors: Falls back to original path if realpath resolution fails
  • Configuration Errors: Throws descriptive errors for invalid nyc configuration
  • Instrumentation Skipping: Silently skips files that match exclude patterns
  • Source Map Errors: Continues instrumentation without source maps if parsing fails

Common error patterns:

// Configuration loading error
throw new Error("Failed to load nyc configuration: Invalid JSON in .nycrc");

// File filtering (no error, just skipped)
if (shouldSkip(filePath, nycConfig)) {
  return; // File not instrumented
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/babel-plugin-istanbul@7.0.x
Publish Source
CLI
Badge
tessl/npm-babel-plugin-istanbul badge