Skip to content

feat(core): allow more granular control over sanity checks #16973

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

Merged
merged 1 commit into from
Sep 16, 2019
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
56 changes: 45 additions & 11 deletions src/material/core/common-behaviors/common-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,30 @@ import {VERSION as CDK_VERSION} from '@angular/cdk';
const VERSION = new Version('0.0.0-PLACEHOLDER');

/** @docs-private */
export function MATERIAL_SANITY_CHECKS_FACTORY(): boolean {
export function MATERIAL_SANITY_CHECKS_FACTORY(): SanityChecks {
return true;
}

/** Injection token that configures whether the Material sanity checks are enabled. */
export const MATERIAL_SANITY_CHECKS = new InjectionToken<boolean>('mat-sanity-checks', {
export const MATERIAL_SANITY_CHECKS = new InjectionToken<SanityChecks>('mat-sanity-checks', {
providedIn: 'root',
factory: MATERIAL_SANITY_CHECKS_FACTORY,
});

/**
* Possible sanity checks that can be enabled. If set to
* true/false, all checks will be enabled/disabled.
*/
export type SanityChecks = boolean | GranularSanityChecks;

/** Object that can be used to configure the sanity checks granularly. */
export interface GranularSanityChecks {
doctype: boolean;
theme: boolean;
version: boolean;
hammer: boolean;
}

/**
* Module that captures anything that should be loaded and/or run for *all* Angular Material
* components. This includes Bidi, etc.
Expand All @@ -51,21 +65,28 @@ export class MatCommonModule {
/** Reference to the global 'window' object. */
private _window = typeof window === 'object' && window ? window : null;

/** Configured sanity checks. */
private _sanityChecks: SanityChecks;

constructor(
@Optional() @Inject(MATERIAL_SANITY_CHECKS) private _sanityChecksEnabled: boolean,
@Optional() @Inject(MATERIAL_SANITY_CHECKS) sanityChecks: any,
@Optional() @Inject(HAMMER_LOADER) private _hammerLoader?: HammerLoader) {

if (this._areChecksEnabled() && !this._hasDoneGlobalChecks) {
// Note that `_sanityChecks` is typed to `any`, because AoT
// throws an error if we use the `SanityChecks` type directly.
this._sanityChecks = sanityChecks;

if (!this._hasDoneGlobalChecks) {
this._checkDoctypeIsDefined();
this._checkThemeIsPresent();
this._checkCdkVersionMatch();
this._hasDoneGlobalChecks = true;
}
}

/** Whether any sanity checks are enabled */
private _areChecksEnabled(): boolean {
return this._sanityChecksEnabled && isDevMode() && !this._isTestEnv();
/** Whether any sanity checks are enabled. */
private _checksAreEnabled(): boolean {
return isDevMode() && !this._isTestEnv();
}

/** Whether the code is running in tests. */
Expand All @@ -75,7 +96,10 @@ export class MatCommonModule {
}

private _checkDoctypeIsDefined(): void {
if (this._document && !this._document.doctype) {
const isEnabled = this._checksAreEnabled() &&
(this._sanityChecks === true || (this._sanityChecks as GranularSanityChecks).doctype);

if (isEnabled && this._document && !this._document.doctype) {
console.warn(
'Current document does not have a doctype. This may cause ' +
'some Angular Material components not to behave as expected.'
Expand All @@ -86,7 +110,11 @@ export class MatCommonModule {
private _checkThemeIsPresent(): void {
// We need to assert that the `body` is defined, because these checks run very early
// and the `body` won't be defined if the consumer put their scripts in the `head`.
if (!this._document || !this._document.body || typeof getComputedStyle !== 'function') {
const isDisabled = !this._checksAreEnabled() ||
(this._sanityChecks === false || !(this._sanityChecks as GranularSanityChecks).theme);

if (isDisabled || !this._document || !this._document.body ||
typeof getComputedStyle !== 'function') {
return;
}

Expand All @@ -113,7 +141,10 @@ export class MatCommonModule {

/** Checks whether the material version matches the cdk version */
private _checkCdkVersionMatch(): void {
if (VERSION.full !== CDK_VERSION.full) {
const isEnabled = this._checksAreEnabled() &&
(this._sanityChecks === true || (this._sanityChecks as GranularSanityChecks).version);

if (isEnabled && VERSION.full !== CDK_VERSION.full) {
console.warn(
'The Angular Material version (' + VERSION.full + ') does not match ' +
'the Angular CDK version (' + CDK_VERSION.full + ').\n' +
Expand All @@ -128,7 +159,10 @@ export class MatCommonModule {
return;
}

if (this._areChecksEnabled() && !(this._window as any)['Hammer'] && !this._hammerLoader) {
const isEnabled = this._checksAreEnabled() &&
(this._sanityChecks === true || (this._sanityChecks as GranularSanityChecks).hammer);

if (isEnabled && !(this._window as any)['Hammer'] && !this._hammerLoader) {
console.warn(
'Could not find HammerJS. Certain Angular Material components may not work correctly.');
}
Expand Down
7 changes: 6 additions & 1 deletion src/material/core/common-behaviors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/

export {MatCommonModule, MATERIAL_SANITY_CHECKS} from './common-module';
export {
MatCommonModule,
MATERIAL_SANITY_CHECKS,
SanityChecks,
GranularSanityChecks,
} from './common-module';
export {CanDisable, CanDisableCtor, mixinDisabled} from './disabled';
export {CanColor, CanColorCtor, mixinColor, ThemePalette} from './color';
export {CanDisableRipple, CanDisableRippleCtor, mixinDisableRipple} from './disable-ripple';
Expand Down
13 changes: 11 additions & 2 deletions tools/public_api_guard/material/core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ export declare class GestureConfig extends HammerGestureConfig {
buildHammer(element: HTMLElement): HammerInstance;
}

export interface GranularSanityChecks {
doctype: boolean;
hammer: boolean;
theme: boolean;
version: boolean;
}

export interface HammerInput {
center: {
x: number;
Expand Down Expand Up @@ -190,7 +197,7 @@ export declare const MAT_OPTION_PARENT_COMPONENT: InjectionToken<MatOptionParent
export declare const MAT_RIPPLE_GLOBAL_OPTIONS: InjectionToken<RippleGlobalOptions>;

export declare class MatCommonModule {
constructor(_sanityChecksEnabled: boolean, _hammerLoader?: HammerLoader | undefined);
constructor(sanityChecks: any, _hammerLoader?: HammerLoader | undefined);
_checkHammerIsAvailable(): void;
}

Expand All @@ -206,7 +213,7 @@ export declare type MatDateFormats = {
};
};

export declare const MATERIAL_SANITY_CHECKS: InjectionToken<boolean>;
export declare const MATERIAL_SANITY_CHECKS: InjectionToken<SanityChecks>;

export declare class MatLine {
}
Expand Down Expand Up @@ -412,6 +419,8 @@ export interface RippleTarget {
rippleDisabled: boolean;
}

export declare type SanityChecks = boolean | GranularSanityChecks;

export declare const JAN = 0, FEB = 1, MAR = 2, APR = 3, MAY = 4, JUN = 5, JUL = 6, AUG = 7, SEP = 8, OCT = 9, NOV = 10, DEC = 11;

export declare function setLines(lines: QueryList<MatLine>, element: ElementRef<HTMLElement>): void;
Expand Down