Skip to content

Commit

Permalink
fix(material/schematics): fix various issues with mdc-migration (#25772)
Browse files Browse the repository at this point in the history
* fix(material/schematics): add missing material/core transforms

* test(material/schematics): fix integration test diff output

* fix(material/schematics): delete legacy mixin when migrating if new mixin is already present

* fix(material/schematics): handle form-field appearance

* test(material/schematics): fix test errors in mdc migration sample app

* test(material/schematics): verify golden builds and doesn't contain 'legacy'
  • Loading branch information
mmalerba committed Oct 10, 2022
1 parent a231e9b commit a0ec4be
Show file tree
Hide file tree
Showing 27 changed files with 367 additions and 80 deletions.
10 changes: 10 additions & 0 deletions integration/mdc-migration/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ migration_test(
"sample-project/**/*",
]),
approve = False,
verify = [
"! grep" +
" --include=*.{ts,css,scss,html}" +
" --exclude-dir={node_modules,.angular,.yarn_cache_folder}" +
" -ir legacy" +
" || { echo \"Error: golden project contains 'legacy'.\" >&2; exit 1; }",
"yarn build",
# TODO(mmalerba): add back once slider tests pass.
# "yarn test",
],
)

migration_test(
Expand Down
2 changes: 1 addition & 1 deletion integration/mdc-migration/golden/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumError": "2mb"
},
{
"type": "anyComponentStyle",
Expand Down
6 changes: 5 additions & 1 deletion integration/mdc-migration/golden/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {MatSnackBarModule} from '@angular/material/snack-bar';
import {MatTableModule} from '@angular/material/table';
import {MatTabsModule} from '@angular/material/tabs';
import {MatTooltipModule} from '@angular/material/tooltip';
import {MatOptionModule, VERSION} from '@angular/material/core';
import {AutocompleteComponent} from './components/autocomplete/autocomplete.component';
import {ButtonComponent} from './components/button/button.component';
import {CardComponent} from './components/card/card.component';
Expand Down Expand Up @@ -94,9 +95,12 @@ import {TooltipComponent} from './components/tooltip/tooltip.component';
MatTableModule,
MatTabsModule,
MatTooltipModule,
MatOptionModule,
ReactiveFormsModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
export class AppModule {
version = VERSION;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ <h2>Form field example</h2>
<mat-form-field hintLabel="Max 10 characters" appearance="fill">
<mat-label>Enter some input</mat-label>
<input matInput #input maxlength="10" placeholder="Ex. Nougat">
<mat-hint align="end">{{input.value?.length || 0}}/10</mat-hint>
<mat-hint align="end">{{input.value.length}}/10</mat-hint>
</mat-form-field>
<mat-form-field appearance="outline"><input matInput></mat-form-field>
<mat-form-field><input matInput></mat-form-field>
<mat-form-field><input matInput></mat-form-field>
11 changes: 7 additions & 4 deletions integration/mdc-migration/golden/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat.all-component-typographies();
@include mat.legacy-core();
@include mat.all-component-typographies(mat.define-typography-config());
@include mat.core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
Expand All @@ -26,9 +26,11 @@ $sample-project-theme: mat.define-light-theme((
primary: $sample-project-primary,
accent: $sample-project-accent,
warn: $sample-project-warn,
)
),
typography: mat.define-typography-config(),
));

@include mat.core-theme($sample-project-theme);
@include mat.autocomplete-theme($sample-project-theme);
@include mat.button-theme($sample-project-theme);
@include mat.fab-theme($sample-project-theme);
Expand All @@ -45,13 +47,14 @@ $sample-project-theme: mat.define-light-theme((
@include mat.progress-bar-theme($sample-project-theme);
@include mat.progress-spinner-theme($sample-project-theme);
@include mat.radio-theme($sample-project-theme);
@include mat.legacy-select-theme($sample-project-theme);
@include mat.slide-toggle-theme($sample-project-theme);
@include mat.slider-theme($sample-project-theme);
@include mat.snack-bar-theme($sample-project-theme);
@include mat.table-theme($sample-project-theme);
@include mat.tabs-theme($sample-project-theme);
@include mat.tooltip-theme($sample-project-theme);
@include mat.option-theme($sample-project-theme);
@include mat.optgroup-theme($sample-project-theme);

/* You can add global styles to this file, and also import other style files */

Expand Down
6 changes: 2 additions & 4 deletions integration/mdc-migration/migration-test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ IGNORED_FILES = [
"yarn.lock",
]

def migration_test(name, srcs, approve):
def migration_test(name, srcs, approve, verify = []):
node_integration_test(
name = name,
srcs = srcs,
Expand All @@ -32,15 +32,13 @@ def migration_test(name, srcs, approve):
# TODO(devversion): determine if a solution/workaround could live in the test runner.
"yarn install --cache-folder .yarn_cache_folder/",
"yarn ng generate @angular/material:mdc-migration --components all",
# TODO(amysorto): add back once MDC components are in @angular/material
# "yarn test",
" ".join([
"$(rootpath :verify_golden)",
"%s" % approve,
"../golden",
"integration/mdc-migration/golden",
] + IGNORED_FILES),
],
] + verify,
data = [
":golden_project",
":test_project",
Expand Down
2 changes: 1 addition & 1 deletion integration/mdc-migration/sample-project/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumError": "2mb"
},
{
"type": "anyComponentStyle",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {MatLegacySnackBarModule as MatSnackBarModule} from '@angular/material/le
import {MatLegacyTableModule as MatTableModule} from '@angular/material/legacy-table';
import {MatLegacyTabsModule as MatTabsModule} from '@angular/material/legacy-tabs';
import {MatLegacyTooltipModule as MatTooltipModule} from '@angular/material/legacy-tooltip';
import {MatLegacyOptionModule, LEGACY_VERSION} from '@angular/material/legacy-core';
import {AutocompleteComponent} from './components/autocomplete/autocomplete.component';
import {ButtonComponent} from './components/button/button.component';
import {CardComponent} from './components/card/card.component';
Expand Down Expand Up @@ -94,9 +95,12 @@ import {TooltipComponent} from './components/tooltip/tooltip.component';
MatTableModule,
MatTabsModule,
MatTooltipModule,
MatLegacyOptionModule,
ReactiveFormsModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
export class AppModule {
version = LEGACY_VERSION;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ <h2>Form field example</h2>
<mat-form-field hintLabel="Max 10 characters" appearance="fill">
<mat-label>Enter some input</mat-label>
<input matInput #input maxlength="10" placeholder="Ex. Nougat">
<mat-hint align="end">{{input.value?.length || 0}}/10</mat-hint>
<mat-hint align="end">{{input.value.length}}/10</mat-hint>
</mat-form-field>
<mat-form-field appearance="outline"><input matInput></mat-form-field>
<mat-form-field appearance="standard"><input matInput></mat-form-field>
<mat-form-field appearance="legacy"><input matInput></mat-form-field>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatProgressSpinnerModule} from '@angular/material/legacy-progress-spinner';
import {MatLegacyProgressSpinnerModule as MatProgressSpinnerModule} from '@angular/material/legacy-progress-spinner';
import {ProgressSpinnerComponent} from './progress-spinner.component';

describe('ProgressSpinnerComponent', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatSlideToggleModule} from '@angular/material/legacy-slide-toggle';
import {MatLegacySlideToggleModule as MatSlideToggleModule} from '@angular/material/legacy-slide-toggle';
import {SlideToggleComponent} from './slide-toggle.component';

describe('SlideToggleComponent', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatSnackBarModule} from '@angular/material/legacy-snack-bar';
import {MatLegacySnackBarModule as MatSnackBarModule} from '@angular/material/legacy-snack-bar';
import {SnackBarComponent} from './snack-bar.component';

describe('SnackBarComponent', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatTableModule} from '@angular/material/legacy-table';
import {MatLegacyTableModule as MatTableModule} from '@angular/material/legacy-table';
import {TableComponent} from './table.component';

describe('TableComponent', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatTabsModule} from '@angular/material/legacy-tabs';
import {MatLegacyTabsModule as MatTabsModule} from '@angular/material/legacy-tabs';
import {TabsComponent} from './tabs.component';

describe('TabsComponent', () => {
Expand Down
8 changes: 6 additions & 2 deletions integration/mdc-migration/sample-project/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat.all-legacy-component-typographies();
@include mat.all-legacy-component-typographies(mat.define-legacy-typography-config());
@include mat.legacy-core();

// Define the palettes for your theme using the Material Design palettes available in palette.scss
Expand All @@ -26,9 +26,11 @@ $sample-project-theme: mat.define-light-theme((
primary: $sample-project-primary,
accent: $sample-project-accent,
warn: $sample-project-warn,
)
),
typography: mat.define-legacy-typography-config(),
));

@include mat.legacy-core-theme($sample-project-theme);
@include mat.legacy-autocomplete-theme($sample-project-theme);
@include mat.legacy-button-theme($sample-project-theme);
@include mat.legacy-card-theme($sample-project-theme);
Expand All @@ -49,6 +51,8 @@ $sample-project-theme: mat.define-light-theme((
@include mat.legacy-table-theme($sample-project-theme);
@include mat.legacy-tabs-theme($sample-project-theme);
@include mat.legacy-tooltip-theme($sample-project-theme);
@include mat.legacy-option-theme($sample-project-theme);
@include mat.legacy-optgroup-theme($sample-project-theme);

/* You can add global styles to this file, and also import other style files */

Expand Down
8 changes: 4 additions & 4 deletions integration/mdc-migration/verify-golden.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ async function compareFiles(
const [testContent, goldenContent] = await Promise.allSettled(contentPromises);
const diff = {
filename,
actual: getDiffValue(goldenStats, goldenContent),
expected: getDiffValue(testStats, testContent),
actual: getDiffValue(testStats, testContent),
expected: getDiffValue(goldenStats, goldenContent),
};
if (testStats.status === 'rejected' && goldenStats.status === 'rejected') {
return null; // Neither file exists.
Expand All @@ -92,9 +92,9 @@ function showDiffs(diffs: FileDiff[]) {
console.error(
[
''.padEnd(80, '='),
`----- ${diff.filename} (actual) `.padEnd(80, '-'),
`----- ${diff.filename} (this run) `.padEnd(80, '-'),
diff.actual,
`----- ${diff.filename} (expected) `.padEnd(80, '-'),
`----- ${diff.filename} (golden) `.padEnd(80, '-'),
diff.expected,
'',
].join('\n'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import * as compiler from '@angular/compiler';
import {TemplateMigrator} from '../../template-migrator';
import {addAttribute, visitElements} from '../../tree-traversal';
import {updateAttribute, visitElements} from '../../tree-traversal';
import {Update} from '../../../../../migration-utilities';

export class CardTemplateMigrator extends TemplateMigrator {
Expand All @@ -22,7 +22,7 @@ export class CardTemplateMigrator extends TemplateMigrator {

updates.push({
offset: node.startSourceSpan.start.offset,
updateFn: html => addAttribute(html, node, 'appearance', 'outlined'),
updateFn: html => updateAttribute(html, node, 'appearance', () => 'outlined'),
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {createTestApp, patchDevkitTreeToExposeTypeScript} from '@angular/cdk/schematics/testing';
import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing';
import {createNewTestRunner, migrateComponents, TEMPLATE_FILE} from '../test-setup-helper';

describe('form-field template migrator', () => {
let runner: SchematicTestRunner;
let cliAppTree: UnitTestTree;

async function runMigrationTest(oldFileContent: string, newFileContent: string) {
cliAppTree.overwrite(TEMPLATE_FILE, oldFileContent);
const tree = await migrateComponents(['form-field'], runner, cliAppTree);
expect(tree.readContent(TEMPLATE_FILE)).toBe(newFileContent);
}

beforeEach(async () => {
runner = createNewTestRunner();
cliAppTree = patchDevkitTreeToExposeTypeScript(await createTestApp(runner));
});

it('should not update other elements appearance', async () => {
await runMigrationTest(
'<mat-card appearance="raised"></mat-card>',
'<mat-card appearance="raised"></mat-card>',
);
});

it('should not update default appearance', async () => {
await runMigrationTest(
'<mat-form-field></mat-form-field>',
'<mat-form-field></mat-form-field>',
);
});

it('should not update outline appearance', async () => {
await runMigrationTest(
'<mat-form-field appearance="outline"></mat-form-field>',
'<mat-form-field appearance="outline"></mat-form-field>',
);
});

it('should not update fill appearance', async () => {
await runMigrationTest(
'<mat-form-field appearance="fill"></mat-form-field>',
'<mat-form-field appearance="fill"></mat-form-field>',
);
});

it('should update standard appearance', async () => {
await runMigrationTest(
'<mat-form-field appearance="standard"></mat-form-field>',
'<mat-form-field></mat-form-field>',
);
});

it('should update legacy appearance', async () => {
await runMigrationTest(
'<mat-form-field appearance="legacy"></mat-form-field>',
'<mat-form-field></mat-form-field>',
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import * as compiler from '@angular/compiler';
import {TemplateMigrator} from '../../template-migrator';
import {updateAttribute, visitElements} from '../../tree-traversal';
import {Update} from '../../../../../migration-utilities';

export class FormFieldTemplateMigrator extends TemplateMigrator {
getUpdates(ast: compiler.ParsedTemplate): Update[] {
const updates: Update[] = [];

visitElements(ast.nodes, (node: compiler.TmplAstElement) => {
if (node.name !== 'mat-form-field') {
return;
}

updates.push({
offset: node.startSourceSpan.start.offset,
updateFn: html =>
updateAttribute(html, node, 'appearance', old =>
['legacy', 'standard'].includes(old || '') ? null : old,
),
});
});

return updates;
}
}

0 comments on commit a0ec4be

Please sign in to comment.