angular-cli/packages/schematics/angular/migrations/update-12/production-default-config_spec.ts
Alan Agius c7e126609f feat(@schematics/angular): add production by default optional migration
With this change we add an optional migration to update Angular CLI workspace configurations to 'production' mode by default.

To run this migration use the below commands
```
ng update @angular/cli
ng update @angular/cli --migrate-only production-by-default
```
2021-03-24 09:16:50 -04:00

311 lines
9.6 KiB
TypeScript

/**
* @license
* Copyright Google Inc. 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 { JsonObject } from '@angular-devkit/core';
import { EmptyTree } from '@angular-devkit/schematics';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models';
function getArchitect(tree: UnitTestTree): JsonObject {
return JSON.parse(tree.readContent('/angular.json')).projects.app.architect;
}
function createWorkSpaceConfig(tree: UnitTestTree) {
const angularConfig: WorkspaceSchema = {
version: 1,
projects: {
app: {
root: '',
sourceRoot: 'src',
projectType: ProjectType.Application,
prefix: 'app',
architect: {
browser: {
builder: Builders.Browser,
options: {
outputPath: 'dist/integration-project',
index: 'src/index.html',
main: 'src/main.ts',
polyfills: 'src/polyfills.ts',
tsConfig: 'tsconfig.app.json',
aot: true,
sourceMap: true,
assets: [
'src/favicon.ico',
'src/assets',
],
styles: [
'src/styles.css',
],
scripts: [],
},
configurations: {
production: {
deployUrl: 'http://cdn.com',
fileReplacements: [{
replace: 'src/environments/environment.ts',
with: 'src/environments/environment.prod.ts',
}],
optimization: true,
outputHashing: 'all',
sourceMap: false,
namedChunks: false,
extractLicenses: true,
vendorChunk: false,
buildOptimizer: true,
watch: true,
budgets: [{
type: 'initial',
maximumWarning: '2mb',
maximumError: '5mb',
}],
},
optimization_sm: {
sourceMap: true,
optimization: true,
namedChunks: false,
vendorChunk: true,
buildOptimizer: true,
},
},
},
ng_packagr: {
builder: Builders.NgPackagr,
options: {
watch: true,
tsConfig: 'projects/lib/tsconfig.lib.json',
},
configurations: {
production: {
watch: false,
tsConfig: 'projects/lib/tsconfig.lib.prod.json',
},
},
},
dev_server: {
builder: Builders.DevServer,
options: {
browserTarget: 'app:build',
watch: false,
},
configurations: {
production: {
browserTarget: 'app:build:production',
},
optimization_sm: {
browserTarget: 'app:build:optimization_sm',
},
},
},
app_shell: {
builder: Builders.AppShell,
options: {
browserTarget: 'app:build',
serverTarget: 'app:server',
},
configurations: {
optimization_sm: {
browserTarget: 'app:build:optimization_sm',
serverTarget: 'app:server:optimization_sm',
},
production: {
browserTarget: 'app:build:production',
serverTarget: 'app:server:optimization_sm',
},
},
},
server: {
builder: Builders.Server,
options: {
outputPath: 'dist/server',
main: 'server.ts',
tsConfig: 'tsconfig.server.json',
optimization: false,
sourceMap: true,
},
configurations: {
optimization_sm: {
sourceMap: true,
optimization: true,
},
production: {
fileReplacements: [
{
replace: 'src/environments/environment.ts',
with: 'src/environments/environment.prod.ts',
},
],
sourceMap: false,
optimization: true,
},
},
},
},
},
},
};
tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2));
}
const schematicName = 'production-by-default';
describe(`Migration to update 'angular.json' configurations to production by default. ${schematicName}`, () => {
const schematicRunner = new SchematicTestRunner(
'migrations',
require.resolve('../migration-collection.json'),
);
let tree: UnitTestTree;
beforeEach(() => {
tree = new UnitTestTree(new EmptyTree());
createWorkSpaceConfig(tree);
});
it('update browser builder configurations', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
const { browser } = getArchitect(newTree);
const output = {
builder: '@angular-devkit/build-angular:browser',
options: {
outputPath: 'dist/integration-project',
index: 'src/index.html',
main: 'src/main.ts',
polyfills: 'src/polyfills.ts',
tsConfig: 'tsconfig.app.json',
aot: true,
sourceMap: true,
assets: ['src/favicon.ico', 'src/assets'],
styles: ['src/styles.css'],
scripts: [],
},
configurations: {
production: {
deployUrl: 'http://cdn.com',
optimization: true,
outputHashing: 'all',
sourceMap: false,
namedChunks: false,
extractLicenses: true,
vendorChunk: false,
buildOptimizer: true,
watch: true,
fileReplacements: [{
replace: 'src/environments/environment.ts',
with: 'src/environments/environment.prod.ts',
}],
budgets: [{
type: 'initial',
maximumWarning: '2mb',
maximumError: '5mb',
}],
},
optimization_sm: {
sourceMap: true,
optimization: true,
namedChunks: false,
vendorChunk: true,
buildOptimizer: true,
},
development: {},
},
defaultConfiguration: 'production',
};
expect(browser).toEqual(output);
});
it('update ng-packagr builder configurations', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
const { ng_packagr } = getArchitect(newTree);
const output = {
builder: '@angular-devkit/build-angular:ng-packagr',
options: { watch: true, tsConfig: 'projects/lib/tsconfig.lib.json' },
configurations: {
production: { watch: false, tsConfig: 'projects/lib/tsconfig.lib.prod.json' },
development: {},
},
defaultConfiguration: 'production',
};
expect(ng_packagr).toEqual(output);
});
it('update dev-server builder configurations', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
const { dev_server } = getArchitect(newTree);
const output = {
builder: '@angular-devkit/build-angular:dev-server',
options: { watch: false },
configurations: {
production: { browserTarget: 'app:build:production' },
optimization_sm: { browserTarget: 'app:build:optimization_sm' },
development: { browserTarget: 'app:build:development' },
},
defaultConfiguration: 'development',
};
expect(dev_server).toEqual(output);
});
it('update server builder configurations', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
const { server } = getArchitect(newTree);
const output = {
builder: '@angular-devkit/build-angular:server',
options: {
outputPath: 'dist/server',
main: 'server.ts',
tsConfig: 'tsconfig.server.json',
optimization: false,
sourceMap: true,
},
configurations: {
optimization_sm: { sourceMap: true, optimization: true },
production: {
fileReplacements: [{
replace: 'src/environments/environment.ts',
with: 'src/environments/environment.prod.ts',
}],
sourceMap: false,
optimization: true,
},
development: {},
},
defaultConfiguration: 'production',
};
expect(server).toEqual(output);
});
it('update app-shell builder configurations', async () => {
const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise();
const { app_shell } = getArchitect(newTree);
const output = {
builder: '@angular-devkit/build-angular:app-shell',
options: {},
configurations: {
optimization_sm: {
browserTarget: 'app:build:optimization_sm',
serverTarget: 'app:server:optimization_sm',
},
production: {
browserTarget: 'app:build:production',
serverTarget: 'app:server:optimization_sm',
},
development: {
serverTarget: 'app:server:development',
browserTarget: 'app:build:development',
},
},
defaultConfiguration: 'production',
};
expect(app_shell).toEqual(output);
});
});