Skip to content

Commit

Permalink
fix(material/schematics): migrate to mdc components selectively bug (#…
Browse files Browse the repository at this point in the history
…26427)

Fixes mdc-migration to migrate only the selected components.

(cherry picked from commit fba14dc)
  • Loading branch information
llorenspujol authored and mmalerba committed Feb 28, 2023
1 parent 1a33e83 commit 54d157f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,5 @@ export const PERMANENT_MIGRATORS: ComponentMigrator[] = [
styles: new TypographyHierarchyStylesMigrator(),
},
];

export const CORE_COMPONENTS = ['option', 'optgroup'];
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import {Migration, getPropertyNameText} from '@angular/cdk/schematics';
import {SchematicContext} from '@angular-devkit/schematics';
import {ComponentMigrator, LEGACY_MODULES} from '../index';
import {ComponentMigrator, CORE_COMPONENTS, LEGACY_MODULES} from '../index';
import * as ts from 'typescript';
import {ThemingStylesMigration} from '../theming-styles';
import {TemplateMigration} from '../template-migration';
Expand Down Expand Up @@ -65,6 +65,16 @@ export class RuntimeCodeMigration extends Migration<ComponentMigrator[], Schemat
});
}

private _importPathHasComponentToMigrate(importTextPath: string): boolean {
const lastImportName = importTextPath.split('/').slice(-1)[0];
return !!this.upgradeData.find(componentMigrator => {
return (
lastImportName.includes(componentMigrator.component) ||
(lastImportName === 'legacy-core' && CORE_COMPONENTS.includes(componentMigrator.component))
);
});
}

/** Finds the imported symbols in a file that need to be migrated. */
private _findImportsToMigrate(sourceFile: ts.SourceFile) {
const importSpecifiersToNewNames = new Map<ts.ImportSpecifier, string>();
Expand All @@ -77,7 +87,8 @@ export class RuntimeCodeMigration extends Migration<ComponentMigrator[], Schemat
ts.isStringLiteral(statement.moduleSpecifier) &&
statement.importClause?.namedBindings &&
ts.isNamedImports(statement.importClause.namedBindings) &&
LEGACY_MODULES.has(statement.moduleSpecifier.text)
LEGACY_MODULES.has(statement.moduleSpecifier.text) &&
this._importPathHasComponentToMigrate(statement.moduleSpecifier.text)
) {
statement.importClause.namedBindings.elements.forEach(element => {
const oldName = (element.propertyName || element.name).text;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,78 @@ describe('runtime code migration', () => {
);
});

it('should not replace imports from non selected components', async () => {
declareLibrarySymbols('legacy-button', 'export declare class MatLegacyButtonModule {};');
declareLibrarySymbols('legacy-checkbox', 'export declare class MatLegacyCheckboxModule {};');

await runMigrationTest(
`
import {NgModule} from '@angular/core';
import {MatLegacyButtonModule} from '@angular/material/legacy-button';
import {MatLegacyCheckboxModule} from '@angular/material/legacy-checkbox';
@NgModule({imports: [MatLegacyButtonModule, MatLegacyCheckboxModule]})
export class AppModule {}
`,
`
import {NgModule} from '@angular/core';
import {MatButtonModule} from '@angular/material/button';
import {MatLegacyCheckboxModule} from '@angular/material/legacy-checkbox';
@NgModule({imports: [MatButtonModule, MatLegacyCheckboxModule]})
export class AppModule {}
`,
);
});

it('should migrate legacy-core symbols when option or optgroup is choosen for migration', async () => {
declareLibrarySymbols('legacy-select', 'export declare class MatLegacySelectModule {};');

async function runMigrationSelectTest(oldFileContent: string, newFileContent: string) {
cliAppTree.overwrite(APP_MODULE_FILE, oldFileContent);
const tree = await migrateComponents(['select'], runner, cliAppTree);
expect(tree.readContent(APP_MODULE_FILE)).toBe(newFileContent);
}

await runMigrationSelectTest(
`
import {NgModule} from '@angular/core';
import {MatLegacySelectModule as MatSelectModule} from '@angular/material/legacy-select';
import {MatLegacyOptionModule as MatOptionModule, LEGACY_VERSION as VERSION} from '@angular/material/legacy-core';
@NgModule({imports: [MatSelectModule, MatOptionModule]})
export class AppModule {}
`,
`
import {NgModule} from '@angular/core';
import {MatSelectModule} from '@angular/material/select';
import {MatOptionModule, VERSION} from '@angular/material/core';
@NgModule({imports: [MatSelectModule, MatOptionModule]})
export class AppModule {}
`,
);
});

it('should not migrate legacy-core symbols when option or optgroup are not choosen for migration', async () => {
await runMigrationTest(
`
import {NgModule} from '@angular/core';
import {MatLegacyOptionModule as MatOptionModule, LEGACY_VERSION as VERSION} from '@angular/material/legacy-core';
@NgModule({imports: [MatOptionModule]})
export class AppModule {}
`,
`
import {NgModule} from '@angular/core';
import {MatLegacyOptionModule as MatOptionModule, LEGACY_VERSION as VERSION} from '@angular/material/legacy-core';
@NgModule({imports: [MatOptionModule]})
export class AppModule {}
`,
);
});

it('should migrate styles for a component', async () => {
await runMigrationTest(
`
Expand Down

0 comments on commit 54d157f

Please sign in to comment.