Skip to content

Commit 6afe3f5

Browse files
devversionandrewseguin
authored andcommitted
refactor(schematics): add test cases for cdk ng-update (#13517)
1 parent d128fff commit 6afe3f5

28 files changed

+532
-126
lines changed

src/cdk/schematics/BUILD.bazel

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,20 @@ filegroup(
1616
ts_library(
1717
name = "schematics",
1818
module_name = "@angular/cdk/schematics",
19-
srcs = glob(["**/*.ts"], exclude=["**/files/**/*.ts", "**/*.spec.ts"]),
19+
srcs = glob(["**/*.ts"], exclude=[
20+
"**/files/**/*.ts",
21+
"**/*.spec.ts",
22+
"ng-update/test-cases/**/*",
23+
]),
2024
tsconfig = ":tsconfig.json",
2125
deps = [
2226
"@npm//@schematics/angular",
2327
"@npm//@angular-devkit/schematics",
24-
# TODO(devversion): Only include jasmine for test sources (See: tsconfig types).
28+
# TODO(devversion): Only include jasmine for test sources (See: tsconfig types).
2529
"@npm//@types/jasmine",
2630
"@npm//@types/node",
31+
# TODO(devversion): Similarly to "jasmine", we need to extract these into testing only.
32+
"@npm//fs-extra",
2733
"@npm//glob",
2834
"@npm//parse5",
2935
"@npm//rxjs",
@@ -45,7 +51,7 @@ npm_package(
4551
jasmine_node_test(
4652
name = "unit_tests",
4753
srcs = [":schematics_test_sources"],
48-
data = [":schematics_assets"],
54+
data = [":schematics_assets", ":schematics_test_cases"],
4955
)
5056

5157
ts_library(
@@ -64,3 +70,12 @@ ts_library(
6470
tsconfig = ":tsconfig.json",
6571
testonly = True,
6672
)
73+
74+
filegroup(
75+
name = "schematics_test_cases",
76+
srcs = glob([
77+
"ng-update/test-cases/**/*_input.ts",
78+
"ng-update/test-cases/**/*_expected_output.ts"
79+
]),
80+
testonly = True,
81+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/** Path to the schematic collection that includes the migrations. */
2+
export const migrationCollection = require.resolve('../../migration.json');
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {migrationCollection} from '../index.spec';
2+
import {runTestCases} from '../../../testing';
3+
4+
describe('v6 method call checks', () => {
5+
6+
it('should properly report invalid method calls', async () => {
7+
const {logOutput} = await runTestCases('migration-v6', migrationCollection, {
8+
'method-call-checks': require.resolve('./method-call-checks_input.ts')
9+
});
10+
11+
expect(logOutput)
12+
.toMatch(/\[15,.*Found call to "FocusMonitor\.monitor".*renderer.*has been removed/);
13+
expect(logOutput)
14+
.toMatch(/\[16,.*Found call to "FocusMonitor\.monitor".*renderer.*has been removed/);
15+
});
16+
});

src/lib/schematics/ng-update/test-cases/misc/method-call-checks_input.ts renamed to src/cdk/schematics/ng-update/test-cases/misc/method-call-checks_input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ class A implements AfterViewInit {
1515
this.focusMonitor.monitor(this.elementRef.nativeElement, this.renderer, true);
1616
this.self.a.monitor(this.elementRef.nativeElement, this.renderer, true);
1717
}
18-
}
18+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {join} from 'path';
2+
import {readFileContent, runTestCases} from '../../testing';
3+
import {migrationCollection} from './index.spec';
4+
5+
describe('v6 upgrade test cases', () => {
6+
7+
/**
8+
* Name of test cases that will be used to verify that update schematics properly update
9+
* a developers application.
10+
*/
11+
const testCases = [
12+
'v6/attribute-selectors',
13+
'v6/class-names',
14+
'v6/input-names',
15+
'v6/property-names',
16+
];
17+
18+
let testCasesOutputPath: string;
19+
20+
beforeAll(async () => {
21+
const testCaseInputs = testCases.reduce((inputs, testCaseName) => {
22+
inputs[testCaseName] = require.resolve(`./${testCaseName}_input.ts`);
23+
return inputs;
24+
}, {} as {[name: string]: string});
25+
26+
const {tempPath} = await runTestCases('migration-v6', migrationCollection, testCaseInputs);
27+
28+
testCasesOutputPath = join(tempPath, 'projects/cdk-testing/src/test-cases/');
29+
});
30+
31+
// Iterates through every test case directory and generates a jasmine test block that will
32+
// verify that the update schematics properly updated the test input to the expected output.
33+
testCases.forEach(testCaseName => {
34+
const expectedOutputPath = require.resolve(`./${testCaseName}_expected_output.ts`);
35+
36+
it(`should apply update schematics to test case: ${testCaseName}`, () => {
37+
expect(readFileContent(join(testCasesOutputPath, `${testCaseName}.ts`)))
38+
.toBe(readFileContent(expectedOutputPath));
39+
});
40+
});
41+
});
42+
43+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {Component} from '@angular/core';
2+
import {By} from '@angular/platform-browser';
3+
4+
const a = By.css('[cdkPortalOutlet]');
5+
const b = By.css('[cdkPortalOutlet]');
6+
7+
// These should not change because we only update string literals that are
8+
// inside of a call expression.
9+
const c = 'cdkPortalHost';
10+
const d = 'portalHost';
11+
12+
@Component({
13+
template: `
14+
<div cdkPortalOutlet="E"></div>
15+
<div [cdkPortalOutlet]="myPortal"></div>
16+
`,
17+
styles: [
18+
'[cdkPortalOutlet] {background: red}',
19+
'div[cdkPortalOutlet] {color: blue}'
20+
]
21+
})
22+
class E {}
23+
24+
@Component({
25+
template: `
26+
<div cdkPortalOutlet="F"></div>
27+
<div [cdkPortalOutlet]="myPortal"></div>
28+
`,
29+
styles: [
30+
'[cdkPortalOutlet] {background: red}',
31+
'div[cdkPortalOutlet] {color: blue}'
32+
]
33+
})
34+
class F {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {Component} from '@angular/core';
2+
import {By} from '@angular/platform-browser';
3+
4+
const a = By.css('[cdkPortalHost]');
5+
const b = By.css('[portalHost]');
6+
7+
// These should not change because we only update string literals that are
8+
// inside of a call expression.
9+
const c = 'cdkPortalHost';
10+
const d = 'portalHost';
11+
12+
@Component({
13+
template: `
14+
<div cdkPortalHost="E"></div>
15+
<div [cdkPortalHost]="myPortal"></div>
16+
`,
17+
styles: [
18+
'[cdkPortalHost] {background: red}',
19+
'div[cdkPortalHost] {color: blue}'
20+
]
21+
})
22+
class E {}
23+
24+
@Component({
25+
template: `
26+
<div portalHost="F"></div>
27+
<div [portalHost]="myPortal"></div>
28+
`,
29+
styles: [
30+
'[portalHost] {background: red}',
31+
'div[portalHost] {color: blue}'
32+
]
33+
})
34+
class F {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import {CdkConnectedOverlay, CdkOverlayOrigin} from '@angular/cdk/overlay';
2+
import {CdkObserveContent} from '@angular/cdk/observers';
3+
import {CdkTrapFocus} from '@angular/cdk/a11y';
4+
5+
const a = new CdkConnectedOverlay();
6+
const b = new CdkOverlayOrigin();
7+
const c = new CdkObserveContent();
8+
const d = new CdkTrapFocus();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import {ConnectedOverlayDirective, OverlayOrigin} from '@angular/cdk/overlay';
2+
import {ObserveContent} from '@angular/cdk/observers';
3+
import {FocusTrapDirective} from '@angular/cdk/a11y';
4+
5+
const a = new ConnectedOverlayDirective();
6+
const b = new OverlayOrigin();
7+
const c = new ObserveContent();
8+
const d = new FocusTrapDirective();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {Component} from '@angular/core';
2+
3+
@Component({
4+
template: `
5+
<ng-template cdkConnectedOverlay
6+
[cdkConnectedOverlayOrigin]="myOrigin"
7+
[cdkConnectedOverlayPositions]="myPositions"
8+
[cdkConnectedOverlayOffsetX]="myOffsetX"
9+
[cdkConnectedOverlayOffsetY]="myOffsetY"
10+
[cdkConnectedOverlayWidth]="myWidth"
11+
[cdkConnectedOverlayHeight]="myHeight"
12+
[cdkConnectedOverlayMinWidth]="myMinWidth"
13+
[cdkConnectedOverlayMinHeight]="myMinHeight"
14+
[cdkConnectedOverlayBackdropClass]="myBackdropClass"
15+
[cdkConnectedOverlayScrollStrategy]="myScrollStrategy"
16+
[cdkConnectedOverlayOpen]="isOpen"
17+
[cdkConnectedOverlayHasBackdrop]="hasBackdrop">
18+
</ng-template>
19+
`
20+
})
21+
class A {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {Component} from '@angular/core';
2+
3+
@Component({
4+
template: `
5+
<ng-template cdkConnectedOverlay
6+
[origin]="myOrigin"
7+
[positions]="myPositions"
8+
[offsetX]="myOffsetX"
9+
[offsetY]="myOffsetY"
10+
[width]="myWidth"
11+
[height]="myHeight"
12+
[minWidth]="myMinWidth"
13+
[minHeight]="myMinHeight"
14+
[backdropClass]="myBackdropClass"
15+
[scrollStrategy]="myScrollStrategy"
16+
[open]="isOpen"
17+
[hasBackdrop]="hasBackdrop">
18+
</ng-template>
19+
`
20+
})
21+
class A {}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
class CdkConnectedOverlay {
2+
_deprecatedOrigin: any;
3+
_deprecatedPositions: any;
4+
_deprecatedOffsetX: any;
5+
_deprecatedOffsetY: any;
6+
_deprecatedWidth: any;
7+
_deprecatedHeight: any;
8+
_deprecatedMinWidth: any;
9+
_deprecatedMinHeight: any;
10+
_deprecatedBackdropClass: any;
11+
_deprecatedScrollStrategy: any;
12+
_deprecatedOpen: any;
13+
_deprecatedHasBackdrop: any;
14+
}
15+
16+
class CdkPortalOutlet {
17+
_deprecatedPortal: any;
18+
_deprecatedPortalHost: any;
19+
}
20+
21+
class A {
22+
self = {me: this};
23+
24+
constructor(private a: CdkConnectedOverlay) {}
25+
26+
onAngularClick() {
27+
this.a.origin = '1';
28+
this.a.positions = '2';
29+
this.a.offsetX = '3';
30+
this.a.offsetY = '4';
31+
this.a.height = '5';
32+
33+
console.log(this.a.width || 10);
34+
console.log(this.a.minWidth || this.a.minHeight);
35+
36+
this.self.me.a.backdropClass = ['a', 'b', 'c'];
37+
38+
const x = ({test: true} || this.a);
39+
40+
if (this.isConnectedOverlay(x)) {
41+
x.scrollStrategy = 'myScrollStrategy';
42+
x.open = false;
43+
x.hasBackdrop = true;
44+
}
45+
}
46+
47+
isConnectedOverlay(val: any): val is CdkConnectedOverlay {
48+
return val instanceof CdkConnectedOverlay;
49+
}
50+
}
51+
52+
class B {
53+
self = {me: this};
54+
55+
constructor(protected a: CdkPortalOutlet) {}
56+
57+
onClick() {
58+
this.a.portal = this.a.portal = 'myNewPortal';
59+
60+
if (this.self.me.a) {
61+
console.log(this.a.portal || this.self.me.a.portal);
62+
}
63+
}
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
class CdkConnectedOverlay {
2+
_deprecatedOrigin: any;
3+
_deprecatedPositions: any;
4+
_deprecatedOffsetX: any;
5+
_deprecatedOffsetY: any;
6+
_deprecatedWidth: any;
7+
_deprecatedHeight: any;
8+
_deprecatedMinWidth: any;
9+
_deprecatedMinHeight: any;
10+
_deprecatedBackdropClass: any;
11+
_deprecatedScrollStrategy: any;
12+
_deprecatedOpen: any;
13+
_deprecatedHasBackdrop: any;
14+
}
15+
16+
class CdkPortalOutlet {
17+
_deprecatedPortal: any;
18+
_deprecatedPortalHost: any;
19+
}
20+
21+
class A {
22+
self = {me: this};
23+
24+
constructor(private a: CdkConnectedOverlay) {}
25+
26+
onAngularClick() {
27+
this.a._deprecatedOrigin = '1';
28+
this.a._deprecatedPositions = '2';
29+
this.a._deprecatedOffsetX = '3';
30+
this.a._deprecatedOffsetY = '4';
31+
this.a._deprecatedHeight = '5';
32+
33+
console.log(this.a._deprecatedWidth || 10);
34+
console.log(this.a._deprecatedMinWidth || this.a._deprecatedMinHeight);
35+
36+
this.self.me.a._deprecatedBackdropClass = ['a', 'b', 'c'];
37+
38+
const x = ({test: true} || this.a);
39+
40+
if (this.isConnectedOverlay(x)) {
41+
x._deprecatedScrollStrategy = 'myScrollStrategy';
42+
x._deprecatedOpen = false;
43+
x._deprecatedHasBackdrop = true;
44+
}
45+
}
46+
47+
isConnectedOverlay(val: any): val is CdkConnectedOverlay {
48+
return val instanceof CdkConnectedOverlay;
49+
}
50+
}
51+
52+
class B {
53+
self = {me: this};
54+
55+
constructor(protected a: CdkPortalOutlet) {}
56+
57+
onClick() {
58+
this.a._deprecatedPortal = this.a._deprecatedPortalHost = 'myNewPortal';
59+
60+
if (this.self.me.a) {
61+
console.log(this.a._deprecatedPortalHost || this.self.me.a._deprecatedPortal);
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)