diff --git a/packages/schematics/angular/migrations/migration-collection.json b/packages/schematics/angular/migrations/migration-collection.json index d7bf9151f72f..baa6be30f7a6 100644 --- a/packages/schematics/angular/migrations/migration-collection.json +++ b/packages/schematics/angular/migrations/migration-collection.json @@ -115,6 +115,11 @@ "factory": "./update-12/update-web-workers", "description": "Updates Web Worker consumer usage to use the new syntax supported directly by Webpack 5." }, + "schematic-options-12": { + "version": "12.0.1", + "factory": "./update-12/schematic-options", + "description": "Remove invalid 'skipTests' option in '@schematics/angular:module' Angular schematic options." + }, "production-by-default": { "version": "9999.0.0", "factory": "./update-12/production-default-config", diff --git a/packages/schematics/angular/migrations/update-12/schematic-options.ts b/packages/schematics/angular/migrations/update-12/schematic-options.ts new file mode 100644 index 000000000000..50870ef2be64 --- /dev/null +++ b/packages/schematics/angular/migrations/update-12/schematic-options.ts @@ -0,0 +1,41 @@ +/** + * @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.io/license + */ + +import { json } from '@angular-devkit/core'; +import { Rule } from '@angular-devkit/schematics'; +import { updateWorkspace } from '../../utility/workspace'; + +export default function (): Rule { + return updateWorkspace((workspace) => { + // Update root level schematics options if present + const rootSchematics = workspace.extensions.schematics; + if (rootSchematics && json.isJsonObject(rootSchematics)) { + updateSchematicsField(rootSchematics); + } + + // Update project level schematics options if present + for (const [, project] of workspace.projects) { + const projectSchematics = project.extensions.schematics; + if (projectSchematics && json.isJsonObject(projectSchematics)) { + updateSchematicsField(projectSchematics); + } + } + }); +} + +function updateSchematicsField(schematics: json.JsonObject): void { + for (const [schematicName, schematicOptions] of Object.entries(schematics)) { + if (!json.isJsonObject(schematicOptions)) { + continue; + } + + if (schematicName === '@schematics/angular:module') { + delete schematicOptions.skipTests; + } + } +} diff --git a/packages/schematics/angular/migrations/update-12/schematic-options_spec.ts b/packages/schematics/angular/migrations/update-12/schematic-options_spec.ts new file mode 100644 index 000000000000..f9891f62a367 --- /dev/null +++ b/packages/schematics/angular/migrations/update-12/schematic-options_spec.ts @@ -0,0 +1,76 @@ +/** + * @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.io/license + */ + +import { EmptyTree } from '@angular-devkit/schematics'; +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; + +describe('Migration to remove schematics old options in angular.json', () => { + const workspacePath = '/angular.json'; + const schematicName = 'schematic-options-12'; + + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + let tree: UnitTestTree; + + beforeEach(async () => { + tree = new UnitTestTree(new EmptyTree()); + tree = await schematicRunner + .runExternalSchematicAsync( + require.resolve('../../collection.json'), + 'ng-new', + { + name: 'migration-test', + version: '1.2.3', + directory: '.', + }, + tree, + ) + .toPromise(); + }); + + describe('schematic options', () => { + it('should remove `skipTests` from `@schematics/angular:module`', async () => { + const workspace = JSON.parse(tree.readContent(workspacePath)); + workspace.schematics = { + '@schematics/angular:module': { + skipTests: true, + }, + }; + tree.overwrite(workspacePath, JSON.stringify(workspace, undefined, 2)); + + const tree2 = await schematicRunner + .runSchematicAsync(schematicName, {}, tree.branch()) + .toPromise(); + const { schematics } = JSON.parse(tree2.readContent(workspacePath)); + expect(schematics['@schematics/angular:module'].skipTests).toBeUndefined(); + }); + + it('should not remove `skipTests` from non `@schematics/angular:module` schematic', async () => { + const workspace = JSON.parse(tree.readContent(workspacePath)); + workspace.schematics = { + '@schematics/angular:component': { + skipTests: true, + }, + '@schematics/some-other:module': { + skipTests: true, + }, + }; + tree.overwrite(workspacePath, JSON.stringify(workspace, undefined, 2)); + + const tree2 = await schematicRunner + .runSchematicAsync(schematicName, {}, tree.branch()) + .toPromise(); + const { schematics } = JSON.parse(tree2.readContent(workspacePath)); + expect(schematics['@schematics/angular:component'].skipTests).toBeTrue(); + expect(schematics['@schematics/some-other:module'].skipTests).toBeTrue(); + }); + }); +});