Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(schematics): add v9 migration rules for carousel and inject tokens #4469

Merged
merged 1 commit into from
Apr 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion schematics/ng-update/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { createUpgradeRule, TargetVersion } from '@angular/cdk/schematics';
import chalk from 'chalk';
import { ruleUpgradeData } from './upgrade-data';
import { CalendarTemplateRule } from './upgrade-rules/checks/calendar-input-rule';
import { CarouselTemplateRule } from "./upgrade-rules/checks/carousel-like-template-rule";
import { DropdownClassRule } from './upgrade-rules/checks/dropdown-class-rule';
import { DropdownTemplateRule } from './upgrade-rules/checks/dropdown-template-rule';
import { IconTemplateRule } from './upgrade-rules/checks/icon-template-rule';
import { InjectionTokenRule } from "./upgrade-rules/checks/injection-token-rule";
import { TooltipLikeTemplateRule } from './upgrade-rules/checks/tooltip-like-template-rule';

/** Entry point for the migration schematics with target of NG-ZORRO v7 */
Expand All @@ -22,7 +24,9 @@ export function updateToV9(): Rule {
DropdownTemplateRule,
DropdownClassRule,
IconTemplateRule,
CalendarTemplateRule
CalendarTemplateRule,
CarouselTemplateRule,
InjectionTokenRule
],
ruleUpgradeData,
postUpdate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
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';
import { SchematicsTestNGConfig, SchematicsTestTsConfig } from '../config';

describe('injection tokens migration', () => {
let runner: SchematicTestRunner;
let host: TempScopedNodeJsSyncHost;
let tree: UnitTestTree;
let tmpDirPath: string;
let previousWorkingDir: string;
let warnOutput: string[];

beforeEach(() => {
runner = new SchematicTestRunner('test', require.resolve('../../../migration.json'));
host = new TempScopedNodeJsSyncHost();
tree = new UnitTestTree(new HostTree(host));

writeFile('/tsconfig.json', JSON.stringify(SchematicsTestTsConfig));
writeFile('/angular.json', JSON.stringify(SchematicsTestNGConfig));

warnOutput = [];
runner.logger.subscribe(logEntry => {
if (logEntry.level === 'warn') {
warnOutput.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('Injection Tokens', () => {

it('should properly report invalid deprecated injection tokens', async() => {
writeFile('/index.ts', `
import { NZ_NOTIFICATION_CONFIG, NZ_MESSAGE_CONFIG, NZ_DEFAULT_EMPTY_CONTENT } from 'ng-zorro-antd';

`);
await runMigration();

const tokensWarn = [
'index.ts@2:16 - Found deprecated symbol "NZ_NOTIFICATION_CONFIG" which has been removed. Use "NZ_CONFIG" to ' +
'instead please.',
'index.ts@2:40 - Found deprecated symbol "NZ_MESSAGE_CONFIG" which has been removed. Use "NZ_CONFIG" to ' +
'instead please.',
'index.ts@2:59 - Found deprecated symbol "NZ_DEFAULT_EMPTY_CONTENT" which has been removed. Use "NZ_CONFIG" ' +
'to instead please.'
];

tokensWarn.forEach(warn => {
expect(warnOutput).toContain(warn);
});
});

it('should properly report invalid deprecated injection tokens whit secondary entry', async() => {
writeFile('/index.ts', `
import { NZ_NOTIFICATION_CONFIG} from 'ng-zorro-antd/notification';
import { NZ_DEFAULT_EMPTY_CONTENT } from 'ng-zorro-antd/empty';
import { NZ_MESSAGE_CONFIG } from 'ng-zorro-antd/message';

`);
await runMigration();

const tokensWarn = [
'index.ts@2:16 - Found deprecated symbol "NZ_NOTIFICATION_CONFIG" which has been removed. Use "NZ_CONFIG" ' +
'to instead please.',
'index.ts@3:16 - Found deprecated symbol "NZ_DEFAULT_EMPTY_CONTENT" which has been removed. Use "NZ_CONFIG" ' +
'to instead please.',
'index.ts@4:16 - Found deprecated symbol "NZ_MESSAGE_CONFIG" which has been removed. Use "NZ_CONFIG" to ' +
'instead please.'
];

tokensWarn.forEach(warn => {
expect(warnOutput).toContain(warn);
});
});

it('should not report invalid deprecated injection tokens in other package', async() => {
writeFile('/index.ts', `
import { NZ_NOTIFICATION_CONFIG} from 'other/notification';
import { NZ_DEFAULT_EMPTY_CONTENT } from 'other/empty';
import { NZ_MESSAGE_CONFIG } from 'other/message';
import { NZ_NOTIFICATION_CONFIG, NZ_MESSAGE_CONFIG, NZ_DEFAULT_EMPTY_CONTENT } from 'other';

`);
await runMigration();

expect(warnOutput.length).toBe(0);
});

});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
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';
import { SchematicsTestNGConfig, SchematicsTestTsConfig } from '../config';

describe('carousel migration', () => {
let runner: SchematicTestRunner;
let host: TempScopedNodeJsSyncHost;
let tree: UnitTestTree;
let tmpDirPath: string;
let previousWorkingDir: string;
let warnOutput: string[];

beforeEach(() => {
runner = new SchematicTestRunner('test', require.resolve('../../../migration.json'));
host = new TempScopedNodeJsSyncHost();
tree = new UnitTestTree(new HostTree(host));

writeFile('/tsconfig.json', JSON.stringify(SchematicsTestTsConfig));
writeFile('/angular.json', JSON.stringify(SchematicsTestNGConfig));

warnOutput = [];
runner.logger.subscribe(logEntry => {
if (logEntry.level === 'warn') {
warnOutput.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('Carousel', () => {

it('should properly report invalid deprecated input', async() => {
writeFile('/index.ts', `;
import {Component} from '@angular/core'
@Component({
template: \`
<nz-carousel [nzVertical]="true"></nz-carousel>
<nz-carousel nzVertical></nz-carousel>
\`
})
export class MyComp {
}`);
await runMigration();

expect(warnOutput).toContain('index.ts@6:24 - Found deprecated "[nzVertical]" input. Use "[nzDotPosition]" to ' +
'instead please.');
expect(warnOutput).toContain('index.ts@5:25 - Found deprecated "[nzVertical]" input. Use "[nzDotPosition]" to ' +
'instead please.');
});

});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { findInputsOnElementWithTag, MigrationRule, ResolvedResource, TargetVersion } from '@angular/cdk/schematics';

export class CarouselTemplateRule extends MigrationRule<null> {

ruleEnabled = this.targetVersion === TargetVersion.V9;

visitTemplate(template: ResolvedResource): void {

findInputsOnElementWithTag(template.content, 'nzVertical', ['nz-carousel'])
.forEach(offset => {
this.failures.push({
filePath: template.filePath,
position: template.getCharacterAndLineOfPosition(offset),
message: `Found deprecated "[nzVertical]" input. Use "[nzDotPosition]" to instead please.`
});
});

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { MigrationRule, TargetVersion } from '@angular/cdk/schematics';
import * as ts from 'typescript';
import { isNgZorroImportDeclaration } from "../../../utils/ng-update/module-specifiers";

export class InjectionTokenRule extends MigrationRule<null> {

ruleEnabled = this.targetVersion === TargetVersion.V9;

visitNode(node: ts.Node): void {
if (ts.isImportDeclaration(node)) {
this._visitImportDeclaration(node);
}
}

private _visitImportDeclaration(node: ts.ImportDeclaration): void {
if (!isNgZorroImportDeclaration(node) || !node.importClause ||
!node.importClause.namedBindings) {
return;
}

const namedBindings = node.importClause.namedBindings;

if (ts.isNamedImports(namedBindings)) {
this._checkInjectionToken(namedBindings);
}
}

private _checkInjectionToken(namedImports: ts.NamedImports): void {
namedImports.elements.filter(element => ts.isIdentifier(element.name)).forEach(element => {
const importName = element.name.text;

const deprecatedTokens = ['NZ_MESSAGE_CONFIG', 'NZ_NOTIFICATION_CONFIG', 'NZ_DEFAULT_EMPTY_CONTENT'];

if (deprecatedTokens.indexOf(importName) !== -1) {
this.createFailureAtNode(
element, `Found deprecated symbol "${importName}" which has been removed. Use "NZ_CONFIG" to instead please.`);
}
});
}
}
17 changes: 17 additions & 0 deletions schematics/utils/ng-update/module-specifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getImportDeclaration } from '@angular/cdk/schematics';
import * as ts from 'typescript';

export const materialModuleSpecifier = 'ng-zorro-antd';

export function isNgZorroImportDeclaration(node: ts.Node): boolean {
return isNgZorroDeclaration(getImportDeclaration(node));
}

function isNgZorroDeclaration(declaration: ts.ImportDeclaration|ts.ExportDeclaration): boolean {
if (!declaration.moduleSpecifier) {
return false;
}

const moduleSpecifier = declaration.moduleSpecifier.getText();
return moduleSpecifier.indexOf(materialModuleSpecifier) !== -1
}