Repository navigation
Conversation
…bled The upfront dependency validation of the unit-test builder's karma runner checks the truthiness of the normalized `coverage` option, which is always an object since the introduction of the advanced coverage options. As a result, `ng test` with the karma runner fails with a `MissingDependenciesError` requesting the `karma-coverage` package even when coverage is disabled. Check the `enabled` property instead, matching the vitest runner and the karma executor. A new unit spec for the karma runner's dependency validation fails without this change.
There was a problem hiding this comment.
Code Review
This pull request updates the Karma test runner to check options.coverage.enabled instead of options.coverage when verifying dependencies, and introduces a new unit test suite to validate this behavior. The review feedback suggests simplifying the newly added tests by replacing the asynchronous assertions with synchronous Jasmine matchers, as the validateDependencies method is synchronous.
alan-agius4
reviewed
Oct 23, 2026
Comment on lines
+9
to
+53
| import assert from 'node:assert'; | ||
| import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'; | ||
| import { join } from 'node:path'; | ||
| import type { NormalizedUnitTestBuilderOptions } from '../../options'; | ||
| import KarmaTestRunner from './index'; | ||
|
|
||
| describe('KarmaTestRunner', () => { | ||
| describe('validateDependencies', () => { | ||
| let projectSourceRoot: string; | ||
|
|
||
| function createOptions(coverageEnabled: boolean): NormalizedUnitTestBuilderOptions { | ||
| return { | ||
| projectSourceRoot, | ||
| coverage: { enabled: coverageEnabled }, | ||
| } as NormalizedUnitTestBuilderOptions; | ||
| } | ||
|
|
||
| beforeAll(async () => { | ||
| const baseTmpDir = process.env['TEST_TMPDIR']; | ||
| assert(baseTmpDir, 'TEST_TMPDIR is not set'); | ||
| projectSourceRoot = await mkdtemp(join(baseTmpDir, 'angular-cli-karma-runner-')); | ||
|
|
||
| // A project with karma and karma-jasmine installed but not karma-coverage | ||
| await writeFile(join(projectSourceRoot, 'package.json'), '{"name": "test-project"}'); | ||
| for (const packageName of ['karma', 'karma-jasmine']) { | ||
| const packageRoot = join(projectSourceRoot, 'node_modules', packageName); | ||
| await mkdir(packageRoot, { recursive: true }); | ||
| await writeFile( | ||
| join(packageRoot, 'package.json'), | ||
| JSON.stringify({ name: packageName, version: '0.0.0', main: 'index.js' }), | ||
| ); | ||
| await writeFile(join(packageRoot, 'index.js'), ''); | ||
| } | ||
| }); | ||
|
|
||
| it('does not require karma-coverage when coverage is disabled', () => { | ||
| expect(() => KarmaTestRunner.validateDependencies?.(createOptions(false))).not.toThrow(); | ||
| }); | ||
|
|
||
| it('requires karma-coverage when coverage is enabled', () => { | ||
| expect(() => KarmaTestRunner.validateDependencies?.(createOptions(true))).toThrowError( | ||
| /karma-coverage/, | ||
| ); | ||
| }); | ||
| }); |
Collaborator
There was a problem hiding this comment.
We can simplify this test and avoid creating a temporary directory and mock node_modules on disk by passing a non-existent projectSourceRoot and asserting whether karma-coverage is included in the thrown MissingDependenciesError:
Suggested change
| import assert from 'node:assert'; | |
| import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'; | |
| import { join } from 'node:path'; | |
| import type { NormalizedUnitTestBuilderOptions } from '../../options'; | |
| import KarmaTestRunner from './index'; | |
| describe('KarmaTestRunner', () => { | |
| describe('validateDependencies', () => { | |
| let projectSourceRoot: string; | |
| function createOptions(coverageEnabled: boolean): NormalizedUnitTestBuilderOptions { | |
| return { | |
| projectSourceRoot, | |
| coverage: { enabled: coverageEnabled }, | |
| } as NormalizedUnitTestBuilderOptions; | |
| } | |
| beforeAll(async () => { | |
| const baseTmpDir = process.env['TEST_TMPDIR']; | |
| assert(baseTmpDir, 'TEST_TMPDIR is not set'); | |
| projectSourceRoot = await mkdtemp(join(baseTmpDir, 'angular-cli-karma-runner-')); | |
| // A project with karma and karma-jasmine installed but not karma-coverage | |
| await writeFile(join(projectSourceRoot, 'package.json'), '{"name": "test-project"}'); | |
| for (const packageName of ['karma', 'karma-jasmine']) { | |
| const packageRoot = join(projectSourceRoot, 'node_modules', packageName); | |
| await mkdir(packageRoot, { recursive: true }); | |
| await writeFile( | |
| join(packageRoot, 'package.json'), | |
| JSON.stringify({ name: packageName, version: '0.0.0', main: 'index.js' }), | |
| ); | |
| await writeFile(join(packageRoot, 'index.js'), ''); | |
| } | |
| }); | |
| it('does not require karma-coverage when coverage is disabled', () => { | |
| expect(() => KarmaTestRunner.validateDependencies?.(createOptions(false))).not.toThrow(); | |
| }); | |
| it('requires karma-coverage when coverage is enabled', () => { | |
| expect(() => KarmaTestRunner.validateDependencies?.(createOptions(true))).toThrowError( | |
| /karma-coverage/, | |
| ); | |
| }); | |
| }); | |
| import type { NormalizedUnitTestBuilderOptions } from '../../options'; | |
| import KarmaTestRunner from './index'; | |
| describe('KarmaTestRunner', () => { | |
| describe('validateDependencies', () => { | |
| function createOptions(coverageEnabled: boolean): NormalizedUnitTestBuilderOptions { | |
| return { | |
| projectSourceRoot: '/non-existent', | |
| coverage: { enabled: coverageEnabled }, | |
| } as NormalizedUnitTestBuilderOptions; | |
| } | |
| it('does not require karma-coverage when coverage is disabled', () => { | |
| expect(() => KarmaTestRunner.validateDependencies?.(createOptions(false))).toThrowError( | |
| /^(?!.*karma-coverage)/s, | |
| ); | |
| }); | |
| it('requires karma-coverage when coverage is enabled', () => { | |
| expect(() => KarmaTestRunner.validateDependencies?.(createOptions(true))).toThrowError( | |
| /karma-coverage/, | |
| ); | |
| }); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The upfront dependency validation of the unit-test builder's karma runner checks the truthiness of the normalized
coverageoption, which is always an object since the introduction of the advanced coverage options. As a result,ng testwith the karma runner fails with aMissingDependenciesErrorrequesting thekarma-coveragepackage even when coverage is disabled. Check theenabledproperty instead, matching the vitest runner and the karma executor. A new unit spec for the karma runner's dependency validation fails without this change.