diff --git a/goldens/public-api/platform-browser/animations/animations.d.ts b/goldens/public-api/platform-browser/animations/animations.d.ts index 80b165214e..e9e7450991 100644 --- a/goldens/public-api/platform-browser/animations/animations.d.ts +++ b/goldens/public-api/platform-browser/animations/animations.d.ts @@ -1,6 +1,11 @@ export declare const ANIMATION_MODULE_TYPE: InjectionToken<"NoopAnimations" | "BrowserAnimations">; export declare class BrowserAnimationsModule { + static withConfig(config: BrowserAnimationsModuleConfig): ModuleWithProviders; +} + +export declare interface BrowserAnimationsModuleConfig { + disableAnimations?: boolean; } export declare class NoopAnimationsModule { diff --git a/goldens/size-tracking/aio-payloads.json b/goldens/size-tracking/aio-payloads.json index fea778e139..cc1710aea6 100755 --- a/goldens/size-tracking/aio-payloads.json +++ b/goldens/size-tracking/aio-payloads.json @@ -12,7 +12,7 @@ "master": { "uncompressed": { "runtime-es2015": 3033, - "main-es2015": 447894, + "main-es2015": 448055, "polyfills-es2015": 52493 } } @@ -21,7 +21,7 @@ "master": { "uncompressed": { "runtime-es2015": 3153, - "main-es2015": 432647, + "main-es2015": 433285, "polyfills-es2015": 52493 } } diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts index a73d153977..99338410d5 100644 --- a/packages/core/test/animation/animation_integration_spec.ts +++ b/packages/core/test/animation/animation_integration_spec.ts @@ -46,8 +46,7 @@ describe('animation tests', function() { {declarations: [SharedAnimationCmp], imports: [BrowserAnimationsModule]}); const fixture = TestBed.createComponent(SharedAnimationCmp); - const cmp = fixture.componentInstance; - expect(cmp.animationType).toEqual('BrowserAnimations'); + expect(fixture.componentInstance.animationType).toEqual('BrowserAnimations'); }); it('should hint at NoopAnimationsModule being used', () => { @@ -56,9 +55,20 @@ describe('animation tests', function() { {declarations: [SharedAnimationCmp], imports: [NoopAnimationsModule]}); const fixture = TestBed.createComponent(SharedAnimationCmp); - const cmp = fixture.componentInstance; - expect(cmp.animationType).toEqual('NoopAnimations'); + expect(fixture.componentInstance.animationType).toEqual('NoopAnimations'); }); + + it('should hint at NoopAnimationsModule being used when BrowserAnimationsModule is provided with disabled animations', + () => { + TestBed.resetTestingModule(); + TestBed.configureTestingModule({ + declarations: [SharedAnimationCmp], + imports: [BrowserAnimationsModule.withConfig({disableAnimations: true})] + }); + + const fixture = TestBed.createComponent(SharedAnimationCmp); + expect(fixture.componentInstance.animationType).toEqual('NoopAnimations'); + }); }); @Component({template: '

template text

'}) diff --git a/packages/platform-browser/animations/src/animations.ts b/packages/platform-browser/animations/src/animations.ts index 618c7f6b66..96b42f8ccd 100644 --- a/packages/platform-browser/animations/src/animations.ts +++ b/packages/platform-browser/animations/src/animations.ts @@ -11,7 +11,7 @@ * @description * Entry point for all animation APIs of the animation browser package. */ -export {BrowserAnimationsModule, NoopAnimationsModule} from './module'; +export {BrowserAnimationsModule, BrowserAnimationsModuleConfig, NoopAnimationsModule} from './module'; export {ANIMATION_MODULE_TYPE} from './providers'; diff --git a/packages/platform-browser/animations/src/module.ts b/packages/platform-browser/animations/src/module.ts index 89707cf0dc..bd854c35b4 100644 --- a/packages/platform-browser/animations/src/module.ts +++ b/packages/platform-browser/animations/src/module.ts @@ -5,11 +5,23 @@ * 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 {NgModule} from '@angular/core'; +import {ModuleWithProviders, NgModule} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {BROWSER_ANIMATIONS_PROVIDERS, BROWSER_NOOP_ANIMATIONS_PROVIDERS} from './providers'; +/** + * Object used to configure the behavior of {@link BrowserAnimationsModule} + * @publicApi + */ +export interface BrowserAnimationsModuleConfig { + /** + * Whether animations should be disabled. Passing this is identical to providing the + * `NoopAnimationsModule`, but it can be controlled based on a runtime value. + */ + disableAnimations?: boolean; +} + /** * Exports `BrowserModule` with additional [dependency-injection providers](guide/glossary#provider) * for use with animations. See [Animations](guide/animations). @@ -20,6 +32,30 @@ import {BROWSER_ANIMATIONS_PROVIDERS, BROWSER_NOOP_ANIMATIONS_PROVIDERS} from '. providers: BROWSER_ANIMATIONS_PROVIDERS, }) export class BrowserAnimationsModule { + /** + * Configures the module based on the specified object. + * + * @param config Object used to configure the behavior of the `BrowserAnimationsModule`. + * @see `BrowserAnimationsModuleConfig` + * + * @usageNotes + * When registering the `BrowserAnimationsModule`, you can use the `withConfig` + * function as follows: + * ``` + * @NgModule({ + * imports: [BrowserAnimationsModule.withConfig(config)] + * }) + * class MyNgModule {} + * ``` + */ + static withConfig(config: BrowserAnimationsModuleConfig): + ModuleWithProviders { + return { + ngModule: BrowserAnimationsModule, + providers: config.disableAnimations ? BROWSER_NOOP_ANIMATIONS_PROVIDERS : + BROWSER_ANIMATIONS_PROVIDERS + }; + } } /** diff --git a/packages/platform-browser/animations/test/noop_animations_module_spec.ts b/packages/platform-browser/animations/test/noop_animations_module_spec.ts index 2258c78880..6c18d9bf51 100644 --- a/packages/platform-browser/animations/test/noop_animations_module_spec.ts +++ b/packages/platform-browser/animations/test/noop_animations_module_spec.ts @@ -9,97 +9,121 @@ import {animate, style, transition, trigger} from '@angular/animations'; import {ɵAnimationEngine} from '@angular/animations/browser'; import {Component} from '@angular/core'; import {TestBed} from '@angular/core/testing'; -import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; -{ - describe('NoopAnimationsModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({imports: [NoopAnimationsModule]}); - }); +describe('NoopAnimationsModule', () => { + beforeEach(() => { + TestBed.configureTestingModule({imports: [NoopAnimationsModule]}); + }); - it('should flush and fire callbacks when the zone becomes stable', (async) => { - @Component({ - selector: 'my-cmp', - template: - '
', - animations: [trigger( - 'myAnimation', - [transition( - '* => state', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], - }) - class Cmp { - exp: any; - startEvent: any; - doneEvent: any; - onStart(event: any) { - this.startEvent = event; - } - onDone(event: any) { - this.doneEvent = event; - } + noopAnimationTests(); +}); + +describe('BrowserAnimationsModule with disableAnimations = true', () => { + beforeEach(() => { + TestBed.configureTestingModule( + {imports: [BrowserAnimationsModule.withConfig({disableAnimations: true})]}); + }); + + noopAnimationTests(); +}); + + +function noopAnimationTests() { + it('should flush and fire callbacks when the zone becomes stable', (async) => { + // This test is only meant to be run inside the browser. + if (isNode) { + async(); + return; + } + + @Component({ + selector: 'my-cmp', + template: + '
', + animations: [trigger( + 'myAnimation', + [transition( + '* => state', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], + }) + class Cmp { + exp: any; + startEvent: any; + doneEvent: any; + onStart(event: any) { + this.startEvent = event; } + onDone(event: any) { + this.doneEvent = event; + } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'state'; - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(cmp.startEvent.triggerName).toEqual('myAnimation'); - expect(cmp.startEvent.phaseName).toEqual('start'); - expect(cmp.doneEvent.triggerName).toEqual('myAnimation'); - expect(cmp.doneEvent.phaseName).toEqual('done'); - async(); - }); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'state'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(cmp.startEvent.triggerName).toEqual('myAnimation'); + expect(cmp.startEvent.phaseName).toEqual('start'); + expect(cmp.doneEvent.triggerName).toEqual('myAnimation'); + expect(cmp.doneEvent.phaseName).toEqual('done'); + async(); }); + }); - it('should handle leave animation callbacks even if the element is destroyed in the process', - (async) => { - @Component({ - selector: 'my-cmp', - template: - '
', - animations: [trigger( - 'myAnimation', - [transition( - ':leave', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], - }) - class Cmp { - exp: any; - startEvent: any; - doneEvent: any; - onStart(event: any) { - this.startEvent = event; - } - onDone(event: any) { - this.doneEvent = event; - } + it('should handle leave animation callbacks even if the element is destroyed in the process', + (async) => { + // This test is only meant to be run inside the browser. + if (isNode) { + async(); + return; + } + + @Component({ + selector: 'my-cmp', + template: + '
', + animations: [trigger( + 'myAnimation', + [transition( + ':leave', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], + }) + class Cmp { + exp: any; + startEvent: any; + doneEvent: any; + onStart(event: any) { + this.startEvent = event; } + onDone(event: any) { + this.doneEvent = event; + } + } - TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.inject(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + TestBed.configureTestingModule({declarations: [Cmp]}); + const engine = TestBed.inject(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = true; + cmp.exp = true; + fixture.detectChanges(); + fixture.whenStable().then(() => { + cmp.startEvent = null; + cmp.doneEvent = null; + + cmp.exp = false; fixture.detectChanges(); fixture.whenStable().then(() => { - cmp.startEvent = null; - cmp.doneEvent = null; - - cmp.exp = false; - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(cmp.startEvent.triggerName).toEqual('myAnimation'); - expect(cmp.startEvent.phaseName).toEqual('start'); - expect(cmp.startEvent.toState).toEqual('void'); - expect(cmp.doneEvent.triggerName).toEqual('myAnimation'); - expect(cmp.doneEvent.phaseName).toEqual('done'); - expect(cmp.doneEvent.toState).toEqual('void'); - async(); - }); + expect(cmp.startEvent.triggerName).toEqual('myAnimation'); + expect(cmp.startEvent.phaseName).toEqual('start'); + expect(cmp.startEvent.toState).toEqual('void'); + expect(cmp.doneEvent.triggerName).toEqual('myAnimation'); + expect(cmp.doneEvent.phaseName).toEqual('done'); + expect(cmp.doneEvent.toState).toEqual('void'); + async(); }); }); - }); + }); }