Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/angular/build/src/builders/unit-test/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export async function normalizeOptions(
: [],
dumpVirtualFiles: options.dumpVirtualFiles,
listTests: options.listTests,
update: options.update ?? false,
runnerConfig:
typeof runnerConfig === 'string'
? runnerConfig.length === 0
Expand Down
85 changes: 85 additions & 0 deletions packages/angular/build/src/builders/unit-test/options_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* @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 { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { normalizeOptions } from './options';
import type { Schema as UnitTestBuilderOptions } from './schema';

function createMockContext(workspaceRoot: string) {
return {
workspaceRoot,
target: { project: 'test-project', target: 'test', configuration: '' },
logger: { warn: () => {}, info: () => {}, error: () => {}, debug: () => {} },
getProjectMetadata: async (_projectName: string) => ({
root: '.',
sourceRoot: 'src',
}),
getBuilderNameForTarget: async () => '@angular/build:application',
};
}

describe('normalizeOptions', () => {
let workspaceRoot: string;

beforeEach(async () => {
workspaceRoot = await mkdtemp(join(tmpdir(), 'angular-cli-options-spec-'));
// Write a minimal package.json so cache normalization works
await writeFile(join(workspaceRoot, 'package.json'), '{}');
// Create a tsconfig.spec.json so tsConfig resolution succeeds
await mkdir(join(workspaceRoot, 'src'), { recursive: true });
await writeFile(join(workspaceRoot, 'tsconfig.spec.json'), '{}');
});

afterEach(async () => {
await rm(workspaceRoot, { recursive: true, force: true });
});

it('should set update to false by default', async () => {
const options: UnitTestBuilderOptions = {};
const context = createMockContext(workspaceRoot);

const normalized = await normalizeOptions(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context as any,
'test-project',
options,
);

expect(normalized.update).toBeFalse();
});

it('should set update to true when update option is true', async () => {
const options: UnitTestBuilderOptions = { update: true };
const context = createMockContext(workspaceRoot);

const normalized = await normalizeOptions(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context as any,
'test-project',
options,
);

expect(normalized.update).toBeTrue();
});

it('should set update to false when update option is explicitly false', async () => {
const options: UnitTestBuilderOptions = { update: false };
const context = createMockContext(workspaceRoot);

const normalized = await normalizeOptions(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context as any,
'test-project',
options,
);

expect(normalized.update).toBeFalse();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ export class VitestExecutor implements TestExecutor {
runnerConfig,
projectSourceRoot,
cacheOptions,
update,
} = this.options;
const projectName = this.projectName;

Expand Down Expand Up @@ -355,6 +356,7 @@ export class VitestExecutor implements TestExecutor {
cache: cacheOptions.enabled ? undefined : (false as const),
testNamePattern: this.options.filter,
watch,
...(update ? { update } : {}),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with other boolean options like watch, the update option should be passed directly to the Vitest configuration. Since update is normalized to a boolean value in normalizeOptions, using a conditional spread is unnecessary. Passing it directly also ensures that the CLI flag correctly overrides any settings in the Vitest configuration file (e.g., allowing --no-update to disable snapshot updates if they are enabled in the config).

Suggested change
...(update ? { update } : {}),
update,
References
  1. When refactoring code that handles configuration properties, ensure that any implicit type validation previously performed is still maintained. Redundant checks or conditional logic can be removed if the configuration is guaranteed to be type-safe by an upstream process.

...(typeof ui === 'boolean' ? { ui } : {}),
...debugOptions,
};
Expand Down
5 changes: 5 additions & 0 deletions packages/angular/build/src/builders/unit-test/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@
"type": "boolean",
"description": "Shows build progress information in the console. Defaults to the `progress` setting of the specified `buildTarget`."
},
"update": {
"type": "boolean",
"description": "Updates existing snapshots when they fail instead of failing the test. Only available for the Vitest runner.",
"default": false
},
"listTests": {
"type": "boolean",
"description": "Lists all discovered test files and exits the process without building or executing the tests.",
Expand Down
Loading