Comprehensive JavaScript code coverage tool that computes statement, line, function and branch coverage with module loader hooks for transparent instrumentation
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Report generation creates coverage reports in various formats including HTML, LCOV, text, and JSON. Istanbul provides both high-level Reporter class for multiple formats and individual Report classes for specific formats.
High-level reporter for generating multiple coverage report formats from collected coverage data.
/**
* Creates a multi-format reporter
* @param {Configuration} cfg - Configuration object (optional, uses default if falsy)
* @param {string} dir - Directory to write reports (optional, uses config default if falsy)
*/
class Reporter {
constructor(cfg?: Configuration, dir?: string);
/**
* Adds a report format to be generated
* @param {string} fmt - Report format name (e.g., 'html', 'lcov', 'text')
*/
add(fmt: string): void;
/**
* Adds multiple report formats to be generated
* @param {string[]} fmts - Array of report format names
*/
addAll(fmts: string[]): void;
/**
* Writes all configured reports
* @param {Collector} collector - Collector containing coverage data
* @param {boolean} sync - Whether to write synchronously
* @param {Function} callback - Callback function called when all reports are written
*/
write(collector: Collector, sync: boolean, callback?: () => void): void;
}Usage Examples:
const { Reporter, Collector } = require('istanbul');
// Basic usage
const reporter = new Reporter();
reporter.addAll(['text', 'html', 'lcov']);
const collector = new Collector();
// ... add coverage data to collector
reporter.write(collector, true, () => {
console.log('All reports generated successfully!');
});
// With custom configuration and directory
const config = require('istanbul').config.loadFile('.istanbul.yml');
const reporter2 = new Reporter(config, './coverage-output');
reporter2.add('html');
reporter2.add('json-summary');
reporter2.write(collector, false, callback);Factory for creating individual report instances and accessing available report types.
/**
* Factory class for creating individual reports
*/
class Report {
/**
* Creates a report of the specified type
* @param {string} type - Report type name
* @param {Object} opts - Report-specific options
* @returns {Report} Report instance
*/
static create(type: string, opts?: Object): Report;
/**
* Registers a new report implementation
* @param {Function} constructor - Report constructor function
*/
static register(constructor: Function): void;
/**
* Returns array of available report format names
* @returns {string[]} Available report types
*/
static getReportList(): string[];
/**
* Returns one-line summary of what this report does
* @returns {string} Report synopsis
*/
synopsis(): string;
/**
* Returns default configuration object for this report
* @returns {Object} Default configuration with overrideable keys
*/
getDefaultConfig(): Object;
/**
* Writes the report using coverage data from collector
* @param {Collector} collector - Collector with coverage data
* @param {boolean} sync - Whether to write synchronously
*/
writeReport(collector: Collector, sync?: boolean): void;
}Usage Examples:
// Get available report types
const availableReports = Report.getReportList();
console.log('Available reports:', availableReports);
// Output: ['text', 'text-summary', 'html', 'lcov', 'json', ...]
// Create individual reports
const htmlReport = Report.create('html', {
dir: './html-coverage'
});
const lcovReport = Report.create('lcov', {
file: 'coverage.lcov'
});
// Use individual reports
htmlReport.writeReport(collector, true);
lcovReport.writeReport(collector, true);
// Get report information
console.log('HTML report:', htmlReport.synopsis());
console.log('Default config:', htmlReport.getDefaultConfig());Istanbul includes several built-in report formats:
// Text-based console output with detailed coverage information
const textReport = Report.create('text', {
file: null // null = console output, string = file path
});
// Summary text report with just the totals
const summaryReport = Report.create('text-summary', {
file: null // null = console output
});
// LCOV format output to console
const textLcovReport = Report.create('text-lcov');// HTML report with interactive browsing
const htmlReport = Report.create('html', {
dir: './coverage', // output directory
verbose: true, // include source code
linkMapper: null, // function to map file paths to URLs
subdir: '', // subdirectory within dir
watermarks: { // coverage watermarks for colors
statements: [50, 80],
functions: [50, 80],
branches: [50, 80],
lines: [50, 80]
}
});
// LCOV tracefile format
const lcovReport = Report.create('lcov', {
dir: './coverage',
file: 'lcov.info' // output filename
});
// LCOV format only (no HTML)
const lcovOnlyReport = Report.create('lcovonly', {
file: 'coverage.lcov'
});
// JSON coverage data
const jsonReport = Report.create('json', {
file: 'coverage.json'
});
// JSON summary metrics only
const jsonSummaryReport = Report.create('json-summary', {
file: 'coverage-summary.json'
});// Clover XML format (for Jenkins, etc.)
const cloverReport = Report.create('clover', {
dir: './coverage',
file: 'clover.xml'
});
// Cobertura XML format
const coberturaReport = Report.create('cobertura', {
dir: './coverage',
file: 'cobertura-coverage.xml'
});// TeamCity service messages
const teamcityReport = Report.create('teamcity', {
file: null, // output to console
blockName: null // TeamCity block name
});
// No-op report (for disabling output)
const noneReport = Report.create('none');Each report type accepts specific configuration options:
interface ReportOptions {
/** Output directory for file-based reports */
dir?: string;
/** Output filename (for single-file reports) */
file?: string;
/** Coverage watermarks for color coding */
watermarks?: {
statements: [number, number];
functions: [number, number];
branches: [number, number];
lines: [number, number];
};
/** Whether to include verbose information */
verbose?: boolean;
/** Custom subdirectory within main output directory */
subdir?: string;
/** Function to map file paths to URLs (for HTML reports) */
linkMapper?: (filePath: string) => string;
/** TeamCity block name (for teamcity reports) */
blockName?: string;
}You can register custom report implementations:
class CustomReport {
constructor(opts) {
this.opts = opts || {};
}
synopsis() {
return 'Custom coverage report format';
}
getDefaultConfig() {
return { file: 'custom-coverage.txt' };
}
writeReport(collector, sync) {
const coverage = collector.getFinalCoverage();
// ... custom report generation logic
}
}
// Register the custom report
Report.register(CustomReport);
// Use it
const customReport = Report.create('CustomReport', {
outputPath: './custom-output'
});Coverage watermarks determine color coding in reports:
const reporter = new Reporter(null, './coverage');
// Configure watermarks for HTML report
reporter.add('html');
const htmlReport = Report.create('html', {
watermarks: {
statements: [70, 90], // Red < 70%, Yellow 70-90%, Green > 90%
branches: [60, 80],
functions: [75, 95],
lines: [65, 85]
}
});// Synchronous writing (blocks until complete)
reporter.write(collector, true, () => {
console.log('Reports written synchronously');
});
// Asynchronous writing (non-blocking)
reporter.write(collector, false, () => {
console.log('Reports written asynchronously');
});try {
const reporter = new Reporter();
reporter.add('html');
reporter.add('invalidformat'); // This will throw
} catch (error) {
console.error('Invalid report format:', error.message);
}
// Handle write errors
reporter.write(collector, true, (error) => {
if (error) {
console.error('Report generation failed:', error);
} else {
console.log('Reports generated successfully');
}
});Common patterns for report generation:
const { Instrumenter, Collector, Reporter } = require('istanbul');
// Complete workflow
function generateCoverageReports() {
// 1. Collect coverage
const collector = new Collector();
collector.add(global.__coverage__);
// 2. Setup reporter
const reporter = new Reporter();
reporter.addAll(['text-summary', 'html', 'lcov']);
// 3. Generate reports
reporter.write(collector, true, () => {
console.log('Coverage reports generated in ./coverage/');
collector.dispose();
});
}
// With error handling
function generateReportsWithErrorHandling() {
try {
const collector = new Collector();
if (global.__coverage__ && Object.keys(global.__coverage__).length > 0) {
collector.add(global.__coverage__);
const reporter = new Reporter();
reporter.addAll(['text', 'html']);
reporter.write(collector, true, (error) => {
if (error) {
console.error('Failed to generate reports:', error);
} else {
console.log('Coverage reports generated successfully');
}
collector.dispose();
});
} else {
console.warn('No coverage data found');
}
} catch (error) {
console.error('Coverage reporting error:', error);
}
}