Skip to content

Commit b830ba3

Browse files
committed
build: prepare schematics for v8
* Prepares the schematics for V8 * Dynamically resolves the test cases so that we don't need to hardcode them for each version
1 parent d22f48c commit b830ba3

16 files changed

+141
-206
lines changed

src/cdk/schematics/migration.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
"description": "Updates the Angular CDK to v7",
1212
"factory": "./ng-update/index#updateToV7"
1313
},
14+
"migration-v8": {
15+
"version": "8",
16+
"description": "Updates the Angular CDK to v8",
17+
"factory": "./ng-update/index#updateToV8"
18+
},
1419
"ng-post-update": {
1520
"description": "Prints out results after ng-update.",
1621
"factory": "./ng-update/index#postUpdate",

src/cdk/schematics/ng-update/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ export function updateToV7(): Rule {
3535
return createUpgradeRule(TargetVersion.V7, tslintUpgradeConfig);
3636
}
3737

38+
/** Entry point for the migration schematics with target of Angular Material 8.0.0 */
39+
export function updateToV8(): Rule {
40+
return createUpgradeRule(TargetVersion.V8, tslintUpgradeConfig);
41+
}
42+
3843
/** Post-update schematic to be called when update is finished. */
3944
export function postUpdate(): Rule {
4045
return () => {

src/cdk/schematics/ng-update/target-version.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@
1010
export enum TargetVersion {
1111
V6,
1212
V7,
13+
V8,
14+
}
15+
16+
/**
17+
* Returns all versions that are supported by "ng update". The versions are determined
18+
* based on the "TargetVersion" enum.
19+
*/
20+
export function getAllVersionNames(): string[] {
21+
return Object.keys(TargetVersion)
22+
.filter(enumValue => typeof TargetVersion[enumValue] === 'number');
1323
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
1+
import {defineJasmineTestCases, findBazelVersionTestCases} from '@angular/cdk/schematics/testing';
2+
import {getAllVersionNames} from '../target-version';
3+
14
/** Path to the schematic collection that includes the migrations. */
25
export const migrationCollection = require.resolve('../../migration.json');
6+
7+
describe('CDK upgrade test cases', () => {
8+
9+
const versionNames = getAllVersionNames().map(versionName => versionName.toLowerCase());
10+
const testCasesMap = findBazelVersionTestCases(
11+
'angular_material/src/cdk/schematics/ng-update/test-cases');
12+
13+
// Setup the test cases for each target version. The test cases will be automatically
14+
// detected through Bazel's runfiles manifest.
15+
versionNames.forEach(version => describe(`${version} update`, () => {
16+
defineJasmineTestCases(version, migrationCollection, testCasesMap.get(version));
17+
}));
18+
});

src/cdk/schematics/ng-update/test-cases/misc/method-call-checks.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import {runTestCases} from '../../../testing';
44
describe('v6 method call checks', () => {
55

66
it('should properly report invalid method calls', async () => {
7-
const {logOutput, removeTempDir} = await runTestCases('migration-v6', migrationCollection, {
8-
'method-call-checks': require.resolve('./method-call-checks_input.ts')
9-
});
7+
const {logOutput, removeTempDir} = await runTestCases('migration-v6', migrationCollection,
8+
[require.resolve('./method-call-checks_input.ts')]);
109

1110
expect(logOutput)
1211
.toMatch(/\[15,.*Found call to "FocusMonitor\.monitor".*renderer.*has been removed/);

src/cdk/schematics/ng-update/test-cases/v6-test-cases.spec.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/cdk/schematics/ng-update/test-cases/v7-test-cases.spec.ts

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/cdk/schematics/ng-update/update-schematic.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ targets a specific Angular CDK or Angular Material version.
1414
As of right now, we have two migration entry-points that handle the breaking changes for the
1515
given target version:
1616

17-
| Target Version | Description |
18-
|----------------|-------------|
17+
| Target Version | Description |
18+
|----------------|------------------------|
1919
| V6 | Upgrade from any version to v6.0.0 |
2020
| V7 | Upgrade from any version to v7.0.0 |
21+
| V8 | Upgrade from any version to v8.0.0 |
2122

2223
Note that the migrations run _in order_ if multiple versions are transitively targeted. For
2324
example, consider an application which uses Angular Material v5.0.0. In case the developer runs

src/cdk/schematics/testing/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ ts_library(
66
name = "testing",
77
module_name = "@angular/cdk/schematics/testing",
88
srcs = glob(["**/*.ts"]),
9+
tsconfig = "tsconfig.json",
910
deps = [
1011
"@matdeps//@angular-devkit/core",
1112
"@matdeps//@angular-devkit/schematics",
1213
"@matdeps//@schematics/angular",
1314
"@matdeps//@types/node",
1415
"@matdeps//@types/fs-extra",
16+
"@matdeps//@types/jasmine",
1517
"@matdeps//fs-extra",
1618
"@matdeps//rxjs",
1719
],

src/cdk/schematics/testing/test-case-setup.ts

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {TempScopedNodeJsSyncHost} from '@angular-devkit/core/node/testing';
1111
import * as virtualFs from '@angular-devkit/core/src/virtual-fs/host';
1212
import {SchematicTestRunner} from '@angular-devkit/schematics/testing';
1313
import {mkdirpSync, readFileSync, writeFileSync, removeSync} from 'fs-extra';
14-
import {dirname, join} from 'path';
14+
import {dirname, join, basename, relative, sep} from 'path';
1515
import {createTestApp, runPostScheduledTasks} from '../testing';
1616

1717
/** Reads the UTF8 content of the specified file. Normalizes the path and ensures that */
@@ -38,10 +38,9 @@ export function createFileSystemTestApp(runner: SchematicTestRunner) {
3838
}
3939

4040
export async function runTestCases(migrationName: string, collectionPath: string,
41-
inputs: {[name: string]: string}) {
41+
inputFiles: string[]) {
4242

4343
const runner = new SchematicTestRunner('schematics', collectionPath);
44-
const inputNames = Object.keys(inputs);
4544
const initialWorkingDir = process.cwd();
4645

4746
let logOutput = '';
@@ -51,11 +50,12 @@ export async function runTestCases(migrationName: string, collectionPath: string
5150

5251
// Write each test-case input to the file-system. This is necessary because otherwise
5352
// TSLint won't be able to pick up the test cases.
54-
inputNames.forEach(inputName => {
55-
const tempInputPath = join(tempPath, `projects/cdk-testing/src/test-cases/${inputName}.ts`);
53+
inputFiles.forEach(inputFilePath => {
54+
const inputTestName = basename(inputFilePath);
55+
const tempInputPath = join(tempPath, `projects/cdk-testing/src/test-cases/${inputTestName}.ts`);
5656

5757
mkdirpSync(dirname(tempInputPath));
58-
writeFileSync(tempInputPath, readFileContent(inputs[inputName]));
58+
writeFileSync(tempInputPath, readFileContent(inputFilePath));
5959
});
6060

6161
runner.runSchematic(migrationName, {}, appTree);
@@ -73,3 +73,68 @@ export async function runTestCases(migrationName: string, collectionPath: string
7373

7474
return {tempPath, logOutput, removeTempDir};
7575
}
76+
77+
/**
78+
* Resolves all test cases for specified path using Bazel's runfile manifest. Note that we
79+
* cannot just use "glob" since the test case files are not copied to the Bazel bin directory
80+
* and are just runfiles.
81+
*/
82+
export function findBazelVersionTestCases(basePath: string) {
83+
const testCasesMap = new Map<string, string[]>();
84+
const manifestPath = process.env['RUNFILES_MANIFEST_FILE']!;
85+
86+
// Read the Bazel runfiles manifest which contains a path mapping for each line. Read more
87+
// about this here: https://git.io/fhIZE
88+
readFileSync(manifestPath, 'utf8').split('\n').forEach(line => {
89+
const [runfilePath, realPath] = line.split(' ');
90+
91+
// In case the mapped runfile starts with the specified base path and ends with "_input.ts",
92+
// we store it in our result map because we assume that this is a test case.
93+
if (runfilePath.startsWith(basePath) && runfilePath.endsWith('_input.ts')) {
94+
// Determine the target version of this test case by just reading the first path segment
95+
// which is a "TargetVersion" (e.g. "v7", "v8")
96+
const version = relative(basePath, runfilePath).split(sep)[0];
97+
98+
testCasesMap.set(version, (testCasesMap.get(version) || []).concat(realPath));
99+
}
100+
});
101+
102+
return testCasesMap;
103+
}
104+
105+
/**
106+
* Sets up the specified test cases using Jasmine by creating the appropriate jasmine
107+
* spec definitions. This should be used within a "describe" jasmine closure.
108+
*/
109+
export function defineJasmineTestCases(versionName: string, collectionFile: string,
110+
inputFiles: string[] | undefined) {
111+
// No test cases for the given version are available. Skip setting up tests for that
112+
// version.
113+
if (!inputFiles) {
114+
return;
115+
}
116+
117+
let testCasesOutputPath: string;
118+
let cleanupTestApp: () => void;
119+
120+
beforeAll(async () => {
121+
const {tempPath, removeTempDir} =
122+
await runTestCases(`migration-${versionName}`, collectionFile, inputFiles);
123+
124+
testCasesOutputPath = join(tempPath, 'projects/cdk-testing/src/test-cases/');
125+
cleanupTestApp = removeTempDir;
126+
});
127+
128+
afterAll(() => cleanupTestApp());
129+
130+
// Iterates through every test case directory and generates a jasmine test block that will
131+
// verify that the update schematics properly updated the test input to the expected output.
132+
inputFiles.forEach(inputFile => {
133+
const inputTestName = basename(inputFile);
134+
135+
it(`should apply update schematics to test case: ${inputTestName}`, () => {
136+
expect(readFileContent(join(testCasesOutputPath, `${inputTestName}.ts`)))
137+
.toBe(readFileContent(inputFile.replace('_input', '_expected_output')));
138+
});
139+
});
140+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"compilerOptions": {
3+
"lib": ["es2015"],
4+
"types": ["node", "jasmine"]
5+
}
6+
}
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
1-
/** Path to the schematic collection that includes the Angular Material migrations. */
1+
import {defineJasmineTestCases, findBazelVersionTestCases} from '@angular/cdk/schematics/testing';
2+
import {getAllVersionNames} from '@angular/cdk/schematics';
3+
4+
/** Path to the schematic collection that includes the migrations. */
25
export const migrationCollection = require.resolve('../../migration.json');
6+
7+
describe('Material upgrade test cases', () => {
8+
9+
const versionNames = getAllVersionNames().map(versionName => versionName.toLowerCase());
10+
const testCasesMap = findBazelVersionTestCases(
11+
'angular_material/src/lib/schematics/ng-update/test-cases');
12+
13+
// Setup the test cases for each target version. The test cases will be automatically
14+
// detected through Bazel's runfiles manifest.
15+
versionNames.forEach(version => describe(`${version} update`, () => {
16+
defineJasmineTestCases(version, migrationCollection, testCasesMap.get(version));
17+
}));
18+
});

src/lib/schematics/ng-update/test-cases/misc/constructor-checks.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import {runTestCases} from '@angular/cdk/schematics/testing';
44
describe('constructor checks', () => {
55

66
it('should properly report invalid constructor expression signatures', async () => {
7-
const {logOutput, removeTempDir} = await runTestCases('migration-v6', migrationCollection, {
8-
'constructor-checks': require.resolve('./constructor-checks_input.ts')
9-
});
7+
const {logOutput, removeTempDir} = await runTestCases('migration-v6', migrationCollection,
8+
[require.resolve('./constructor-checks_input.ts')]);
109

1110
expect(logOutput).toMatch(/\[22.*Found "NativeDateAdapter"/,
1211
'Expected the constructor checks to report if an argument is not assignable.');

src/lib/schematics/ng-update/test-cases/misc/import-checks.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import {migrationCollection} from '../index.spec';
44
describe('v6 import misc checks', () => {
55

66
it('should report imports for deleted animation constants', async () => {
7-
const {logOutput, removeTempDir} = await runTestCases('migration-v6', migrationCollection, {
8-
'import-checks': require.resolve('./import-checks_input.ts')
9-
});
7+
const {logOutput, removeTempDir} = await runTestCases('migration-v6', migrationCollection,
8+
[require.resolve('./import-checks_input.ts')]);
109

1110
expect(logOutput).toMatch(/Found deprecated symbol "SHOW_ANIMATION"/);
1211
expect(logOutput).toMatch(/Found deprecated symbol "HIDE_ANIMATION"/);

0 commit comments

Comments
 (0)