From 152f1596acb320060dcd48a42c59dc2fb7144793 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Thu, 24 Apr 2025 12:21:22 -0400 Subject: [PATCH] refactor(@angular/build): provide karma runner for unit-test builder The `runner` option for the `unit-test` builder can now be set to `karma`. This leverages the existing `karma` builder for test execution. The `karma` build related options are derived from the provided `buildTarget` option instead of being manually specified within the `unit-test` builder. In other areas, the test execution is the same with the exceptions of specifying either a custom configuration file and/or a custom main file. --- .../build/src/builders/unit-test/builder.ts | 9 ++++ .../src/builders/unit-test/karma-bridge.ts | 53 +++++++++++++++++++ .../build/src/builders/unit-test/schema.json | 2 +- 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 packages/angular/build/src/builders/unit-test/karma-bridge.ts diff --git a/packages/angular/build/src/builders/unit-test/builder.ts b/packages/angular/build/src/builders/unit-test/builder.ts index fcf1f837a658..2ba2f140e8bb 100644 --- a/packages/angular/build/src/builders/unit-test/builder.ts +++ b/packages/angular/build/src/builders/unit-test/builder.ts @@ -22,6 +22,7 @@ import { ResultKind } from '../application/results'; import { OutputHashing } from '../application/schema'; import { writeTestFiles } from '../karma/application_builder'; import { findTests, getTestEntrypoints } from '../karma/find-tests'; +import { useKarmaBuilder } from './karma-bridge'; import { normalizeOptions } from './options'; import type { Schema as UnitTestOptions } from './schema'; @@ -52,6 +53,14 @@ export async function* execute( const normalizedOptions = await normalizeOptions(context, projectName, options); const { projectSourceRoot, workspaceRoot, runnerName } = normalizedOptions; + // Translate options and use karma builder directly if specified + if (runnerName === 'karma') { + const karmaBridge = await useKarmaBuilder(context, normalizedOptions); + yield* karmaBridge; + + return; + } + if (runnerName !== 'vitest') { context.logger.error('Unknown test runner: ' + runnerName); diff --git a/packages/angular/build/src/builders/unit-test/karma-bridge.ts b/packages/angular/build/src/builders/unit-test/karma-bridge.ts new file mode 100644 index 000000000000..1080e8ade73e --- /dev/null +++ b/packages/angular/build/src/builders/unit-test/karma-bridge.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import type { BuilderContext, BuilderOutput } from '@angular-devkit/architect'; +import type { ApplicationBuilderInternalOptions } from '../application/options'; +import type { KarmaBuilderOptions } from '../karma'; +import type { NormalizedUnitTestOptions } from './options'; + +export async function useKarmaBuilder( + context: BuilderContext, + unitTestOptions: NormalizedUnitTestOptions, +): Promise> { + const buildTargetOptions = (await context.validateOptions( + await context.getTargetOptions(unitTestOptions.buildTarget), + await context.getBuilderNameForTarget(unitTestOptions.buildTarget), + )) as unknown as ApplicationBuilderInternalOptions; + + const options: KarmaBuilderOptions = { + tsConfig: unitTestOptions.tsConfig, + polyfills: buildTargetOptions.polyfills, + assets: buildTargetOptions.assets, + scripts: buildTargetOptions.scripts, + styles: buildTargetOptions.styles, + inlineStyleLanguage: buildTargetOptions.inlineStyleLanguage, + stylePreprocessorOptions: buildTargetOptions.stylePreprocessorOptions, + externalDependencies: buildTargetOptions.externalDependencies, + loader: buildTargetOptions.loader, + define: buildTargetOptions.define, + include: unitTestOptions.include, + exclude: unitTestOptions.exclude, + sourceMap: buildTargetOptions.sourceMap, + progress: buildTargetOptions.progress, + watch: unitTestOptions.watch, + poll: buildTargetOptions.poll, + preserveSymlinks: buildTargetOptions.preserveSymlinks, + browsers: unitTestOptions.browsers?.join(','), + codeCoverage: unitTestOptions.codeCoverage, + codeCoverageExclude: unitTestOptions.codeCoverageExclude, + fileReplacements: buildTargetOptions.fileReplacements, + reporters: unitTestOptions.reporters, + webWorkerTsConfig: buildTargetOptions.webWorkerTsConfig, + aot: buildTargetOptions.aot, + }; + + const { execute } = await import('../karma'); + + return execute(options, context); +} diff --git a/packages/angular/build/src/builders/unit-test/schema.json b/packages/angular/build/src/builders/unit-test/schema.json index 1455227a3808..223aa149bcdf 100644 --- a/packages/angular/build/src/builders/unit-test/schema.json +++ b/packages/angular/build/src/builders/unit-test/schema.json @@ -16,7 +16,7 @@ "runner": { "type": "string", "description": "The name of the test runner to use for test execution.", - "enum": ["vitest"] + "enum": ["karma", "vitest"] }, "browsers": { "description": "A list of browsers to use for test execution. If undefined, jsdom on Node.js will be used instead of a browser.",