Skip to content

Commit 90af397

Browse files
devversionjelbourn
authored andcommitted
refactor(schematics): constructor check rule does not check all diagnostics (#13103)
* Currently if the node of a diagnostic couldn't be resolved, or the `className` is not part of the upgrade data, we accidentally `return` instead of `continuing` the `for of` loop that checks every determined diagnostic. * Adds missing upgrade data for a V7 merged breaking change: #8286 * Renames the `test-cases/v5` directory to `test-cases/v6` because the test-cases are running against version target: `v6`. * Adds test cases for V7 constructor checks data; test cases for property name change from #8286
1 parent 239c781 commit 90af397

22 files changed

+144
-21
lines changed

src/lib/schematics/update/material/data/property-names.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,21 @@ export interface MaterialPropertyNameData {
2222
}
2323

2424
export const propertyNames: VersionChanges<MaterialPropertyNameData> = {
25+
[TargetVersion.V7]: [
26+
{
27+
pr: 'https://github.com/angular/material2/pull/8286',
28+
changes: [
29+
{
30+
replace: 'onChange',
31+
replaceWith: 'changed',
32+
whitelist: {
33+
classes: ['SelectionModel']
34+
}
35+
}
36+
]
37+
}
38+
],
39+
2540
[TargetVersion.V6]: [
2641
{
2742
pr: 'https://github.com/angular/material2/pull/10161',

src/lib/schematics/update/rules/signature-check/constructorSignatureCheckRule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function visitSourceFile(context: WalkContext<null>, program: ts.Program) {
5353
const node = findConstructorNode(diagnostic, sourceFile);
5454

5555
if (!node) {
56-
return;
56+
continue;
5757
}
5858

5959
const classType = program.getTypeChecker().getTypeAtLocation(node.expression);
@@ -63,7 +63,7 @@ function visitSourceFile(context: WalkContext<null>, program: ts.Program) {
6363
// TODO(devversion): Consider handling pass-through classes better.
6464
// TODO(devversion): e.g. `export class CustomCalendar extends MatCalendar {}`
6565
if (!constructorChecks.includes(className)) {
66-
return;
66+
continue;
6767
}
6868

6969
const classSignatures = classType.getConstructSignatures()

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ describe('v5 constructor checks', () => {
1616

1717
await runPostScheduledTasks(runner, 'tslint-fix').toPromise();
1818

19+
expect(output).toMatch(/\[22.*Found "NativeDateAdapter"/,
20+
'Expected the constructor checks to report if an argument is not assignable.');
21+
expect(output).not.toMatch(/\[26.*Found "NativeDateAdapter".*/,
22+
'Expected the constructor to not report if an argument is assignable.');
23+
24+
expect(output).not.toMatch(/Found "NonMaterialClass".*: new NonMaterialClass\(\)/);
25+
1926
expect(output).toMatch(/Found "NativeDateAdapter".*super.*: super\(string, Platform\)/);
2027
expect(output).toMatch(/Found "NativeDateAdapter".*: new \w+\(string, Platform\)/);
2128

@@ -31,12 +38,11 @@ describe('v5 constructor checks', () => {
3138
expect(output).toMatch(/Found "MatCalendar".*super.*: super\(any, any, any, any\)/);
3239
expect(output).toMatch(/Found "MatCalendar".*: new \w+\(any, any, any, any\)/);
3340

34-
expect(output).toMatch(/\[97.*Found "NativeDateAdapter"/,
35-
'Expected the constructor checks to report if an argument is not assignable.');
36-
expect(output).not.toMatch(/\[99.*Found "NativeDateAdapter".*/,
37-
'Expected the constructor to not report if an argument is assignable.');
41+
expect(output).toMatch(/Found "MatDrawerContent".*super.*: super\((any, ){4}any\)/);
42+
expect(output).toMatch(/Found "MatDrawerContent".*: new \w+\((any, ){4}any\)/);
3843

39-
expect(output).not.toMatch(/Found "NonMaterialClass".*: new NonMaterialClass\(\)/);
44+
expect(output).toMatch(/Found "MatSidenavContent".*super.*: super\((any, ){4}any\)/);
45+
expect(output).toMatch(/Found "MatSidenavContent".*: new \w+\((any, ){4}any\)/);
4046
});
4147
});
4248

src/lib/schematics/update/test-cases/misc/constructor-checks_input.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ class MatAutocomplete {
1717
constructor(_changeDetector: any, _elementRef: any, _defaults: string[]) {}
1818
}
1919

20+
class NonMaterialClass {}
21+
22+
const _t1 = new NativeDateAdapter('b', 'invalid-argument');
23+
24+
const _t2 = new NativeDateAdapter('a', {IOS: true});
25+
26+
const _t3 = new NonMaterialClass('invalid-argument');
27+
2028
class MatTooltip {
2129
constructor(
2230
private _overlay: any,
@@ -40,10 +48,20 @@ class MatCalendar {
4048
constructor(_intl: any, _adapter: any, _formats: any, _changeDetector: any) {}
4149
}
4250

43-
class NonMaterialClass {}
51+
class MatDrawerContent {
52+
constructor (_cd: any,
53+
_container: any,
54+
_elementRef: any,
55+
_scrollDispatcher: any,
56+
_ngZone: any) {}
57+
}
4458

45-
class DelegateClass {
46-
constructor(_adapter: NativeDateAdapter) {}
59+
class MatSidenavContent {
60+
constructor (_cd: any,
61+
_container: any,
62+
_elementRef: any,
63+
_scrollDispatcher: any,
64+
_ngZone: any) {}
4765
}
4866

4967
/* Actual test case using the previously defined definitions. */
@@ -94,8 +112,18 @@ class E extends MatCalendar {
94112

95113
const _E = new MatCalendar({}, {}, {}, {}, {}, {}, {});
96114

97-
const _F = new NativeDateAdapter('b', 'invalid-argument');
115+
class F extends MatDrawerContent {
116+
constructor(changeDetectorRef: any, container: any) {
117+
super(changeDetectorRef, container);
118+
}
119+
}
120+
121+
const _F = new MatDrawerContent({}, 'container');
98122

99-
const _G = new NativeDateAdapter('a', {IOS: true});
123+
class G extends MatSidenavContent {
124+
constructor(changeDetectorRef: any, container: any) {
125+
super(changeDetectorRef, container);
126+
}
127+
}
100128

101-
const _H = new NonMaterialClass('invalid-argument');
129+
const _G = new MatSidenavContent({}, 'container');

src/lib/schematics/update/test-cases/v5-test-cases.spec.ts renamed to src/lib/schematics/update/test-cases/v6-test-cases.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ import {runPostScheduledTasks} from '../../test-setup/post-scheduled-tasks';
33
import {migrationCollection} from '../../test-setup/test-app';
44
import {createTestAppWithTestCase, readFileContent, resolveBazelDataFile} from './index.spec';
55

6-
describe('v5 test cases', () => {
6+
describe('v6 upgrade test cases', () => {
77

88
/**
99
* Name of test cases that will be used to verify that update schematics properly update
1010
* a developers application.
1111
*/
1212
const testCases = [
13-
'v5/attribute-selectors',
14-
'v5/class-names',
15-
'v5/css-names',
16-
'v5/element-selectors',
17-
'v5/input-names',
18-
'v5/output-names',
19-
'v5/property-names',
13+
'v6/attribute-selectors',
14+
'v6/class-names',
15+
'v6/css-names',
16+
'v6/element-selectors',
17+
'v6/input-names',
18+
'v6/output-names',
19+
'v6/property-names',
2020
];
2121

2222
// Iterates through every test case directory and generates a jasmine test block that will
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {SchematicTestRunner} from '@angular-devkit/schematics/testing';
2+
import {runPostScheduledTasks} from '../../test-setup/post-scheduled-tasks';
3+
import {migrationCollection} from '../../test-setup/test-app';
4+
import {createTestAppWithTestCase, readFileContent, resolveBazelDataFile} from './index.spec';
5+
6+
describe('v7 upgrade test cases', () => {
7+
8+
/**
9+
* Name of test cases that will be used to verify that update schematics properly update
10+
* a developers application.
11+
*/
12+
const testCases = [
13+
'v7/property-names'
14+
];
15+
16+
// Iterates through every test case directory and generates a jasmine test block that will
17+
// verify that the update schematics properly update the test input to the expected output.
18+
testCases.forEach(testCaseName => {
19+
const inputPath = resolveBazelDataFile(`${testCaseName}_input.ts`);
20+
const expectedOutputPath = resolveBazelDataFile(`${testCaseName}_expected_output.ts`);
21+
22+
it(`should apply update schematics to test case: ${testCaseName}`, () => {
23+
const runner = new SchematicTestRunner('schematics', migrationCollection);
24+
25+
runner.runSchematic('migration-02', {}, createTestAppWithTestCase(inputPath));
26+
27+
// Run the scheduled TSLint fix task from the update schematic. This task is responsible for
28+
// identifying outdated code parts and performs the fixes. Since tasks won't run automatically
29+
// within a `SchematicTestRunner`, we manually need to run the scheduled task.
30+
return runPostScheduledTasks(runner, 'tslint-fix').toPromise().then(() => {
31+
expect(readFileContent('projects/material/src/main.ts'))
32+
.toBe(readFileContent(expectedOutputPath));
33+
});
34+
});
35+
});
36+
});
37+
38+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {EventEmitter, OnInit} from '@angular/core';
2+
3+
class SelectionModel {
4+
onChange = new EventEmitter<void>();
5+
}
6+
7+
/* Actual test case using the previously defined definitions. */
8+
9+
class A implements OnInit {
10+
self = {me: this};
11+
12+
constructor(private a: SelectionModel) {}
13+
14+
ngOnInit() {
15+
this.a.changed.subscribe(() => console.log('Changed'));
16+
this.self.me.a.changed.subscribe(() => console.log('Changed 2'));
17+
}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {EventEmitter, OnInit} from '@angular/core';
2+
3+
class SelectionModel {
4+
onChange = new EventEmitter<void>();
5+
}
6+
7+
/* Actual test case using the previously defined definitions. */
8+
9+
class A implements OnInit {
10+
self = {me: this};
11+
12+
constructor(private a: SelectionModel) {}
13+
14+
ngOnInit() {
15+
this.a.onChange.subscribe(() => console.log('Changed'));
16+
this.self.me.a.onChange.subscribe(() => console.log('Changed 2'));
17+
}
18+
}

0 commit comments

Comments
 (0)