From f6434eef508ac4747996ba9b26b4a7aa1b73198d Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:38:43 +0000 Subject: [PATCH 1/3] test: simplify array option parsing test cases by consolidating multiple flag usages into a single flag with multiple values This ensures that array parsing is handled correctly. --- .../utilities/json-schema_spec.ts | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts b/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts index d311373d69f0..f0aca0175f30 100644 --- a/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts +++ b/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts @@ -139,9 +139,7 @@ describe('parseJsonSchemaToOptions', () => { describe('type=array, enum', () => { it('parses valid option value', async () => { - expect( - await parse(['--arrayWithChoices', 'always', '--arrayWithChoices', 'never']), - ).toEqual( + expect(await parse(['--arrayWithChoices', 'always', 'never'])).toEqual( jasmine.objectContaining({ 'arrayWithChoices': ['always', 'never'], }), @@ -161,14 +159,7 @@ describe('parseJsonSchemaToOptions', () => { describe('type=array, enum in oneOf', () => { it('parses valid option value', async () => { - expect( - await parse([ - '--arrayWithChoicesInOneOf', - 'default', - '--arrayWithChoicesInOneOf', - 'verbose', - ]), - ).toEqual( + expect(await parse(['--arrayWithChoicesInOneOf', 'default', 'verbose'])).toEqual( jasmine.objectContaining({ 'arrayWithChoicesInOneOf': ['default', 'verbose'], }), @@ -184,14 +175,7 @@ describe('parseJsonSchemaToOptions', () => { describe('type=array, anyOf', () => { it('parses valid option value', async () => { - expect( - await parse([ - '--arrayWithComplexAnyOf', - 'default', - '--arrayWithComplexAnyOf', - 'something-else', - ]), - ).toEqual( + expect(await parse(['--arrayWithComplexAnyOf', 'default', 'something-else'])).toEqual( jasmine.objectContaining({ 'arrayWithComplexAnyOf': ['default', 'something-else'], }), From 2d9572b3d8c9b62ba73f678f872388364b3b911d Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:58:45 +0000 Subject: [PATCH 2/3] test: optimize `json-schema_spec.ts` by parsing the schema once in `beforeAll` instead of `beforeEach` This reduces the parsing times. --- .../utilities/json-schema_spec.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts b/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts index f0aca0175f30..b74cbfc9d6ad 100644 --- a/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts +++ b/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts @@ -9,7 +9,7 @@ import { JsonObject, schema } from '@angular-devkit/core'; import yargs from 'yargs'; -import { addSchemaOptionsToCommand, parseJsonSchemaToOptions } from './json-schema'; +import { Option, addSchemaOptionsToCommand, parseJsonSchemaToOptions } from './json-schema'; describe('parseJsonSchemaToOptions', () => { describe('without required fields in schema', () => { @@ -21,10 +21,9 @@ describe('parseJsonSchemaToOptions', () => { }; let localYargs: yargs.Argv; - beforeEach(async () => { - // Create a fresh yargs for each call. The yargs object is stateful and - // calling .parse multiple times on the same instance isn't safe. - localYargs = yargs().exitProcess(false).strict().fail(false).wrap(1_000); + let options: Option[]; + + beforeAll(async () => { const jsonSchema = { 'type': 'object', 'properties': { @@ -118,12 +117,20 @@ describe('parseJsonSchemaToOptions', () => { }, }, }; + const registry = new schema.CoreSchemaRegistry(); - const options = await parseJsonSchemaToOptions( + options = await parseJsonSchemaToOptions( registry, jsonSchema as unknown as JsonObject, false, ); + }); + + beforeEach(async () => { + // Create a fresh yargs for each call. The yargs object is stateful and + // calling .parse multiple times on the same instance isn't safe. + localYargs = yargs().exitProcess(false).strict().fail(false).wrap(1_000); + addSchemaOptionsToCommand(localYargs, options, true); }); From e88eea9c562338f13f37748a7fa912017e9cfbd8 Mon Sep 17 00:00:00 2001 From: Alan Agius <17563226+alan-agius4@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:43:06 +0000 Subject: [PATCH 3/3] test: add test cases for parsing array options specified multiple times Add some more tests for arrays. --- .../utilities/json-schema_spec.ts | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts b/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts index b74cbfc9d6ad..11228e4adca0 100644 --- a/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts +++ b/packages/angular/cli/src/command-builder/utilities/json-schema_spec.ts @@ -145,7 +145,7 @@ describe('parseJsonSchemaToOptions', () => { }); describe('type=array, enum', () => { - it('parses valid option value', async () => { + it('parses valid option value when specified once', async () => { expect(await parse(['--arrayWithChoices', 'always', 'never'])).toEqual( jasmine.objectContaining({ 'arrayWithChoices': ['always', 'never'], @@ -153,6 +153,16 @@ describe('parseJsonSchemaToOptions', () => { ); }); + it('parses valid option value when specified multiple times', async () => { + expect( + await parse(['--arrayWithChoices', 'always', '--arrayWithChoices', 'never']), + ).toEqual( + jasmine.objectContaining({ + 'arrayWithChoices': ['always', 'never'], + }), + ); + }); + it('rejects non-enum values', async () => { await expectAsync(parse(['--arrayWithChoices', 'yes'])).toBeRejectedWithError( /Argument: array-with-choices, Given: "yes", Choices:/, @@ -165,7 +175,7 @@ describe('parseJsonSchemaToOptions', () => { }); describe('type=array, enum in oneOf', () => { - it('parses valid option value', async () => { + it('parses valid option value when specified once', async () => { expect(await parse(['--arrayWithChoicesInOneOf', 'default', 'verbose'])).toEqual( jasmine.objectContaining({ 'arrayWithChoicesInOneOf': ['default', 'verbose'], @@ -173,6 +183,21 @@ describe('parseJsonSchemaToOptions', () => { ); }); + it('parses valid option value when specified multiple times', async () => { + expect( + await parse([ + '--arrayWithChoicesInOneOf', + 'default', + '--arrayWithChoicesInOneOf', + 'verbose', + ]), + ).toEqual( + jasmine.objectContaining({ + 'arrayWithChoicesInOneOf': ['default', 'verbose'], + }), + ); + }); + it('rejects non-enum values', async () => { await expectAsync(parse(['--arrayWithChoicesInOneOf', 'yes'])).toBeRejectedWithError( /Argument: array-with-choices-in-one-of, Given: "yes", Choices:/, @@ -181,13 +206,28 @@ describe('parseJsonSchemaToOptions', () => { }); describe('type=array, anyOf', () => { - it('parses valid option value', async () => { + it('parses valid option value when specified once', async () => { expect(await parse(['--arrayWithComplexAnyOf', 'default', 'something-else'])).toEqual( jasmine.objectContaining({ 'arrayWithComplexAnyOf': ['default', 'something-else'], }), ); }); + + it('parses valid option value when specified multiple times', async () => { + expect( + await parse([ + '--arrayWithComplexAnyOf', + 'default', + '--arrayWithComplexAnyOf', + 'something-else', + ]), + ).toEqual( + jasmine.objectContaining({ + 'arrayWithComplexAnyOf': ['default', 'something-else'], + }), + ); + }); }); describe('type=string, enum', () => {