Testing infrastructure supporting multiple test runners including Karma, Jest, and Web Test Runner for Angular applications and libraries.
Executes unit tests using Karma test runner with Angular-specific configuration.
/**
* Execute unit tests using Karma test runner
* @param options - Karma test configuration
* @param context - Builder context
* @param transforms - Optional transformation hooks
* @returns Observable with test execution results
*/
function executeKarmaBuilder(
options: KarmaBuilderOptions,
context: BuilderContext,
transforms?: {
webpackConfiguration?: ExecutionTransformer<Configuration>;
karmaOptions?: (options: KarmaConfigOptions) => KarmaConfigOptions;
}
): Observable<BuilderOutput>;
interface KarmaBuilderOptions {
/** Main test entry point */
main: string;
/** TypeScript configuration for tests */
tsConfig: string;
/** Path to karma configuration file */
karmaConfig?: string;
/** Polyfills for test environment */
polyfills?: string | string[];
/** Test assets to include */
assets?: AssetPattern[];
/** Stylesheets for tests */
styles?: (string | StyleElement)[];
/** Scripts for test environment */
scripts?: (string | ScriptElement)[];
/** Enable watch mode */
watch?: boolean;
/** Browser to run tests in */
browsers?: string | false;
/** Enable code coverage */
codeCoverage?: boolean;
/** Files to exclude from coverage */
codeCoverageExclude?: string[];
/** File replacements for testing */
fileReplacements?: FileReplacement[];
/** Test reporters to use */
reporters?: string[];
/** Additional test files to include */
include?: string | string[];
/** Test source maps */
sourceMap?: boolean;
/** Enable progress reporting */
progress?: boolean;
/** Builder mode detection */
builderMode?: BuilderMode;
}
interface KarmaConfigOptions extends ConfigOptions {
/** Webpack build configuration */
buildWebpack?: unknown;
/** Karma config file path */
configFile?: string;
}
enum BuilderMode {
/** Detect builder automatically */
Detect = 'detect',
/** Use application builder (esbuild) */
Application = 'application',
/** Use browser builder (webpack) */
Browser = 'browser'
}Usage Examples:
import { executeKarmaBuilder } from "@angular-devkit/build-angular";
// Basic Karma test configuration
const karmaOptions: KarmaBuilderOptions = {
main: "src/test.ts",
tsConfig: "tsconfig.spec.json",
polyfills: ["zone.js", "zone.js/testing"],
assets: ["src/favicon.ico", "src/assets"],
styles: ["src/styles.css"],
scripts: [],
codeCoverage: true,
browsers: "ChromeHeadless",
watch: false
};
// Run tests with custom webpack configuration
const testResult = await executeKarmaBuilder(karmaOptions, context, {
webpackConfiguration: (config) => {
// Add custom webpack config for tests
config.resolve.alias = {
'@': path.resolve('src')
};
return config;
},
karmaOptions: (karmaConfig) => {
// Customize Karma configuration
karmaConfig.singleRun = true;
karmaConfig.autoWatch = false;
return karmaConfig;
}
}).toPromise();Executes unit tests using Jest test runner with Angular support via esbuild compilation.
/**
* Execute unit tests using Jest test runner
* Jest builder provides faster test execution and better watch mode
* Uses esbuild for compilation and jsdom for browser environment simulation
*/
interface JestBuilderOptions {
/** TypeScript configuration file */
tsConfig: string;
/** Test file patterns to include */
include?: string[];
/** Test file patterns to exclude */
exclude?: string[];
/** Polyfills to include in the build */
polyfills?: string[];
/** Enable Ahead of Time compilation */
aot?: boolean;
}Usage Examples:
// Basic Jest configuration in angular.json
{
"test-jest": {
"builder": "@angular-devkit/build-angular:jest",
"options": {
"tsConfig": "tsconfig.spec.json",
"include": ["**/*.spec.ts"],
"exclude": ["**/*.e2e-spec.ts"],
"polyfills": ["zone.js", "zone.js/testing"],
"aot": false
}
}
}
// Running Jest tests
ng run my-app:test-jestImportant Notes:
jest and jest-environment-jsdom packages to be installedExecutes tests using @web/test-runner for modern browser testing with native ES modules support.
/**
* Execute tests using Web Test Runner
* Modern test runner with native ES modules support and Jasmine framework
* Uses esbuild for compilation and real browser environments for testing
*/
interface WebTestRunnerBuilderOptions {
/** TypeScript configuration file */
tsConfig: string;
/** Main test entry point */
main?: string;
/** Polyfills to include */
polyfills?: string | string[];
/** Static assets to include */
assets?: AssetPattern[];
/** Global scripts */
scripts?: (string | ScriptElement)[];
/** Global styles */
styles?: (string | StyleElement)[];
/** Inline style language */
inlineStyleLanguage?: 'css' | 'less' | 'sass' | 'scss';
/** Style preprocessor options */
stylePreprocessorOptions?: {
includePaths?: string[];
};
/** Test file patterns to include */
include?: string[];
/** Test file patterns to exclude */
exclude?: string[];
/** Enable source maps */
sourceMap?: boolean | SourceMapOptions;
/** Show progress */
progress?: boolean;
/** Watch mode */
watch?: boolean;
/** File watching poll interval */
poll?: number;
/** Preserve symlinks */
preserveSymlinks?: boolean;
/** Browser override */
browsers?: string;
/** Enable code coverage */
codeCoverage?: boolean;
/** Files to exclude from coverage */
codeCoverageExclude?: string[];
/** File replacements */
fileReplacements?: FileReplacement[];
/** Web Worker TypeScript config */
webWorkerTsConfig?: string;
/** Enable AOT compilation */
aot?: boolean;
}Usage Examples:
// Basic Web Test Runner configuration
{
"test-wtr": {
"builder": "@angular-devkit/build-angular:web-test-runner",
"options": {
"tsConfig": "tsconfig.spec.json",
"include": ["**/*.spec.ts"],
"exclude": ["**/*.e2e-spec.ts"],
"polyfills": ["zone.js", "zone.js/testing"],
"codeCoverage": true,
"browsers": "chrome",
"watch": false
}
}
}
// Running Web Test Runner tests
ng run my-app:test-wtrImportant Notes:
@web/test-runner package to be installedinterface TestEnvironmentOptions {
/** Test framework configuration */
framework: 'jasmine' | 'jest' | 'mocha';
/** Browser configuration */
browsers: BrowserConfig[];
/** Test reporters */
reporters: ReporterConfig[];
/** Coverage configuration */
coverage?: CoverageConfig;
}
interface BrowserConfig {
/** Browser name */
name: string;
/** Browser options */
options?: {
headless?: boolean;
args?: string[];
timeout?: number;
};
}
interface ReporterConfig {
/** Reporter type */
type: 'spec' | 'json' | 'html' | 'lcov' | 'text' | 'teamcity';
/** Output directory */
dir?: string;
/** Additional options */
options?: Record<string, any>;
}
interface CoverageConfig {
/** Include patterns */
include?: string[];
/** Exclude patterns */
exclude?: string[];
/** Coverage thresholds */
threshold?: {
statements?: number;
branches?: number;
functions?: number;
lines?: number;
};
/** Coverage reporters */
reporters?: string[];
/** Output directory */
dir?: string;
}/**
* Default Karma configuration for Angular projects
*/
interface DefaultKarmaConfig {
basePath: '';
frameworks: ['jasmine', '@angular-devkit/build-angular'];
plugins: [
'karma-jasmine',
'karma-chrome-launcher',
'karma-jasmine-html-reporter',
'karma-coverage',
'@angular-devkit/build-angular/plugins/karma'
];
jasmineHtmlReporter: {
suppressAll: boolean;
};
coverageReporter: {
dir: string;
subdir: '.';
reporters: Array<{ type: string }>;
};
reporters: ['progress', 'kjhtml'];
browsers: ['Chrome'];
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless';
flags: string[];
};
};
restartOnFileChange: boolean;
}