The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/docs/coverage.md

4.6 KiB

Code Coverage

This document explains how code coverage instrumentation works in Rocket.Chat's build and CI pipeline.

Overview

Coverage is collected during E2E test runs (API, UI, Livechat) to measure how much of the server-side code is exercised by tests. The instrumentation uses Istanbul-compatible tooling, which injects counters (__coverage__) into the compiled code at build time.

Architecture

The coverage pipeline has three components:

  1. Build-time instrumentation - injects coverage counters into the code during Meteor build
  2. Runtime collection - the rocketchat:coverage Meteor package collects __coverage__ data on process exit
  3. CI reporting - test workflows merge coverage data and upload reports
Build (SWC + plugin)  -->  Run tests  -->  Process exit triggers report  -->  Merge & upload

Build-time instrumentation

Modern build stack (SWC)

Rocket.Chat uses Meteor's modern build stack with SWC as the transpiler. For coverage builds, the swc-plugin-coverage-instrument plugin is injected into .swcrc at build time.

This is configured in .github/actions/meteor-build/action.yml:

env:
  BABEL_ENV: ${{ inputs.type }}  # "production" or "coverage"

When BABEL_ENV=coverage, the build script:

  1. Adds rocketchat:coverage to .meteor/packages
  2. Injects swc-plugin-coverage-instrument into .swcrc via a node script:
const swcrc = JSON.parse(fs.readFileSync('./apps/meteor/.swcrc', 'utf8'));
swcrc.jsc.experimental = swcrc.jsc.experimental || {};
swcrc.jsc.experimental.plugins = swcrc.jsc.experimental.plugins || [];
swcrc.jsc.experimental.plugins.push(['swc-plugin-coverage-instrument', {}]);
fs.writeFileSync('./apps/meteor/.swcrc', JSON.stringify(swcrc, null, 2) + '\n');

This approach ensures the same build pipeline (SWC) is used for both regular and coverage builds, avoiding behavioral differences between build modes.

Legacy build stack (Babel)

Before the modern build stack, coverage was handled via babel-plugin-istanbul configured in .babelrc:

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

This section is still present in .babelrc as a fallback for files that fall back to Babel compilation (e.g., SWC-incompatible code).

Runtime collection: rocketchat:coverage

The rocketchat:coverage Meteor package (apps/meteor/packages/rocketchat-coverage/) is only added to the build during coverage runs. It:

  1. Registers a process.on('exit') handler
  2. Reads globalThis['__coverage__'] (populated by the instrumentation)
  3. Generates a coverage report using istanbul-lib-coverage and istanbul-reports

Configuration via environment variables:

Variable Description Example
COVERAGE_DIR Output directory for reports /tmp/coverage/api
COVERAGE_FILE_NAME Report filename api-1.json
COVERAGE_REPORTER Istanbul reporter format json, lcov

CI workflow

Coverage is collected in the ci-test-e2e.yml workflow:

  1. Build: meteor-build action runs with type: coverage, producing a Docker image with instrumented code
  2. Test: E2E tests run against the instrumented server. On each test shard:
    • COVERAGE_DIR, COVERAGE_FILE_NAME, and COVERAGE_REPORTER are set
    • When the Rocket.Chat process exits after tests, the coverage plugin writes a JSON report
  3. Merge: nyc merge combines per-shard JSON reports into a single coverage file
  4. Upload: Coverage data is uploaded to Codecov

Local development

To build with coverage locally:

cd apps/meteor

# Inject the SWC coverage plugin into .swcrc
node -e "
  const fs = require('fs');
  const swcrc = JSON.parse(fs.readFileSync('.swcrc', 'utf8'));
  swcrc.jsc.experimental = { plugins: [['swc-plugin-coverage-instrument', {}]] };
  fs.writeFileSync('.swcrc', JSON.stringify(swcrc, null, 2));
"

# Add the coverage package
echo -e "rocketchat:coverage\n" >> .meteor/packages

# Set env vars and run
COVERAGE_DIR=/tmp/coverage COVERAGE_FILE_NAME=local.json COVERAGE_REPORTER=lcov yarn dev

Remember to restore .swcrc and .meteor/packages after testing.

Dependencies

Package Purpose
swc-plugin-coverage-instrument SWC plugin for Istanbul-compatible instrumentation
istanbul-lib-coverage Coverage map creation (used by rocketchat:coverage)
istanbul-lib-report Report context creation
istanbul-reports Report formatters (json, lcov, etc.)