From 6afb07c8e16d7140ee5ddd266e34dc76fb8316bc Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sat, 1 Apr 2017 20:22:02 +0200 Subject: [PATCH] fix(compatibility): throw better error when wrong prefix is used Throws a slightly better error when the wrong prefix is used. The error now includes the node name of the offending element, which should make it easier to pinpoint the issue. --- .../core/compatibility/compatibility.spec.ts | 18 ++++++++---- src/lib/core/compatibility/compatibility.ts | 29 ++++++++++++++++--- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/lib/core/compatibility/compatibility.spec.ts b/src/lib/core/compatibility/compatibility.spec.ts index 479ee3b13bf0..6b490d07a4d6 100644 --- a/src/lib/core/compatibility/compatibility.spec.ts +++ b/src/lib/core/compatibility/compatibility.spec.ts @@ -4,8 +4,10 @@ import {MdCheckboxModule} from '../../checkbox/index'; import { NoConflictStyleCompatibilityMode, MAT_ELEMENTS_SELECTOR, - MD_ELEMENTS_SELECTOR + MD_ELEMENTS_SELECTOR, + MdCompatibilityInvalidPrefixError, } from './compatibility'; +import {wrappedErrorMessage} from '../testing/wrapped-error-message'; describe('Style compatibility', () => { @@ -32,9 +34,11 @@ describe('Style compatibility', () => { })); it('should throw an error when trying to use the "mat-" prefix', () => { + const expectedError = new MdCompatibilityInvalidPrefixError('mat', 'mat-checkbox'); + expect(() => { TestBed.createComponent(ComponentWithMatCheckbox); - }).toThrowError(/The "mat-" prefix cannot be used out of ng-material v1 compatibility mode/); + }).toThrowError(wrappedErrorMessage(expectedError)); }); }); @@ -53,9 +57,11 @@ describe('Style compatibility', () => { }); it('should throw an error when trying to use the "md-" prefix', () => { + const expectedError = new MdCompatibilityInvalidPrefixError('md', 'md-checkbox'); + expect(() => { TestBed.createComponent(ComponentWithMdCheckbox); - }).toThrowError(/The "md-" prefix cannot be used in ng-material v1 compatibility mode/); + }).toThrowError(wrappedErrorMessage(expectedError)); }); }); @@ -69,9 +75,11 @@ describe('Style compatibility', () => { })); it('should throw an error when using the "md-" prefix', () => { - expect(() => { + const expectedError = new MdCompatibilityInvalidPrefixError('md', 'md-checkbox'); + + expect(() => { TestBed.createComponent(ComponentWithMdCheckbox); - }).toThrowError(/The "md-" prefix cannot be used in ng-material v1 compatibility mode/); + }).toThrowError(wrappedErrorMessage(expectedError)); }); it('should not throw an error when using the "mat-" prefix', () => { diff --git a/src/lib/core/compatibility/compatibility.ts b/src/lib/core/compatibility/compatibility.ts index 341e5af7fdd6..6f7830d8f9c6 100644 --- a/src/lib/core/compatibility/compatibility.ts +++ b/src/lib/core/compatibility/compatibility.ts @@ -6,14 +6,29 @@ import { Inject, Optional, isDevMode, + ElementRef, } from '@angular/core'; import {DOCUMENT} from '@angular/platform-browser'; +import {MdError} from '../errors/error'; /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */ let hasDoneGlobalChecks = false; export const MATERIAL_COMPATIBILITY_MODE = new OpaqueToken('md-compatibility-mode'); +/** + * Exception thrown if the consumer has used an invalid Material prefix on a component. + * @docs-private + */ +export class MdCompatibilityInvalidPrefixError extends MdError { + constructor(prefix: string, nodeName: string) { + super( + `The "${prefix}-" prefix cannot be used in ng-material v1 compatibility mode. ` + + `It was used on an "${nodeName.toLowerCase()}" element.` + ); + } +} + /** Selector that matches all elements that may have style collisions with AngularJS Material. */ export const MAT_ELEMENTS_SELECTOR = ` [mat-button], @@ -137,9 +152,12 @@ export const MD_ELEMENTS_SELECTOR = ` /** Directive that enforces that the `mat-` prefix cannot be used. */ @Directive({selector: MAT_ELEMENTS_SELECTOR}) export class MatPrefixRejector { - constructor(@Optional() @Inject(MATERIAL_COMPATIBILITY_MODE) isCompatibilityMode: boolean) { + constructor( + @Optional() @Inject(MATERIAL_COMPATIBILITY_MODE) isCompatibilityMode: boolean, + elementRef: ElementRef) { + if (!isCompatibilityMode) { - throw Error('The "mat-" prefix cannot be used out of ng-material v1 compatibility mode.'); + throw new MdCompatibilityInvalidPrefixError('mat', elementRef.nativeElement.nodeName); } } } @@ -147,9 +165,12 @@ export class MatPrefixRejector { /** Directive that enforces that the `md-` prefix cannot be used. */ @Directive({selector: MD_ELEMENTS_SELECTOR}) export class MdPrefixRejector { - constructor(@Optional() @Inject(MATERIAL_COMPATIBILITY_MODE) isCompatibilityMode: boolean) { + constructor( + @Optional() @Inject(MATERIAL_COMPATIBILITY_MODE) isCompatibilityMode: boolean, + elementRef: ElementRef) { + if (isCompatibilityMode) { - throw Error('The "md-" prefix cannot be used in ng-material v1 compatibility mode.'); + throw new MdCompatibilityInvalidPrefixError('md', elementRef.nativeElement.nodeName); } } }