or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdenvironment-integration.mdindex.mdplugin-integration.mdtest-runner.mdutilities.md
tile.json

tessl/npm-stryker-mutator--jest-runner

A plugin to use the jest test runner and framework in Stryker, the JavaScript mutation testing framework

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@stryker-mutator/jest-runner@9.1.x

To install, run

npx @tessl/cli install tessl/npm-stryker-mutator--jest-runner@9.1.0

index.mddocs/

StrykerJS Jest Runner

StrykerJS Jest Runner is a plugin that enables the use of Jest as a test runner and framework within Stryker, the JavaScript mutation testing framework. It provides seamless integration between Jest and Stryker, supporting advanced features like per-test coverage analysis, multiple Jest environments, and optimized test execution for mutation testing workflows.

Package Information

  • Package Name: @stryker-mutator/jest-runner
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @stryker-mutator/jest-runner
  • Peer Dependency: @stryker-mutator/core ~9.1.0

Core Imports

import { strykerPlugins, strykerValidationSchema, mixinJestEnvironment } from "@stryker-mutator/jest-runner";

For Jest environment integration:

// These are pre-enhanced Jest environments (CommonJS exports)
// Node.js environment with Stryker integration
const JestEnvironmentNode = require("@stryker-mutator/jest-runner/jest-env/node");

// JSDOM environment with Stryker integration
const JestEnvironmentJsdom = require("@stryker-mutator/jest-runner/jest-env/jsdom");

// JSDOM v16 environment with Stryker integration
const JestEnvironmentJsdomSixteen = require("@stryker-mutator/jest-runner/jest-env/jsdom-sixteen");

Basic Usage

Stryker Configuration

// stryker.conf.js
module.exports = {
  testRunner: "jest",
  coverageAnalysis: "perTest", // or "all" or "off"
  jest: {
    projectType: "custom", // or "create-react-app"  
    enableFindRelatedTests: true,
    config: {
      // Custom Jest configuration
      testEnvironment: "node"
    }
  }
};

Jest Environment Integration

import { mixinJestEnvironment } from "@stryker-mutator/jest-runner";
import { TestEnvironment } from "@jest/environment";

// Enhance Jest environment with Stryker integration
const StrykerJestEnvironment = mixinJestEnvironment(TestEnvironment);

Architecture

The Jest Runner is built around several key components:

  • Plugin System: Integrates with Stryker's plugin architecture using factory pattern
  • Test Adapter Pattern: Abstracts Jest version differences through adapters
  • Configuration Management: Handles Jest config loading for different project types
  • Environment Enhancement: Provides Jest environment mixins for mutation testing
  • Coverage Analysis: Implements per-test and global coverage tracking
  • Hit Limiting: Prevents infinite loops during mutation testing

Capabilities

Stryker Plugin Integration

Core plugin registration and validation schema for Stryker integration. Provides the main entry point for using Jest as a test runner in Stryker mutation testing.

export const strykerPlugins: Array<PluginDeclaration>;

export const strykerValidationSchema: JestRunnerOptionsSchema;

Plugin Integration

Jest Test Runner

Main test runner implementation that executes Jest tests within Stryker's mutation testing workflow. Handles dry runs for coverage analysis and mutant runs for testing specific mutations.

export class JestTestRunner implements TestRunner {
  init(): Promise<void>;
  capabilities(): TestRunnerCapabilities;
  dryRun(options: Pick<DryRunOptions, 'coverageAnalysis' | 'files'>): Promise<DryRunResult>;
  mutantRun(options: MutantRunOptions): Promise<MutantRunResult>;
}

export function createJestTestRunnerFactory(
  namespace?: typeof INSTRUMENTER_CONSTANTS.NAMESPACE | '__stryker2__'
): {
  (injector: Injector<PluginContext>): JestTestRunner;
  inject: ['$injector'];
};

export const jestTestRunnerFactory: ReturnType<typeof createJestTestRunnerFactory>;

Test Runner

Jest Environment Integration

Jest environment enhancement utilities that provide Stryker-specific functionality including instrumenter context sharing and test event handling for coverage analysis.

export function mixinJestEnvironment<T extends typeof JestEnvironment>(
  JestEnvironmentClass: T & { [STRYKER_JEST_ENV]?: true }
): T;

Environment Integration

Configuration Management

Configuration loading and validation for different Jest project types including custom projects and Create React App setups. Handles Jest config merging and validation.

export interface JestOptions {
  projectType: JestProjectType;
  configFile?: string;
  config?: { [k: string]: unknown };
  enableFindRelatedTests: boolean;
}

export type JestProjectType = 'create-react-app' | 'custom';

export interface JestRunnerOptions {
  jest: JestOptions;
  [k: string]: unknown;
}

export interface JestRunnerOptionsWithStrykerOptions extends StrykerOptions, JestRunnerOptions {}

Configuration Management

Utility Functions and Classes

Core utility functions and wrapper classes for Jest integration, version handling, and coverage validation.

export class JestWrapper {
  getVersion(): string;
}

export class JestConfigWrapper {
  // Configuration loading and manipulation utilities
}

export function verifyAllTestFilesHaveCoverage(
  jestResult: AggregatedResult,
  testFilesWithStrykerEnvironment: Set<string>
): string | undefined;

export function withCoverageAnalysis(
  jestConfig: Config.InitialOptions,
  coverageAnalysis: CoverageAnalysis,
  jestWrapper: JestWrapper
): Config.InitialOptions;

export function withHitLimit(
  jestConfig: Config.InitialOptions,
  hitLimit: number | undefined,
  jestWrapper: JestWrapper
): Config.InitialOptions;

export const JEST_OVERRIDE_OPTIONS: Readonly<Config.InitialOptions>;

export const pluginTokens: {
  readonly requireFromCwd: 'requireFromCwd';
  readonly resolve: 'resolve';
  readonly resolveFromDirectory: 'resolveFromDirectory';
  readonly configLoader: 'configLoader';
  readonly processEnv: 'processEnv';
  readonly jestTestAdapter: 'jestTestAdapter';
  readonly globalNamespace: 'globalNamespace';
  readonly jestWrapper: 'jestWrapper';
  readonly jestConfigWrapper: 'jestConfigWrapper';
};

Utilities

Types

Core Plugin Types

interface PluginDeclaration {
  kind: PluginKind;
  name: string;
  factory: Function;
}

interface TestRunnerCapabilities {
  reloadEnvironment: boolean;
}

Test Execution Types

interface DryRunOptions {
  coverageAnalysis: CoverageAnalysis;
  files: string[];
}

interface MutantRunOptions {
  activeMutant: Mutant;
  sandboxFileName: string;
  testFilter?: string[];
  disableBail: boolean;
  hitLimit?: number;
}

interface DryRunResult {
  status: DryRunStatus;
  tests?: TestResult[];
  errorMessage?: string;
  mutantCoverage?: MutantCoverage;
}

interface MutantRunResult {
  status: MutantRunStatus;
  tests?: TestResult[];
  errorMessage?: string;
  killedBy?: string[];
  survivalReason?: string;
}

Jest Integration Types

interface RunSettings {
  jestConfig: Config.InitialOptions;
  testNamePattern?: string;
  fileNamesUnderTest?: string[];
  testLocationInResults?: boolean;
}

interface JestRunResult {
  results: AggregatedResult;
  globalConfig: Config.GlobalConfig;
}

interface JestTestAdapter {
  run(settings: RunSettings): Promise<JestRunResult>;
}

Jest and Stryker Core Types

// Jest configuration types (from @jest/types)
namespace Config {
  interface InitialOptions {
    [key: string]: unknown;
    testEnvironment?: string;
    collectCoverageFrom?: string[];
    coverageReporters?: string[];
    setupFilesAfterEnv?: string[];
    transform?: { [key: string]: string };
    testMatch?: string[];
    testPathIgnorePatterns?: string[];
    moduleNameMapping?: { [key: string]: string };
  }
  
  interface GlobalConfig extends InitialOptions {
    projects: ProjectConfig[];
    watch: boolean;
    watchman: boolean;
  }
  
  interface ProjectConfig extends InitialOptions {
    displayName?: string;
    rootDir: string;
    testMatch: string[];
  }
}

// Jest test result types (from @jest/test-result)
interface AggregatedResult {
  numFailedTests: number;
  numPassedTests: number;
  numPendingTests: number;
  numTotalTests: number;
  success: boolean;
  testResults: TestResult[];
}

// Stryker core types
type CoverageAnalysis = 'off' | 'all' | 'perTest';

interface Mutant {
  id: string;
  fileName: string;
  mutatorName: string;
  replacement: string;
  range: [number, number];
}

enum DryRunStatus {
  Complete = 'Complete',
  Error = 'Error',
  Timeout = 'Timeout'
}

enum MutantRunStatus {
  Killed = 'Killed',
  Survived = 'Survived',
  Timeout = 'Timeout',
  Error = 'Error'
}

interface TestResult {
  id: string;
  name: string;
  status: TestStatus;
  timeSpentMs?: number;
  failureMessage?: string;
}

enum TestStatus {
  Success = 'Success',
  Failed = 'Failed',
  Skipped = 'Skipped'
}

// Stryker constants
const INSTRUMENTER_CONSTANTS = {
  NAMESPACE: '__stryker__'
} as const;