-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(schematics): add v9 migration rules for dropdown (#4466)
- Loading branch information
Showing
6 changed files
with
304 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
schematics/ng-update/test-cases/v9/deprecated-class-dropdown.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { getSystemPath, normalize, virtualFs } from '@angular-devkit/core'; | ||
import { TempScopedNodeJsSyncHost } from '@angular-devkit/core/node/testing'; | ||
import { HostTree } from '@angular-devkit/schematics'; | ||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; | ||
import * as shx from 'shelljs'; | ||
|
||
describe('dropdown class migration', () => { | ||
let runner: SchematicTestRunner; | ||
let host: TempScopedNodeJsSyncHost; | ||
let tree: UnitTestTree; | ||
let tmpDirPath: string; | ||
let previousWorkingDir: string; | ||
let warnOutput: string[]; | ||
let errorOutput: string[]; | ||
|
||
beforeEach(() => { | ||
runner = new SchematicTestRunner('test', require.resolve('../../../migration.json')); | ||
host = new TempScopedNodeJsSyncHost(); | ||
tree = new UnitTestTree(new HostTree(host)); | ||
|
||
writeFile('/tsconfig.json', JSON.stringify({ | ||
compilerOptions: { | ||
experimentalDecorators: true, | ||
lib: ['es2015'] | ||
} | ||
})); | ||
writeFile('/angular.json', JSON.stringify({ | ||
projects: {t: {architect: {build: {options: {tsConfig: './tsconfig.json'}}}}} | ||
})); | ||
|
||
warnOutput = []; | ||
errorOutput = []; | ||
runner.logger.subscribe(logEntry => { | ||
if (logEntry.level === 'warn') { | ||
warnOutput.push(logEntry.message); | ||
} else if (logEntry.level === 'error') { | ||
errorOutput.push(logEntry.message); | ||
} | ||
}); | ||
|
||
previousWorkingDir = shx.pwd(); | ||
tmpDirPath = getSystemPath(host.root); | ||
|
||
shx.cd(tmpDirPath); | ||
|
||
writeFakeAngular(); | ||
}); | ||
|
||
afterEach(() => { | ||
shx.cd(previousWorkingDir); | ||
shx.rm('-r', tmpDirPath); | ||
}); | ||
|
||
function writeFakeAngular(): void { writeFile('/node_modules/@angular/core/index.d.ts', ``); } | ||
|
||
function writeFile(filePath: string, contents: string): void { | ||
host.sync.write(normalize(filePath), virtualFs.stringToFileBuffer(contents)); | ||
} | ||
|
||
// tslint:disable-next-line:no-any | ||
async function runMigration(): Promise<any> { | ||
await runner.runSchematicAsync('migration-v9', {}, tree).toPromise(); | ||
} | ||
|
||
describe('dropdown class', () => { | ||
|
||
it('should properly report invalid deprecated class', async() => { | ||
writeFile('/index.ts', ` | ||
import { Component, TemplateRef } from '@angular/core'; | ||
import { NzDropdownContextComponent, NzDropdownService, NzMenuItemDirective } from 'ng-zorro-antd'; | ||
@Component({ | ||
selector: 'nz-demo-dropdown-context-menu', | ||
template: \` | ||
<div | ||
style="background: rgb(190, 200, 200); padding: 32px;text-align: center" | ||
(contextmenu)="contextMenu($event, template)" | ||
> | ||
<ng-template #template> | ||
<ul nz-menu nzInDropDown (nzClick)="close($event)"> | ||
<li nz-menu-item>1st menu item</li> | ||
<li nz-submenu> | ||
<span title>sub menu</span> | ||
<ul> | ||
<li nz-menu-item>4th menu item</li> | ||
</ul> | ||
</li> | ||
</ul> | ||
</ng-template> | ||
<span style="color:#fff;font-size: 14px;">Context Menu</span> | ||
</div> | ||
\`, | ||
styles: [] | ||
}) | ||
export class NzDemoDropdownContextMenuComponent { | ||
private dropdown: NzDropdownContextComponent; | ||
contextMenu($event: MouseEvent, template: TemplateRef<void>): void { | ||
this.dropdown = this.nzDropdownService.create($event, template); | ||
} | ||
close(e: NzMenuItemDirective): void { | ||
console.log(e); | ||
this.dropdown.close(); | ||
} | ||
constructor(private nzDropdownService: NzDropdownService) {} | ||
}`); | ||
await runMigration(); | ||
|
||
const messages = [ | ||
'index.ts@3:16 - Found "NzDropdownContextComponent" which has been removed. Your code need to be updated.', | ||
'index.ts@3:44 - Found usage of "NzDropdownService" which has been removed. Please use "NzContextMenuService" ' + | ||
'instead.', | ||
'index.ts@29:27 - Found "NzDropdownContextComponent" which has been removed. Your code need to be updated.', | ||
'index.ts@40:48 - Found usage of "NzDropdownService" which has been removed. Please use "NzContextMenuService" ' + | ||
'instead.' | ||
]; | ||
|
||
messages.forEach(message => { | ||
expect(warnOutput).toContain( message); | ||
}) | ||
}); | ||
|
||
}); | ||
|
||
}); |
107 changes: 107 additions & 0 deletions
107
schematics/ng-update/test-cases/v9/deprecated-component-dropdown.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { getSystemPath, normalize, virtualFs } from '@angular-devkit/core'; | ||
import { TempScopedNodeJsSyncHost } from '@angular-devkit/core/node/testing'; | ||
import { HostTree } from '@angular-devkit/schematics'; | ||
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; | ||
import * as shx from 'shelljs'; | ||
|
||
describe('dropdown components migration', () => { | ||
let runner: SchematicTestRunner; | ||
let host: TempScopedNodeJsSyncHost; | ||
let tree: UnitTestTree; | ||
let tmpDirPath: string; | ||
let previousWorkingDir: string; | ||
let warnOutput: string[]; | ||
let errorOutput: string[]; | ||
|
||
beforeEach(() => { | ||
runner = new SchematicTestRunner('test', require.resolve('../../../migration.json')); | ||
host = new TempScopedNodeJsSyncHost(); | ||
tree = new UnitTestTree(new HostTree(host)); | ||
|
||
writeFile('/tsconfig.json', JSON.stringify({ | ||
compilerOptions: { | ||
experimentalDecorators: true, | ||
lib: ['es2015'] | ||
} | ||
})); | ||
writeFile('/angular.json', JSON.stringify({ | ||
projects: {t: {architect: {build: {options: {tsConfig: './tsconfig.json'}}}}} | ||
})); | ||
|
||
warnOutput = []; | ||
errorOutput = []; | ||
runner.logger.subscribe(logEntry => { | ||
if (logEntry.level === 'warn') { | ||
warnOutput.push(logEntry.message); | ||
} else if (logEntry.level === 'error') { | ||
errorOutput.push(logEntry.message); | ||
} | ||
}); | ||
|
||
previousWorkingDir = shx.pwd(); | ||
tmpDirPath = getSystemPath(host.root); | ||
|
||
shx.cd(tmpDirPath); | ||
|
||
writeFakeAngular(); | ||
}); | ||
|
||
afterEach(() => { | ||
shx.cd(previousWorkingDir); | ||
shx.rm('-r', tmpDirPath); | ||
}); | ||
|
||
function writeFakeAngular(): void { writeFile('/node_modules/@angular/core/index.d.ts', ``); } | ||
|
||
function writeFile(filePath: string, contents: string): void { | ||
host.sync.write(normalize(filePath), virtualFs.stringToFileBuffer(contents)); | ||
} | ||
|
||
// tslint:disable-next-line:no-any | ||
async function runMigration(): Promise<any> { | ||
await runner.runSchematicAsync('migration-v9', {}, tree).toPromise(); | ||
} | ||
|
||
describe('dropdown components', () => { | ||
|
||
it('should properly report invalid deprecated component', async() => { | ||
writeFile('/index.ts', `; | ||
import {Component} from '@angular/core' | ||
@Component({ | ||
template: \` | ||
<nz-dropdown> | ||
<a nz-dropdown> Hover me <i nz-icon type="down"></i> </a> | ||
<ul nz-menu nzSelectable> | ||
<li nz-menu-item> | ||
<a>1st menu item</a> | ||
</li> | ||
</ul> | ||
</nz-dropdown> | ||
<nz-dropdown-button (nzClick)="log()"> | ||
DropDown | ||
<ul nz-menu> | ||
<li nz-menu-item>2nd menu item</li> | ||
<li nz-submenu> | ||
<span title>sub menu</span> | ||
<ul> | ||
<li nz-menu-item>3rd menu item</li> | ||
</ul> | ||
</li> | ||
</ul> | ||
</nz-dropdown-button> | ||
\` | ||
}) | ||
export class MyComp { | ||
log() {} | ||
}`); | ||
await runMigration(); | ||
|
||
expect(warnOutput).toContain( 'index.ts@5:9 - Found deprecated "<nz-dropdown>" component. ' + | ||
'Use "[nz-dropdown]" to instead please.'); | ||
expect(warnOutput).toContain( 'index.ts@13:9 - Found deprecated "<nz-dropdown-button>" component. ' + | ||
'Use "[nz-dropdown]" to instead please.'); | ||
}); | ||
|
||
}); | ||
|
||
}); |
28 changes: 28 additions & 0 deletions
28
schematics/ng-update/upgrade-rules/checks/dropdown-class-rule.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { MigrationRule, TargetVersion } from '@angular/cdk/schematics'; | ||
import * as ts from 'typescript'; | ||
|
||
export class DropdownClassRule extends MigrationRule<null> { | ||
|
||
ruleEnabled = this.targetVersion === TargetVersion.V9; | ||
|
||
visitNode(node: ts.Node): void { | ||
if (ts.isIdentifier(node)) { | ||
this._visitIdentifier(node); | ||
} | ||
} | ||
|
||
// tslint:disable-next-line:typedef | ||
private _visitIdentifier(identifier: ts.Identifier) { | ||
if (identifier.getText() === 'NzDropdownContextComponent') { | ||
this.createFailureAtNode( | ||
identifier, | ||
`Found "NzDropdownContextComponent" which has been removed. Your code need to be updated.`); | ||
} | ||
|
||
if (identifier.getText() === 'NzDropdownService') { | ||
this.createFailureAtNode( | ||
identifier, | ||
`Found usage of "NzDropdownService" which has been removed. Please use "NzContextMenuService" instead.`); | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
schematics/ng-update/upgrade-rules/checks/dropdown-template-rule.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { | ||
MigrationRule, | ||
ResolvedResource, TargetVersion | ||
} from '@angular/cdk/schematics'; | ||
import { findElementWithTag } from '../../../utils/ng-update/elements'; | ||
|
||
export class DropdownTemplateRule extends MigrationRule<null> { | ||
|
||
ruleEnabled = this.targetVersion === TargetVersion.V9; | ||
|
||
visitTemplate(template: ResolvedResource): void { | ||
|
||
const deprecatedComponent = (deprecated: string, instead: string) => { | ||
findElementWithTag(template.content, deprecated) | ||
.forEach(offset => { | ||
this.failures.push({ | ||
filePath: template.filePath, | ||
position: template.getCharacterAndLineOfPosition(offset), | ||
message: `Found deprecated "<${deprecated}>" component. Use "${instead}" to instead please.` | ||
}); | ||
}) | ||
}; | ||
|
||
deprecatedComponent('nz-dropdown', '[nz-dropdown]'); | ||
deprecatedComponent('nz-dropdown-button', '[nz-dropdown]'); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters