diff --git a/packages/core/test/BUILD.bazel b/packages/core/test/BUILD.bazel index 766e727710..8d066f005b 100644 --- a/packages/core/test/BUILD.bazel +++ b/packages/core/test/BUILD.bazel @@ -66,9 +66,6 @@ jasmine_node_test( ts_web_test_suite( name = "test_web", - tags = [ - "fixme-ivy-aot", - ], deps = [ ":test_lib", ], diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts index 4aafeca023..7c78d43f76 100644 --- a/packages/core/test/animation/animation_integration_spec.ts +++ b/packages/core/test/animation/animation_integration_spec.ts @@ -5,15 +5,15 @@ * 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 {AUTO_STYLE, AnimationEvent, AnimationOptions, AnimationPlayer, NoopAnimationPlayer, animate, animateChild, group, keyframes, query, state, style, transition, trigger, ɵPRE_STYLE as PRE_STYLE} from '@angular/animations'; +import {AUTO_STYLE, AnimationEvent, AnimationOptions, animate, animateChild, group, keyframes, query, state, style, transition, trigger, ɵPRE_STYLE as PRE_STYLE} from '@angular/animations'; import {AnimationDriver, ɵAnimationEngine, ɵNoopAnimationDriver as NoopAnimationDriver} from '@angular/animations/browser'; import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/browser/testing'; import {ChangeDetectorRef, Component, HostBinding, HostListener, Inject, RendererFactory2, ViewChild} from '@angular/core'; +import {TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing'; import {ɵDomRendererFactory2} from '@angular/platform-browser'; import {ANIMATION_MODULE_TYPE, BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; - -import {TestBed, fakeAsync, flushMicrotasks} from '../../testing'; +import {fixmeIvy} from '@angular/private/testing'; const DEFAULT_NAMESPACE_ID = 'id'; const DEFAULT_COMPONENT_ID = '1'; @@ -66,124 +66,127 @@ const DEFAULT_COMPONENT_ID = '1'; } describe('fakeAsync testing', () => { - it('should only require one flushMicrotasks call to kick off animation callbacks', - fakeAsync(() => { - @Component({ - selector: 'cmp', - template: ` + fixmeIvy('unknown').it( + 'should only require one flushMicrotasks call to kick off animation callbacks', + fakeAsync(() => { + @Component({ + selector: 'cmp', + template: `
`, - animations: [trigger( - 'myAnimation', - [transition('* => on, * => off', [animate(1000, style({opacity: 1}))])])] - }) - class Cmp { - exp: any = false; - status: string = ''; - cb(status: string) { this.status = status; } - } + animations: [trigger( + 'myAnimation', + [transition('* => on, * => off', [animate(1000, style({opacity: 1}))])])] + }) + class Cmp { + exp: any = false; + status: string = ''; + cb(status: string) { this.status = status; } + } - TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'on'; - fixture.detectChanges(); - expect(cmp.status).toEqual(''); + TestBed.configureTestingModule({declarations: [Cmp]}); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'on'; + fixture.detectChanges(); + expect(cmp.status).toEqual(''); - flushMicrotasks(); - expect(cmp.status).toEqual('start'); + flushMicrotasks(); + expect(cmp.status).toEqual('start'); - let player = MockAnimationDriver.log.pop() !; - player.finish(); - expect(cmp.status).toEqual('done'); + let player = MockAnimationDriver.log.pop() !; + player.finish(); + expect(cmp.status).toEqual('done'); - cmp.status = ''; - cmp.exp = 'off'; - fixture.detectChanges(); - expect(cmp.status).toEqual(''); + cmp.status = ''; + cmp.exp = 'off'; + fixture.detectChanges(); + expect(cmp.status).toEqual(''); - player = MockAnimationDriver.log.pop() !; - player.finish(); - expect(cmp.status).toEqual(''); - flushMicrotasks(); - expect(cmp.status).toEqual('done'); - })); + player = MockAnimationDriver.log.pop() !; + player.finish(); + expect(cmp.status).toEqual(''); + flushMicrotasks(); + expect(cmp.status).toEqual('done'); + })); - it('should always run .start callbacks before .done callbacks even for noop animations', - fakeAsync(() => { - @Component({ - selector: 'cmp', - template: ` + fixmeIvy('unknown').it( + 'should always run .start callbacks before .done callbacks even for noop animations', + fakeAsync(() => { + @Component({ + selector: 'cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - transition('* => go', []), - ]), - ] - }) - class Cmp { - exp: any = false; - log: string[] = []; - cb(status: string) { this.log.push(status); } - } + animations: [ + trigger( + 'myAnimation', + [ + transition('* => go', []), + ]), + ] + }) + class Cmp { + exp: any = false; + log: string[] = []; + cb(status: string) { this.log.push(status); } + } - TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'go'; - fixture.detectChanges(); - expect(cmp.log).toEqual([]); + TestBed.configureTestingModule({declarations: [Cmp]}); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'go'; + fixture.detectChanges(); + expect(cmp.log).toEqual([]); - flushMicrotasks(); - expect(cmp.log).toEqual(['start', 'done']); - })); + flushMicrotasks(); + expect(cmp.log).toEqual(['start', 'done']); + })); - it('should emit the correct totalTime value for a noop-animation', fakeAsync(() => { - @Component({ - selector: 'cmp', - template: ` + fixmeIvy('unknown').it( + 'should emit the correct totalTime value for a noop-animation', fakeAsync(() => { + @Component({ + selector: 'cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - transition( - '* => go', - [ - animate('1s', style({opacity: 0})), - ]), - ]), - ] - }) - class Cmp { - exp: any = false; - log: AnimationEvent[] = []; - cb(event: AnimationEvent) { this.log.push(event); } - } + animations: [ + trigger( + 'myAnimation', + [ + transition( + '* => go', + [ + animate('1s', style({opacity: 0})), + ]), + ]), + ] + }) + class Cmp { + exp: any = false; + log: AnimationEvent[] = []; + cb(event: AnimationEvent) { this.log.push(event); } + } - TestBed.configureTestingModule({ - declarations: [Cmp], - providers: [ - {provide: AnimationDriver, useClass: NoopAnimationDriver}, - ], - }); + TestBed.configureTestingModule({ + declarations: [Cmp], + providers: [ + {provide: AnimationDriver, useClass: NoopAnimationDriver}, + ], + }); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'go'; - fixture.detectChanges(); - expect(cmp.log).toEqual([]); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'go'; + fixture.detectChanges(); + expect(cmp.log).toEqual([]); - flushMicrotasks(); - expect(cmp.log.length).toEqual(2); - const [start, end] = cmp.log; - expect(start.totalTime).toEqual(1000); - expect(end.totalTime).toEqual(1000); - })); + flushMicrotasks(); + expect(cmp.log.length).toEqual(2); + const [start, end] = cmp.log; + expect(start.totalTime).toEqual(1000); + expect(end.totalTime).toEqual(1000); + })); }); describe('component fixture integration', () => { @@ -297,7 +300,7 @@ const DEFAULT_COMPONENT_ID = '1'; }); describe('animation triggers', () => { - it('should trigger a state change animation from void => state', () => { + fixmeIvy('unknown').it('should trigger a state change animation from void => state', () => { @Component({ selector: 'if-cmp', template: ` @@ -327,94 +330,96 @@ const DEFAULT_COMPONENT_ID = '1'; ]); }); - it('should allow a transition to use a function to determine what method to run', () => { - let valueToMatch = ''; - let capturedElement: any; - const transitionFn = (fromState: string, toState: string, element: any) => { - capturedElement = element; - return toState == valueToMatch; - }; + fixmeIvy('unknown').it( + 'should allow a transition to use a function to determine what method to run', () => { + let valueToMatch = ''; + let capturedElement: any; + const transitionFn = (fromState: string, toState: string, element: any) => { + capturedElement = element; + return toState == valueToMatch; + }; - @Component({ - selector: 'if-cmp', - template: '
', - animations: [ - trigger('myAnimation', [transition( - transitionFn, - [style({opacity: 0}), animate(1234, style({opacity: 1}))])]), - ] - }) - class Cmp { - @ViewChild('element') - element: any; - exp: any = ''; - } + @Component({ + selector: 'if-cmp', + template: '
', + animations: [ + trigger( + 'myAnimation', + [transition( + transitionFn, [style({opacity: 0}), animate(1234, style({opacity: 1}))])]), + ] + }) + class Cmp { + @ViewChild('element') + element: any; + exp: any = ''; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - valueToMatch = cmp.exp = 'something'; - fixture.detectChanges(); - const element = cmp.element.nativeElement; + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + valueToMatch = cmp.exp = 'something'; + fixture.detectChanges(); + const element = cmp.element.nativeElement; - let players = getLog(); - expect(players.length).toEqual(1); - let [p1] = players; - expect(p1.totalTime).toEqual(1234); - expect(capturedElement).toEqual(element); - resetLog(); + let players = getLog(); + expect(players.length).toEqual(1); + let [p1] = players; + expect(p1.totalTime).toEqual(1234); + expect(capturedElement).toEqual(element); + resetLog(); - valueToMatch = 'something-else'; - cmp.exp = 'this-wont-match'; - fixture.detectChanges(); + valueToMatch = 'something-else'; + cmp.exp = 'this-wont-match'; + fixture.detectChanges(); - players = getLog(); - expect(players.length).toEqual(0); - }); + players = getLog(); + expect(players.length).toEqual(0); + }); - it('should allow a transition to use a function to determine what method to run and expose any parameter values', - () => { - const transitionFn = - (fromState: string, toState: string, element: any, params: {[key: string]: any}) => { - return params['doMatch'] == true; - }; + fixmeIvy('unknown').it( + 'should allow a transition to use a function to determine what method to run and expose any parameter values', + () => { + const transitionFn = + (fromState: string, toState: string, element: any, + params: {[key: string]: any}) => { return params['doMatch'] == true; }; - @Component({ - selector: 'if-cmp', - template: '
', - animations: [ - trigger( - 'myAnimation', - [transition( - transitionFn, [style({opacity: 0}), animate(3333, style({opacity: 1}))])]), - ] - }) - class Cmp { - doMatch = false; - exp: any = ''; - } + @Component({ + selector: 'if-cmp', + template: '
', + animations: [ + trigger( + 'myAnimation', + [transition( + transitionFn, [style({opacity: 0}), animate(3333, style({opacity: 1}))])]), + ] + }) + class Cmp { + doMatch = false; + exp: any = ''; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.doMatch = true; - fixture.detectChanges(); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.doMatch = true; + fixture.detectChanges(); - let players = getLog(); - expect(players.length).toEqual(1); - let [p1] = players; - expect(p1.totalTime).toEqual(3333); - resetLog(); + let players = getLog(); + expect(players.length).toEqual(1); + let [p1] = players; + expect(p1.totalTime).toEqual(3333); + resetLog(); - cmp.doMatch = false; - cmp.exp = 'this-wont-match'; - fixture.detectChanges(); + cmp.doMatch = false; + cmp.exp = 'this-wont-match'; + fixture.detectChanges(); - players = getLog(); - expect(players.length).toEqual(0); - }); + players = getLog(); + expect(players.length).toEqual(0); + }); it('should allow a state value to be `0`', () => { @Component({ @@ -454,217 +459,223 @@ const DEFAULT_COMPONENT_ID = '1'; expect(player.duration).toEqual(1234); }); - it('should always cancel the previous transition if a follow-up transition is not matched', - fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should always cancel the previous transition if a follow-up transition is not matched', + fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [trigger( - 'myAnimation', - [transition( - 'a => b', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], - }) - class Cmp { - exp: any; - startEvent: any; - doneEvent: any; + animations: [trigger( + 'myAnimation', + [transition( + 'a => b', + [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], + }) + class Cmp { + exp: any; + startEvent: any; + doneEvent: any; - callback(event: any) { - if (event.phaseName == 'done') { - this.doneEvent = event; - } else { - this.startEvent = event; - } - } - } + callback(event: any) { + if (event.phaseName == 'done') { + this.doneEvent = event; + } else { + this.startEvent = event; + } + } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = 'a'; - fixture.detectChanges(); - engine.flush(); - expect(getLog().length).toEqual(0); - expect(engine.players.length).toEqual(0); + cmp.exp = 'a'; + fixture.detectChanges(); + engine.flush(); + expect(getLog().length).toEqual(0); + expect(engine.players.length).toEqual(0); - flushMicrotasks(); - expect(cmp.startEvent.toState).toEqual('a'); - expect(cmp.startEvent.totalTime).toEqual(0); - expect(cmp.startEvent.toState).toEqual('a'); - expect(cmp.startEvent.totalTime).toEqual(0); - resetLog(); + flushMicrotasks(); + expect(cmp.startEvent.toState).toEqual('a'); + expect(cmp.startEvent.totalTime).toEqual(0); + expect(cmp.startEvent.toState).toEqual('a'); + expect(cmp.startEvent.totalTime).toEqual(0); + resetLog(); - cmp.exp = 'b'; - fixture.detectChanges(); - engine.flush(); + cmp.exp = 'b'; + fixture.detectChanges(); + engine.flush(); - const players = getLog(); - expect(players.length).toEqual(1); - expect(engine.players.length).toEqual(1); + const players = getLog(); + expect(players.length).toEqual(1); + expect(engine.players.length).toEqual(1); - flushMicrotasks(); - expect(cmp.startEvent.toState).toEqual('b'); - expect(cmp.startEvent.totalTime).toEqual(500); - expect(cmp.startEvent.toState).toEqual('b'); - expect(cmp.startEvent.totalTime).toEqual(500); - resetLog(); + flushMicrotasks(); + expect(cmp.startEvent.toState).toEqual('b'); + expect(cmp.startEvent.totalTime).toEqual(500); + expect(cmp.startEvent.toState).toEqual('b'); + expect(cmp.startEvent.totalTime).toEqual(500); + resetLog(); - let completed = false; - players[0].onDone(() => completed = true); + let completed = false; + players[0].onDone(() => completed = true); - cmp.exp = 'c'; - fixture.detectChanges(); - engine.flush(); + cmp.exp = 'c'; + fixture.detectChanges(); + engine.flush(); - expect(engine.players.length).toEqual(0); - expect(getLog().length).toEqual(0); + expect(engine.players.length).toEqual(0); + expect(getLog().length).toEqual(0); - flushMicrotasks(); - expect(cmp.startEvent.toState).toEqual('c'); - expect(cmp.startEvent.totalTime).toEqual(0); - expect(cmp.startEvent.toState).toEqual('c'); - expect(cmp.startEvent.totalTime).toEqual(0); + flushMicrotasks(); + expect(cmp.startEvent.toState).toEqual('c'); + expect(cmp.startEvent.totalTime).toEqual(0); + expect(cmp.startEvent.toState).toEqual('c'); + expect(cmp.startEvent.totalTime).toEqual(0); - expect(completed).toBe(true); - })); + expect(completed).toBe(true); + })); - it('should always fire inner callbacks even if no animation is fired when a view is inserted', - fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should always fire inner callbacks even if no animation is fired when a view is inserted', + fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [ - trigger('myAnimation', []), - ] - }) - class Cmp { - exp: any = false; - log: string[] = []; - track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } - } + animations: [ + trigger('myAnimation', []), + ] + }) + class Cmp { + exp: any = false; + log: string[] = []; + track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - fixture.detectChanges(); - flushMicrotasks(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual([]); + expect(cmp.log).toEqual([]); - cmp.exp = true; - fixture.detectChanges(); - flushMicrotasks(); + cmp.exp = true; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual(['myAnimation-start', 'myAnimation-done']); - })); + expect(cmp.log).toEqual(['myAnimation-start', 'myAnimation-done']); + })); - it('should only turn a view removal as into `void` state transition', () => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should only turn a view removal as into `void` state transition', () => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [trigger( - 'myAnimation', - [ - transition( - 'void <=> *', [style({width: '0px'}), animate(1000, style({width: '100px'}))]), - transition( - '* => *', [style({height: '0px'}), animate(1000, style({height: '100px'}))]), - ])] - }) - class Cmp { - exp1: any = false; - exp2: any = false; - } + animations: [trigger( + 'myAnimation', + [ + transition( + 'void <=> *', + [style({width: '0px'}), animate(1000, style({width: '100px'}))]), + transition( + '* => *', + [style({height: '0px'}), animate(1000, style({height: '100px'}))]), + ])] + }) + class Cmp { + exp1: any = false; + exp2: any = false; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - function resetState() { - cmp.exp2 = 'something'; - fixture.detectChanges(); - engine.flush(); - resetLog(); - } + function resetState() { + cmp.exp2 = 'something'; + fixture.detectChanges(); + engine.flush(); + resetLog(); + } - cmp.exp1 = true; - cmp.exp2 = null; + cmp.exp1 = true; + cmp.exp2 = null; - fixture.detectChanges(); - engine.flush(); + fixture.detectChanges(); + engine.flush(); - expect(getLog().pop() !.keyframes).toEqual([ - {offset: 0, width: '0px'}, {offset: 1, width: '100px'} - ]); + expect(getLog().pop() !.keyframes).toEqual([ + {offset: 0, width: '0px'}, {offset: 1, width: '100px'} + ]); - resetState(); - cmp.exp2 = false; + resetState(); + cmp.exp2 = false; - fixture.detectChanges(); - engine.flush(); + fixture.detectChanges(); + engine.flush(); - expect(getLog().pop() !.keyframes).toEqual([ - {offset: 0, height: '0px'}, {offset: 1, height: '100px'} - ]); + expect(getLog().pop() !.keyframes).toEqual([ + {offset: 0, height: '0px'}, {offset: 1, height: '100px'} + ]); - resetState(); - cmp.exp2 = 0; + resetState(); + cmp.exp2 = 0; - fixture.detectChanges(); - engine.flush(); + fixture.detectChanges(); + engine.flush(); - expect(getLog().pop() !.keyframes).toEqual([ - {offset: 0, height: '0px'}, {offset: 1, height: '100px'} - ]); + expect(getLog().pop() !.keyframes).toEqual([ + {offset: 0, height: '0px'}, {offset: 1, height: '100px'} + ]); - resetState(); - cmp.exp2 = ''; + resetState(); + cmp.exp2 = ''; - fixture.detectChanges(); - engine.flush(); + fixture.detectChanges(); + engine.flush(); - expect(getLog().pop() !.keyframes).toEqual([ - {offset: 0, height: '0px'}, {offset: 1, height: '100px'} - ]); + expect(getLog().pop() !.keyframes).toEqual([ + {offset: 0, height: '0px'}, {offset: 1, height: '100px'} + ]); - resetState(); - cmp.exp2 = undefined; + resetState(); + cmp.exp2 = undefined; - fixture.detectChanges(); - engine.flush(); + fixture.detectChanges(); + engine.flush(); - expect(getLog().pop() !.keyframes).toEqual([ - {offset: 0, height: '0px'}, {offset: 1, height: '100px'} - ]); + expect(getLog().pop() !.keyframes).toEqual([ + {offset: 0, height: '0px'}, {offset: 1, height: '100px'} + ]); - resetState(); - cmp.exp1 = false; - cmp.exp2 = 'abc'; + resetState(); + cmp.exp1 = false; + cmp.exp2 = 'abc'; - fixture.detectChanges(); - engine.flush(); + fixture.detectChanges(); + engine.flush(); - expect(getLog().pop() !.keyframes).toEqual([ - {offset: 0, width: '0px'}, {offset: 1, width: '100px'} - ]); - }); + expect(getLog().pop() !.keyframes).toEqual([ + {offset: 0, width: '0px'}, {offset: 1, width: '100px'} + ]); + }); - it('should stringify boolean triggers to `1` and `0`', () => { + fixmeIvy('unknown').it('should stringify boolean triggers to `1` and `0`', () => { @Component({ selector: 'if-cmp', template: ` @@ -817,91 +828,95 @@ const DEFAULT_COMPONENT_ID = '1'; }); describe('host bindings', () => { - it('should trigger a state change animation from state => state on the component host element', - fakeAsync(() => { - @Component({ - selector: 'my-cmp', - template: '...', - animations: [trigger( - 'myAnimation', - [transition( - 'a => b', - [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], - }) - class Cmp { - @HostBinding('@myAnimation') - exp = 'a'; - } + fixmeIvy('unknown').it( + 'should trigger a state change animation from state => state on the component host element', + fakeAsync(() => { + @Component({ + selector: 'my-cmp', + template: '...', + animations: [trigger( + 'myAnimation', + [transition( + 'a => b', + [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], + }) + class Cmp { + @HostBinding('@myAnimation') + exp = 'a'; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - fixture.detectChanges(); - engine.flush(); - expect(getLog().length).toEqual(0); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); + engine.flush(); + expect(getLog().length).toEqual(0); - cmp.exp = 'b'; - fixture.detectChanges(); - engine.flush(); - expect(getLog().length).toEqual(1); + cmp.exp = 'b'; + fixture.detectChanges(); + engine.flush(); + expect(getLog().length).toEqual(1); - const data = getLog().pop() !; - expect(data.element).toEqual(fixture.elementRef.nativeElement); - expect(data.keyframes).toEqual([{offset: 0, opacity: '0'}, {offset: 1, opacity: '1'}]); - })); + const data = getLog().pop() !; + expect(data.element).toEqual(fixture.elementRef.nativeElement); + expect(data.keyframes).toEqual([ + {offset: 0, opacity: '0'}, {offset: 1, opacity: '1'} + ]); + })); // nonAnimationRenderer => animationRenderer - it('should trigger a leave animation when the inner components host binding updates', - fakeAsync(() => { - @Component({ - selector: 'parent-cmp', - template: ` + fixmeIvy('unknown').it( + 'should trigger a leave animation when the inner components host binding updates', + fakeAsync(() => { + @Component({ + selector: 'parent-cmp', + template: ` ` - }) - class ParentCmp { - public exp = true; - } + }) + class ParentCmp { + public exp = true; + } - @Component({ - selector: 'child-cmp', - template: '...', - animations: [trigger( - 'host', - [transition( - ':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])])] - }) - class ChildCmp { - @HostBinding('@host') public hostAnimation = true; - } + @Component({ + selector: 'child-cmp', + template: '...', + animations: [trigger( + 'host', + [transition( + ':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])])] + }) + class ChildCmp { + @HostBinding('@host') public hostAnimation = true; + } - TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); + TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ParentCmp); - const cmp = fixture.componentInstance; - fixture.detectChanges(); - engine.flush(); - expect(getLog().length).toEqual(0); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ParentCmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); + engine.flush(); + expect(getLog().length).toEqual(0); - cmp.exp = false; - fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.children.length).toBe(1); + cmp.exp = false; + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.children.length).toBe(1); - engine.flush(); - expect(getLog().length).toEqual(1); + engine.flush(); + expect(getLog().length).toEqual(1); - const [player] = getLog(); - expect(player.keyframes).toEqual([ - {opacity: '1', offset: 0}, - {opacity: '0', offset: 1}, - ]); + const [player] = getLog(); + expect(player.keyframes).toEqual([ + {opacity: '1', offset: 0}, + {opacity: '0', offset: 1}, + ]); - player.finish(); - expect(fixture.debugElement.nativeElement.children.length).toBe(0); - })); + player.finish(); + expect(fixture.debugElement.nativeElement.children.length).toBe(0); + })); // animationRenderer => nonAnimationRenderer it('should trigger a leave animation when the outer components element binding updates on the host component element', @@ -955,67 +970,69 @@ const DEFAULT_COMPONENT_ID = '1'; })); // animationRenderer => animationRenderer - it('should trigger a leave animation when both the inner and outer components trigger on the same element', - fakeAsync(() => { - @Component({ - selector: 'parent-cmp', - animations: [trigger( - 'host', - [transition( - ':leave', - [style({height: '100px'}), animate(1000, style({height: '0px'}))])])], - template: ` + fixmeIvy('unknown').it( + 'should trigger a leave animation when both the inner and outer components trigger on the same element', + fakeAsync(() => { + @Component({ + selector: 'parent-cmp', + animations: [trigger( + 'host', + [transition( + ':leave', + [style({height: '100px'}), animate(1000, style({height: '0px'}))])])], + template: ` ` - }) - class ParentCmp { - public exp = true; - } + }) + class ParentCmp { + public exp = true; + } - @Component({ - selector: 'child-cmp', - template: '...', - animations: [trigger( - 'host', [transition( - ':leave', - [style({width: '100px'}), animate(1000, style({width: '0px'}))])])] - }) - class ChildCmp { - @HostBinding('@host') public hostAnimation = true; - } + @Component({ + selector: 'child-cmp', + template: '...', + animations: [trigger( + 'host', + [transition( + ':leave', + [style({width: '100px'}), animate(1000, style({width: '0px'}))])])] + }) + class ChildCmp { + @HostBinding('@host') public hostAnimation = true; + } - TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); + TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ParentCmp); - const cmp = fixture.componentInstance; - fixture.detectChanges(); - engine.flush(); - expect(getLog().length).toEqual(0); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ParentCmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); + engine.flush(); + expect(getLog().length).toEqual(0); - cmp.exp = false; - fixture.detectChanges(); - expect(fixture.debugElement.nativeElement.children.length).toBe(1); + cmp.exp = false; + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.children.length).toBe(1); - engine.flush(); - expect(getLog().length).toEqual(2); + engine.flush(); + expect(getLog().length).toEqual(2); - const [p1, p2] = getLog(); - expect(p1.keyframes).toEqual([ - {width: '100px', offset: 0}, - {width: '0px', offset: 1}, - ]); + const [p1, p2] = getLog(); + expect(p1.keyframes).toEqual([ + {width: '100px', offset: 0}, + {width: '0px', offset: 1}, + ]); - expect(p2.keyframes).toEqual([ - {height: '100px', offset: 0}, - {height: '0px', offset: 1}, - ]); + expect(p2.keyframes).toEqual([ + {height: '100px', offset: 0}, + {height: '0px', offset: 1}, + ]); - p1.finish(); - p2.finish(); - flushMicrotasks(); - expect(fixture.debugElement.nativeElement.children.length).toBe(0); - })); + p1.finish(); + p2.finish(); + flushMicrotasks(); + expect(fixture.debugElement.nativeElement.children.length).toBe(0); + })); it('should not throw when the host element is removed and no animation triggers', fakeAsync(() => { @@ -1922,46 +1939,47 @@ const DEFAULT_COMPONENT_ID = '1'; expect(p.contains(c2)).toBeTruthy(); }); - it('should detect trigger changes based on object.value properties', () => { - @Component({ - selector: 'ani-cmp', - template: ` + fixmeIvy('unknown').it( + 'should detect trigger changes based on object.value properties', () => { + @Component({ + selector: 'ani-cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - transition('* => 1', [animate(1234, style({opacity: 0}))]), - transition('* => 2', [animate(5678, style({opacity: 0}))]), - ]), - ] - }) - class Cmp { - public exp: any; - } + animations: [ + trigger( + 'myAnimation', + [ + transition('* => 1', [animate(1234, style({opacity: 0}))]), + transition('* => 2', [animate(5678, style({opacity: 0}))]), + ]), + ] + }) + class Cmp { + public exp: any; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = '1'; - fixture.detectChanges(); - engine.flush(); - let players = getLog(); - expect(players.length).toEqual(1); - expect(players[0].duration).toEqual(1234); - resetLog(); + cmp.exp = '1'; + fixture.detectChanges(); + engine.flush(); + let players = getLog(); + expect(players.length).toEqual(1); + expect(players[0].duration).toEqual(1234); + resetLog(); - cmp.exp = '2'; - fixture.detectChanges(); - engine.flush(); - players = getLog(); - expect(players.length).toEqual(1); - expect(players[0].duration).toEqual(5678); - }); + cmp.exp = '2'; + fixture.detectChanges(); + engine.flush(); + players = getLog(); + expect(players.length).toEqual(1); + expect(players[0].duration).toEqual(5678); + }); it('should not render animations when the object expression value is the same as it was previously', () => { @@ -2006,60 +2024,61 @@ const DEFAULT_COMPONENT_ID = '1'; expect(players.length).toEqual(0); }); - it('should update the final state styles when params update even if the expression hasn\'t changed', - fakeAsync(() => { - @Component({ - selector: 'ani-cmp', - template: ` + fixmeIvy('unknown').it( + 'should update the final state styles when params update even if the expression hasn\'t changed', + fakeAsync(() => { + @Component({ + selector: 'ani-cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - state('*', style({color: '{{ color }}'}), {params: {color: 'black'}}), - transition('* => 1', animate(500)) - ]), - ] - }) - class Cmp { - public exp: any; - // TODO(issue/24571): remove '!'. - public color !: string | null; - } + animations: [ + trigger( + 'myAnimation', + [ + state('*', style({color: '{{ color }}'}), {params: {color: 'black'}}), + transition('* => 1', animate(500)) + ]), + ] + }) + class Cmp { + public exp: any; + // TODO(issue/24571): remove '!'. + public color !: string | null; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = '1'; - cmp.color = 'red'; - fixture.detectChanges(); - const player = getLog()[0] !; - const element = player.element; - player.finish(); + cmp.exp = '1'; + cmp.color = 'red'; + fixture.detectChanges(); + const player = getLog()[0] !; + const element = player.element; + player.finish(); - flushMicrotasks(); - expect(getDOM().hasStyle(element, 'color', 'red')).toBeTruthy(); + flushMicrotasks(); + expect(getDOM().hasStyle(element, 'color', 'red')).toBeTruthy(); - cmp.exp = '1'; - cmp.color = 'blue'; - fixture.detectChanges(); - resetLog(); + cmp.exp = '1'; + cmp.color = 'blue'; + fixture.detectChanges(); + resetLog(); - flushMicrotasks(); - expect(getDOM().hasStyle(element, 'color', 'blue')).toBeTruthy(); + flushMicrotasks(); + expect(getDOM().hasStyle(element, 'color', 'blue')).toBeTruthy(); - cmp.exp = '1'; - cmp.color = null; - fixture.detectChanges(); - resetLog(); + cmp.exp = '1'; + cmp.color = null; + fixture.detectChanges(); + resetLog(); - flushMicrotasks(); - expect(getDOM().hasStyle(element, 'color', 'black')).toBeTruthy(); - })); + flushMicrotasks(); + expect(getDOM().hasStyle(element, 'color', 'black')).toBeTruthy(); + })); it('should substitute in values if the provided state match is an object with values', () => { @Component({ @@ -2098,72 +2117,73 @@ const DEFAULT_COMPONENT_ID = '1'; ]); }); - it('should retain substituted styles on the element once the animation is complete if referenced in the final state', - fakeAsync(() => { - @Component({ - selector: 'ani-cmp', - template: ` + fixmeIvy('unknown').it( + 'should retain substituted styles on the element once the animation is complete if referenced in the final state', + fakeAsync(() => { + @Component({ + selector: 'ani-cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - state( - 'start', style({ - color: '{{ color }}', - fontSize: '{{ fontSize }}px', - width: '{{ width }}' - }), - {params: {color: 'red', fontSize: '200', width: '10px'}}), + animations: [ + trigger( + 'myAnimation', + [ + state( + 'start', style({ + color: '{{ color }}', + fontSize: '{{ fontSize }}px', + width: '{{ width }}' + }), + {params: {color: 'red', fontSize: '200', width: '10px'}}), - state( - 'final', - style( - {color: '{{ color }}', fontSize: '{{ fontSize }}px', width: '888px'}), - {params: {color: 'green', fontSize: '50', width: '100px'}}), + state( + 'final', + style( + {color: '{{ color }}', fontSize: '{{ fontSize }}px', width: '888px'}), + {params: {color: 'green', fontSize: '50', width: '100px'}}), - transition('start => final', animate(500)), - ]), - ] - }) - class Cmp { - public exp: any; - public color: any; - } + transition('start => final', animate(500)), + ]), + ] + }) + class Cmp { + public exp: any; + public color: any; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = 'start'; - cmp.color = 'red'; - fixture.detectChanges(); - resetLog(); + cmp.exp = 'start'; + cmp.color = 'red'; + fixture.detectChanges(); + resetLog(); - cmp.exp = 'final'; - cmp.color = 'blue'; - fixture.detectChanges(); + cmp.exp = 'final'; + cmp.color = 'blue'; + fixture.detectChanges(); - const players = getLog(); - expect(players.length).toEqual(1); - const [p1] = players; + const players = getLog(); + expect(players.length).toEqual(1); + const [p1] = players; - expect(p1.keyframes).toEqual([ - {color: 'red', fontSize: '200px', width: '10px', offset: 0}, - {color: 'blue', fontSize: '50px', width: '888px', offset: 1} - ]); + expect(p1.keyframes).toEqual([ + {color: 'red', fontSize: '200px', width: '10px', offset: 0}, + {color: 'blue', fontSize: '50px', width: '888px', offset: 1} + ]); - const element = p1.element; - p1.finish(); - flushMicrotasks(); + const element = p1.element; + p1.finish(); + flushMicrotasks(); - expect(getDOM().hasStyle(element, 'color', 'blue')).toBeTruthy(); - expect(getDOM().hasStyle(element, 'fontSize', '50px')).toBeTruthy(); - expect(getDOM().hasStyle(element, 'width', '888px')).toBeTruthy(); - })); + expect(getDOM().hasStyle(element, 'color', 'blue')).toBeTruthy(); + expect(getDOM().hasStyle(element, 'fontSize', '50px')).toBeTruthy(); + expect(getDOM().hasStyle(element, 'width', '888px')).toBeTruthy(); + })); it('should only evaluate final state param substitutions from the expression and state values and not from the transition options ', fakeAsync(() => { @@ -2443,211 +2463,216 @@ const DEFAULT_COMPONENT_ID = '1'; }); describe('animation listeners', () => { - it('should trigger a `start` state change listener for when the animation changes state from void => state', - fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should trigger a `start` state change listener for when the animation changes state from void => state', + fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [trigger( - 'myAnimation', - [transition( - 'void => *', - [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], - }) - class Cmp { - exp: any = false; - // TODO(issue/24571): remove '!'. - event !: AnimationEvent; + animations: [trigger( + 'myAnimation', + [transition( + 'void => *', + [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])], + }) + class Cmp { + exp: any = false; + // TODO(issue/24571): remove '!'. + event !: AnimationEvent; - callback = (event: any) => { this.event = event; }; - } + callback = (event: any) => { this.event = event; }; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'true'; - fixture.detectChanges(); - flushMicrotasks(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'true'; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.event.triggerName).toEqual('myAnimation'); - expect(cmp.event.phaseName).toEqual('start'); - expect(cmp.event.totalTime).toEqual(500); - expect(cmp.event.fromState).toEqual('void'); - expect(cmp.event.toState).toEqual('true'); - })); + expect(cmp.event.triggerName).toEqual('myAnimation'); + expect(cmp.event.phaseName).toEqual('start'); + expect(cmp.event.totalTime).toEqual(500); + expect(cmp.event.fromState).toEqual('void'); + expect(cmp.event.toState).toEqual('true'); + })); - it('should trigger a `done` state change listener for when the animation changes state from a => b', - fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should trigger a `done` state change listener for when the animation changes state from a => b', + fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [trigger( - 'myAnimation123', - [transition( - '* => b', [style({'opacity': '0'}), animate(999, style({'opacity': '1'}))])])], - }) - class Cmp { - exp: any = false; - // TODO(issue/24571): remove '!'. - event !: AnimationEvent; + animations: [trigger( + 'myAnimation123', + [transition( + '* => b', + [style({'opacity': '0'}), animate(999, style({'opacity': '1'}))])])], + }) + class Cmp { + exp: any = false; + // TODO(issue/24571): remove '!'. + event !: AnimationEvent; - callback = (event: any) => { this.event = event; }; - } + callback = (event: any) => { this.event = event; }; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = 'b'; - fixture.detectChanges(); - engine.flush(); + cmp.exp = 'b'; + fixture.detectChanges(); + engine.flush(); - expect(cmp.event).toBeFalsy(); + expect(cmp.event).toBeFalsy(); - const player = engine.players.pop(); - player.finish(); - flushMicrotasks(); + const player = engine.players.pop(); + player.finish(); + flushMicrotasks(); - expect(cmp.event.triggerName).toEqual('myAnimation123'); - expect(cmp.event.phaseName).toEqual('done'); - expect(cmp.event.totalTime).toEqual(999); - expect(cmp.event.fromState).toEqual('void'); - expect(cmp.event.toState).toEqual('b'); - })); + expect(cmp.event.triggerName).toEqual('myAnimation123'); + expect(cmp.event.phaseName).toEqual('done'); + expect(cmp.event.totalTime).toEqual(999); + expect(cmp.event.fromState).toEqual('void'); + expect(cmp.event.toState).toEqual('b'); + })); - it('should handle callbacks for multiple triggers running simultaneously', fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should handle callbacks for multiple triggers running simultaneously', fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [ - trigger( - 'ani1', - [ - transition( - '* => a', - [style({'opacity': '0'}), animate(999, style({'opacity': '1'}))]), - ]), - trigger( - 'ani2', - [ - transition( - '* => b', - [style({'width': '0px'}), animate(999, style({'width': '100px'}))]), - ]) - ], - }) - class Cmp { - exp1: any = false; - exp2: any = false; - // TODO(issue/24571): remove '!'. - event1 !: AnimationEvent; - // TODO(issue/24571): remove '!'. - event2 !: AnimationEvent; - // tslint:disable:semicolon - callback1 = (event: any) => { this.event1 = event; }; - // tslint:disable:semicolon - callback2 = (event: any) => { this.event2 = event; }; - } + animations: [ + trigger( + 'ani1', + [ + transition( + '* => a', + [style({'opacity': '0'}), animate(999, style({'opacity': '1'}))]), + ]), + trigger( + 'ani2', + [ + transition( + '* => b', + [style({'width': '0px'}), animate(999, style({'width': '100px'}))]), + ]) + ], + }) + class Cmp { + exp1: any = false; + exp2: any = false; + // TODO(issue/24571): remove '!'. + event1 !: AnimationEvent; + // TODO(issue/24571): remove '!'. + event2 !: AnimationEvent; + // tslint:disable:semicolon + callback1 = (event: any) => { this.event1 = event; }; + // tslint:disable:semicolon + callback2 = (event: any) => { this.event2 = event; }; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp1 = 'a'; - cmp.exp2 = 'b'; - fixture.detectChanges(); - engine.flush(); + cmp.exp1 = 'a'; + cmp.exp2 = 'b'; + fixture.detectChanges(); + engine.flush(); - expect(cmp.event1).toBeFalsy(); - expect(cmp.event2).toBeFalsy(); + expect(cmp.event1).toBeFalsy(); + expect(cmp.event2).toBeFalsy(); - const player1 = engine.players[0]; - const player2 = engine.players[1]; + const player1 = engine.players[0]; + const player2 = engine.players[1]; - player1.finish(); - player2.finish(); - expect(cmp.event1).toBeFalsy(); - expect(cmp.event2).toBeFalsy(); + player1.finish(); + player2.finish(); + expect(cmp.event1).toBeFalsy(); + expect(cmp.event2).toBeFalsy(); - flushMicrotasks(); - expect(cmp.event1.triggerName).toBeTruthy('ani1'); - expect(cmp.event2.triggerName).toBeTruthy('ani2'); - })); + flushMicrotasks(); + expect(cmp.event1.triggerName).toBeTruthy('ani1'); + expect(cmp.event2.triggerName).toBeTruthy('ani2'); + })); - it('should handle callbacks for multiple triggers running simultaneously on the same element', - fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should handle callbacks for multiple triggers running simultaneously on the same element', + fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [ - trigger( - 'ani1', - [ - transition( - '* => a', - [style({'opacity': '0'}), animate(999, style({'opacity': '1'}))]), - ]), - trigger( - 'ani2', - [ - transition( - '* => b', - [style({'width': '0px'}), animate(999, style({'width': '100px'}))]), - ]) - ], - }) - class Cmp { - exp1: any = false; - exp2: any = false; - // TODO(issue/24571): remove '!'. - event1 !: AnimationEvent; - // TODO(issue/24571): remove '!'. - event2 !: AnimationEvent; - callback1 = (event: any) => { this.event1 = event; }; - callback2 = (event: any) => { this.event2 = event; }; - } + animations: [ + trigger( + 'ani1', + [ + transition( + '* => a', + [style({'opacity': '0'}), animate(999, style({'opacity': '1'}))]), + ]), + trigger( + 'ani2', + [ + transition( + '* => b', + [style({'width': '0px'}), animate(999, style({'width': '100px'}))]), + ]) + ], + }) + class Cmp { + exp1: any = false; + exp2: any = false; + // TODO(issue/24571): remove '!'. + event1 !: AnimationEvent; + // TODO(issue/24571): remove '!'. + event2 !: AnimationEvent; + callback1 = (event: any) => { this.event1 = event; }; + callback2 = (event: any) => { this.event2 = event; }; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp1 = 'a'; - cmp.exp2 = 'b'; - fixture.detectChanges(); - engine.flush(); + cmp.exp1 = 'a'; + cmp.exp2 = 'b'; + fixture.detectChanges(); + engine.flush(); - expect(cmp.event1).toBeFalsy(); - expect(cmp.event2).toBeFalsy(); + expect(cmp.event1).toBeFalsy(); + expect(cmp.event2).toBeFalsy(); - const player1 = engine.players[0]; - const player2 = engine.players[1]; + const player1 = engine.players[0]; + const player2 = engine.players[1]; - player1.finish(); - player2.finish(); - expect(cmp.event1).toBeFalsy(); - expect(cmp.event2).toBeFalsy(); + player1.finish(); + player2.finish(); + expect(cmp.event1).toBeFalsy(); + expect(cmp.event2).toBeFalsy(); - flushMicrotasks(); - expect(cmp.event1.triggerName).toBeTruthy('ani1'); - expect(cmp.event2.triggerName).toBeTruthy('ani2'); - })); + flushMicrotasks(); + expect(cmp.event1.triggerName).toBeTruthy('ani1'); + expect(cmp.event2.triggerName).toBeTruthy('ani2'); + })); it('should handle a leave animation for multiple triggers even if not all triggers have their own leave transition specified', fakeAsync(() => { @@ -2709,124 +2734,128 @@ const DEFAULT_COMPONENT_ID = '1'; expect(elm.innerText.trim()).toEqual(''); })); - it('should trigger a state change listener for when the animation changes state from void => state on the host element', - fakeAsync(() => { - @Component({ - selector: 'my-cmp', - template: `...`, - animations: [trigger( - 'myAnimation2', - [transition( - 'void => *', - [style({'opacity': '0'}), animate(1000, style({'opacity': '1'}))])])], - }) - class Cmp { - // TODO(issue/24571): remove '!'. - event !: AnimationEvent; + fixmeIvy('unknown').it( + 'should trigger a state change listener for when the animation changes state from void => state on the host element', + fakeAsync(() => { + @Component({ + selector: 'my-cmp', + template: `...`, + animations: [trigger( + 'myAnimation2', + [transition( + 'void => *', + [style({'opacity': '0'}), animate(1000, style({'opacity': '1'}))])])], + }) + class Cmp { + // TODO(issue/24571): remove '!'. + event !: AnimationEvent; - @HostBinding('@myAnimation2') - exp: any = false; + @HostBinding('@myAnimation2') + exp: any = false; - @HostListener('@myAnimation2.start', ['$event']) - callback = (event: any) => { this.event = event; } - } + @HostListener('@myAnimation2.start', ['$event']) + callback = (event: any) => { this.event = event; } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'TRUE'; - fixture.detectChanges(); - flushMicrotasks(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'TRUE'; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.event.triggerName).toEqual('myAnimation2'); - expect(cmp.event.phaseName).toEqual('start'); - expect(cmp.event.totalTime).toEqual(1000); - expect(cmp.event.fromState).toEqual('void'); - expect(cmp.event.toState).toEqual('TRUE'); - })); + expect(cmp.event.triggerName).toEqual('myAnimation2'); + expect(cmp.event.phaseName).toEqual('start'); + expect(cmp.event.totalTime).toEqual(1000); + expect(cmp.event.fromState).toEqual('void'); + expect(cmp.event.toState).toEqual('TRUE'); + })); - it('should always fire callbacks even when a transition is not detected', fakeAsync(() => { - @Component({ - selector: 'my-cmp', - template: ` + fixmeIvy('unknown').it( + 'should always fire callbacks even when a transition is not detected', fakeAsync(() => { + @Component({ + selector: 'my-cmp', + template: `
`, - animations: [trigger('myAnimation', [])] - }) - class Cmp { - // TODO(issue/24571): remove '!'. - exp !: string; - log: any[] = []; - callback = (event: any) => this.log.push(`${event.phaseName} => ${event.toState}`); - } + animations: [trigger('myAnimation', [])] + }) + class Cmp { + // TODO(issue/24571): remove '!'. + exp !: string; + log: any[] = []; + callback = (event: any) => this.log.push(`${event.phaseName} => ${event.toState}`); + } - TestBed.configureTestingModule({ - providers: [{provide: AnimationDriver, useClass: NoopAnimationDriver}], - declarations: [Cmp] - }); + TestBed.configureTestingModule({ + providers: [{provide: AnimationDriver, useClass: NoopAnimationDriver}], + declarations: [Cmp] + }); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = 'a'; - fixture.detectChanges(); - flushMicrotasks(); - expect(cmp.log).toEqual(['start => a', 'done => a']); + cmp.exp = 'a'; + fixture.detectChanges(); + flushMicrotasks(); + expect(cmp.log).toEqual(['start => a', 'done => a']); - cmp.log = []; - cmp.exp = 'b'; - fixture.detectChanges(); - flushMicrotasks(); + cmp.log = []; + cmp.exp = 'b'; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual(['start => b', 'done => b']); - })); + expect(cmp.log).toEqual(['start => b', 'done => b']); + })); - it('should fire callback events for leave animations even if there is no leave transition', - fakeAsync(() => { - @Component({ - selector: 'my-cmp', - template: ` + fixmeIvy('unknown').it( + 'should fire callback events for leave animations even if there is no leave transition', + fakeAsync(() => { + @Component({ + selector: 'my-cmp', + template: `
`, - animations: [trigger('myAnimation', [])] - }) - class Cmp { - exp: boolean = false; - log: any[] = []; - callback = (event: any) => { - const state = event.toState || '_default_'; - this.log.push(`${event.phaseName} => ${state}`); - } - } + animations: [trigger('myAnimation', [])] + }) + class Cmp { + exp: boolean = false; + log: any[] = []; + callback = (event: any) => { + const state = event.toState || '_default_'; + this.log.push(`${event.phaseName} => ${state}`); + } + } - TestBed.configureTestingModule({ - providers: [{provide: AnimationDriver, useClass: NoopAnimationDriver}], - declarations: [Cmp] - }); + TestBed.configureTestingModule({ + providers: [{provide: AnimationDriver, useClass: NoopAnimationDriver}], + declarations: [Cmp] + }); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = true; - fixture.detectChanges(); - flushMicrotasks(); - expect(cmp.log).toEqual(['start => _default_', 'done => _default_']); + cmp.exp = true; + fixture.detectChanges(); + flushMicrotasks(); + expect(cmp.log).toEqual(['start => _default_', 'done => _default_']); - cmp.log = []; + cmp.log = []; - cmp.exp = false; - fixture.detectChanges(); - flushMicrotasks(); + cmp.exp = false; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual(['start => void', 'done => void']); - })); + expect(cmp.log).toEqual(['start => void', 'done => void']); + })); - it('should fire callbacks on a sub animation once it starts and finishes', fakeAsync(() => { - @Component({ - selector: 'my-cmp', - template: ` + fixmeIvy('unknown').it( + 'should fire callbacks on a sub animation once it starts and finishes', fakeAsync(() => { + @Component({ + selector: 'my-cmp', + template: `
`, - animations: [ - trigger( - 'parent', - [ - transition( - '* => go', - [ - style({width: '0px'}), - animate(1000, style({width: '100px'})), - query( - '.child', - [ - animateChild({duration: '1s'}), - ]), - animate(1000, style({width: '0px'})), - ]), - ]), - trigger( - 'child', - [ - transition( - '* => go', - [ - style({height: '0px'}), - animate(1000, style({height: '100px'})), - ]), - ]) - ] - }) - class Cmp { - log: string[] = []; - // TODO(issue/24571): remove '!'. - exp1 !: string; - // TODO(issue/24571): remove '!'. - exp2 !: string; + animations: [ + trigger( + 'parent', + [ + transition( + '* => go', + [ + style({width: '0px'}), + animate(1000, style({width: '100px'})), + query( + '.child', + [ + animateChild({duration: '1s'}), + ]), + animate(1000, style({width: '0px'})), + ]), + ]), + trigger( + 'child', + [ + transition( + '* => go', + [ + style({height: '0px'}), + animate(1000, style({height: '100px'})), + ]), + ]) + ] + }) + class Cmp { + log: string[] = []; + // TODO(issue/24571): remove '!'. + exp1 !: string; + // TODO(issue/24571): remove '!'. + exp2 !: string; - cb(name: string, event: AnimationEvent) { this.log.push(name); } - } + cb(name: string, event: AnimationEvent) { this.log.push(name); } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp1 = 'go'; - cmp.exp2 = 'go'; - fixture.detectChanges(); - engine.flush(); - flushMicrotasks(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp1 = 'go'; + cmp.exp2 = 'go'; + fixture.detectChanges(); + engine.flush(); + flushMicrotasks(); - expect(cmp.log).toEqual(['parent-start', 'child-start']); - cmp.log = []; + expect(cmp.log).toEqual(['parent-start', 'child-start']); + cmp.log = []; - const players = getLog(); - expect(players.length).toEqual(3); - const [p1, p2, p3] = players; + const players = getLog(); + expect(players.length).toEqual(3); + const [p1, p2, p3] = players; - p1.finish(); - flushMicrotasks(); - expect(cmp.log).toEqual([]); + p1.finish(); + flushMicrotasks(); + expect(cmp.log).toEqual([]); - p2.finish(); - flushMicrotasks(); - expect(cmp.log).toEqual([]); + p2.finish(); + flushMicrotasks(); + expect(cmp.log).toEqual([]); - p3.finish(); - flushMicrotasks(); - expect(cmp.log).toEqual(['parent-done', 'child-done']); - })); + p3.finish(); + flushMicrotasks(); + expect(cmp.log).toEqual(['parent-done', 'child-done']); + })); - it('should fire callbacks and collect the correct the totalTime and element details for any queried sub animations', - fakeAsync( - () => { - @Component({ + fixmeIvy('unknown').it( + 'should fire callbacks and collect the correct the totalTime and element details for any queried sub animations', + fakeAsync( + () => { + @Component({ selector: 'my-cmp', template: `
@@ -2946,62 +2976,62 @@ const DEFAULT_COMPONENT_ID = '1'; ] }) class Cmp { - log: string[] = []; - events: {[name: string]: any} = {}; - // TODO(issue/24571): remove '!'. - exp !: string; - items: any = [0, 1, 2, 3]; + log: string[] = []; + events: {[name: string]: any} = {}; + // TODO(issue/24571): remove '!'. + exp !: string; + items: any = [0, 1, 2, 3]; - cb(name: string, phase: string, event: AnimationEvent) { - this.log.push(name + '-' + phase); - this.events[name] = event; - } - } + cb(name: string, phase: string, event: AnimationEvent) { + this.log.push(name + '-' + phase); + this.events[name] = event; + } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.exp = 'go'; - fixture.detectChanges(); - engine.flush(); - flushMicrotasks(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'go'; + fixture.detectChanges(); + engine.flush(); + flushMicrotasks(); - expect(cmp.log).toEqual(['c-0-start', 'c-1-start', 'c-2-start', 'c-3-start']); - cmp.log = []; + expect(cmp.log).toEqual(['c-0-start', 'c-1-start', 'c-2-start', 'c-3-start']); + cmp.log = []; - const players = getLog(); - // 1 + 4 + 4 = 9 players - expect(players.length).toEqual(9); + const players = getLog(); + // 1 + 4 + 4 = 9 players + expect(players.length).toEqual(9); - const [pA, pq1a, pq1b, pq1c, pq1d, pq2a, pq2b, pq2c, pq2d] = getLog(); - pA.finish(); - pq1a.finish(); - pq1b.finish(); - pq1c.finish(); - pq1d.finish(); - flushMicrotasks(); + const [pA, pq1a, pq1b, pq1c, pq1d, pq2a, pq2b, pq2c, pq2d] = getLog(); + pA.finish(); + pq1a.finish(); + pq1b.finish(); + pq1c.finish(); + pq1d.finish(); + flushMicrotasks(); - expect(cmp.log).toEqual([]); - pq2a.finish(); - pq2b.finish(); - pq2c.finish(); - pq2d.finish(); - flushMicrotasks(); + expect(cmp.log).toEqual([]); + pq2a.finish(); + pq2b.finish(); + pq2c.finish(); + pq2d.finish(); + flushMicrotasks(); - expect(cmp.log).toEqual( - ['all-done', 'c-0-done', 'c-1-done', 'c-2-done', 'c-3-done']); + expect(cmp.log).toEqual( + ['all-done', 'c-0-done', 'c-1-done', 'c-2-done', 'c-3-done']); - expect(cmp.events['c-0'].totalTime).toEqual(4100); // 1000 + 1000 + 1800 + 300 - expect(cmp.events['c-0'].element.innerText.trim()).toEqual('0'); - expect(cmp.events['c-1'].totalTime).toEqual(4100); - expect(cmp.events['c-1'].element.innerText.trim()).toEqual('1'); - expect(cmp.events['c-2'].totalTime).toEqual(4100); - expect(cmp.events['c-2'].element.innerText.trim()).toEqual('2'); - expect(cmp.events['c-3'].totalTime).toEqual(4100); - expect(cmp.events['c-3'].element.innerText.trim()).toEqual('3'); - })); + expect(cmp.events['c-0'].totalTime).toEqual(4100); // 1000 + 1000 + 1800 + 300 + expect(cmp.events['c-0'].element.innerText.trim()).toEqual('0'); + expect(cmp.events['c-1'].totalTime).toEqual(4100); + expect(cmp.events['c-1'].element.innerText.trim()).toEqual('1'); + expect(cmp.events['c-2'].totalTime).toEqual(4100); + expect(cmp.events['c-2'].element.innerText.trim()).toEqual('2'); + expect(cmp.events['c-3'].totalTime).toEqual(4100); + expect(cmp.events['c-3'].element.innerText.trim()).toEqual('3'); + })); }); describe('animation control flags', () => { @@ -3255,59 +3285,60 @@ const DEFAULT_COMPONENT_ID = '1'; expect(parent.childElementCount).toEqual(0); }); - it('should properly resolve animation event listeners when disabled', fakeAsync(() => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should properly resolve animation event listeners when disabled', fakeAsync(() => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - transition( - '* => 1, * => 2', - [style({opacity: 0}), animate(9876, style({opacity: 1}))]), - ]), - ] - }) - class Cmp { - disableExp = false; - exp = ''; - // TODO(issue/24571): remove '!'. - startEvent !: AnimationEvent; - // TODO(issue/24571): remove '!'. - doneEvent !: AnimationEvent; - } + animations: [ + trigger( + 'myAnimation', + [ + transition( + '* => 1, * => 2', + [style({opacity: 0}), animate(9876, style({opacity: 1}))]), + ]), + ] + }) + class Cmp { + disableExp = false; + exp = ''; + // TODO(issue/24571): remove '!'. + startEvent !: AnimationEvent; + // TODO(issue/24571): remove '!'. + doneEvent !: AnimationEvent; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.disableExp = true; - fixture.detectChanges(); - resetLog(); - expect(cmp.startEvent).toBeFalsy(); - expect(cmp.doneEvent).toBeFalsy(); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.disableExp = true; + fixture.detectChanges(); + resetLog(); + expect(cmp.startEvent).toBeFalsy(); + expect(cmp.doneEvent).toBeFalsy(); - cmp.exp = '1'; - fixture.detectChanges(); - flushMicrotasks(); - expect(cmp.startEvent.totalTime).toEqual(9876); - expect(cmp.startEvent.disabled).toBeTruthy(); - expect(cmp.doneEvent.totalTime).toEqual(9876); - expect(cmp.doneEvent.disabled).toBeTruthy(); + cmp.exp = '1'; + fixture.detectChanges(); + flushMicrotasks(); + expect(cmp.startEvent.totalTime).toEqual(9876); + expect(cmp.startEvent.disabled).toBeTruthy(); + expect(cmp.doneEvent.totalTime).toEqual(9876); + expect(cmp.doneEvent.disabled).toBeTruthy(); - cmp.exp = '2'; - cmp.disableExp = false; - fixture.detectChanges(); - flushMicrotasks(); - expect(cmp.startEvent.totalTime).toEqual(9876); - expect(cmp.startEvent.disabled).toBeFalsy(); - // the done event isn't fired because it's an actual animation - })); + cmp.exp = '2'; + cmp.disableExp = false; + fixture.detectChanges(); + flushMicrotasks(); + expect(cmp.startEvent.totalTime).toEqual(9876); + expect(cmp.startEvent.disabled).toBeFalsy(); + // the done event isn't fired because it's an actual animation + })); it('should work when there are no animations on the component handling the disable/enable flag', () => { @@ -3360,112 +3391,114 @@ const DEFAULT_COMPONENT_ID = '1'; expect(getLog().length).toEqual(1); }); - it('should treat the property as true when the expression is missing', () => { - @Component({ - selector: 'parent-cmp', - animations: [ - trigger( - 'myAnimation', - [ - transition( - '* => go', - [ - style({opacity: 0}), - animate(500, style({opacity: 1})), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should treat the property as true when the expression is missing', () => { + @Component({ + selector: 'parent-cmp', + animations: [ + trigger( + 'myAnimation', + [ + transition( + '* => go', + [ + style({opacity: 0}), + animate(500, style({opacity: 1})), + ]), + ]), + ], + template: `
` - }) - class Cmp { - exp = ''; - } + }) + class Cmp { + exp = ''; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - fixture.detectChanges(); - resetLog(); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); + resetLog(); - cmp.exp = 'go'; - fixture.detectChanges(); - expect(getLog().length).toEqual(0); - }); + cmp.exp = 'go'; + fixture.detectChanges(); + expect(getLog().length).toEqual(0); + }); - it('should respect parent/sub animations when the respective area in the DOM is disabled', - fakeAsync(() => { - @Component({ - selector: 'parent-cmp', - animations: [ - trigger( - 'parent', - [ - transition( - '* => empty', - [ - style({opacity: 0}), - query( - '@child', - [ - animateChild(), - ]), - animate('1s', style({opacity: 1})), - ]), - ]), - trigger( - 'child', - [ - transition( - ':leave', - [ - animate('1s', style({opacity: 0})), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should respect parent/sub animations when the respective area in the DOM is disabled', + fakeAsync(() => { + @Component({ + selector: 'parent-cmp', + animations: [ + trigger( + 'parent', + [ + transition( + '* => empty', + [ + style({opacity: 0}), + query( + '@child', + [ + animateChild(), + ]), + animate('1s', style({opacity: 1})), + ]), + ]), + trigger( + 'child', + [ + transition( + ':leave', + [ + animate('1s', style({opacity: 0})), + ]), + ]), + ], + template: `
` - }) - class Cmp { - @ViewChild('container') public container: any; + }) + class Cmp { + @ViewChild('container') public container: any; - disableExp = false; - exp = ''; - items: any[] = []; - doneLog: any[] = []; + disableExp = false; + exp = ''; + items: any[] = []; + doneLog: any[] = []; - onDone(event: any) { this.doneLog.push(event); } - } + onDone(event: any) { this.doneLog.push(event); } + } - TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.disableExp = true; - cmp.items = [0, 1, 2, 3, 4]; - fixture.detectChanges(); - flushMicrotasks(); + TestBed.configureTestingModule({declarations: [Cmp]}); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.disableExp = true; + cmp.items = [0, 1, 2, 3, 4]; + fixture.detectChanges(); + flushMicrotasks(); - cmp.exp = 'empty'; - cmp.items = []; - cmp.doneLog = []; - fixture.detectChanges(); - flushMicrotasks(); + cmp.exp = 'empty'; + cmp.items = []; + cmp.doneLog = []; + fixture.detectChanges(); + flushMicrotasks(); - const elms = cmp.container.nativeElement.querySelectorAll('.item'); - expect(elms.length).toEqual(0); + const elms = cmp.container.nativeElement.querySelectorAll('.item'); + expect(elms.length).toEqual(0); - expect(cmp.doneLog.length).toEqual(6); - })); + expect(cmp.doneLog.length).toEqual(6); + })); }); }); @@ -3569,63 +3602,64 @@ const DEFAULT_COMPONENT_ID = '1'; /only state\(\) and transition\(\) definitions can sit inside of a trigger\(\)/); }); - it('should combine multiple errors together into one exception when an animation fails to be built', - () => { - @Component({ - selector: 'if-cmp', - template: ` + fixmeIvy('unknown').it( + 'should combine multiple errors together into one exception when an animation fails to be built', + () => { + @Component({ + selector: 'if-cmp', + template: `
`, - animations: [ - trigger( - 'foo', - [ - transition(':enter', []), - transition( - '* => *', - [ - query('foo', animate(1000, style({background: 'red'}))), - ]), - ]), - trigger( - 'bar', - [ - transition(':enter', []), - transition( - '* => *', - [ - query('bar', animate(1000, style({background: 'blue'}))), - ]), - ]), - ] - }) - class Cmp { - fooExp: any = false; - barExp: any = false; - } + animations: [ + trigger( + 'foo', + [ + transition(':enter', []), + transition( + '* => *', + [ + query('foo', animate(1000, style({background: 'red'}))), + ]), + ]), + trigger( + 'bar', + [ + transition(':enter', []), + transition( + '* => *', + [ + query('bar', animate(1000, style({background: 'blue'}))), + ]), + ]), + ] + }) + class Cmp { + fooExp: any = false; + barExp: any = false; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - fixture.detectChanges(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + fixture.detectChanges(); - cmp.fooExp = 'go'; - cmp.barExp = 'go'; + cmp.fooExp = 'go'; + cmp.barExp = 'go'; - let errorMsg: string = ''; - try { - fixture.detectChanges(); - } catch (e) { - errorMsg = e.message; - } + let errorMsg: string = ''; + try { + fixture.detectChanges(); + } catch (e) { + errorMsg = e.message; + } - expect(errorMsg).toMatch(/@foo has failed due to:/); - expect(errorMsg).toMatch(/`query\("foo"\)` returned zero elements/); - expect(errorMsg).toMatch(/@bar has failed due to:/); - expect(errorMsg).toMatch(/`query\("bar"\)` returned zero elements/); - }); + expect(errorMsg).toMatch(/@foo has failed due to:/); + expect(errorMsg).toMatch(/`query\("foo"\)` returned zero elements/); + expect(errorMsg).toMatch(/@bar has failed due to:/); + expect(errorMsg).toMatch(/`query\("bar"\)` returned zero elements/); + }); it('should not throw an error if styles overlap in separate transitions', () => { @Component({ @@ -3658,18 +3692,19 @@ const DEFAULT_COMPONENT_ID = '1'; expect(() => { TestBed.createComponent(Cmp); }).not.toThrowError(); }); - it('should continue to clean up DOM-related animation artificats even if a compiler-level error is thrown midway', - () => { - @Component({ - selector: 'if-cmp', - animations: [ - trigger( - 'foo', - [ - transition('* => something', []), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should continue to clean up DOM-related animation artificats even if a compiler-level error is thrown midway', + () => { + @Component({ + selector: 'if-cmp', + animations: [ + trigger( + 'foo', + [ + transition('* => something', []), + ]), + ], + template: ` value = {{ foo[bar] }}
1
@@ -3677,32 +3712,32 @@ const DEFAULT_COMPONENT_ID = '1';
3
`, - }) - class Cmp { - exp: any = false; + }) + class Cmp { + exp: any = false; - @ViewChild('contents') public contents: any; - } + @ViewChild('contents') public contents: any; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); - const runCD = () => fixture.detectChanges(); - const cmp = fixture.componentInstance; + const runCD = () => fixture.detectChanges(); + const cmp = fixture.componentInstance; - cmp.exp = true; - expect(runCD).toThrow(); + cmp.exp = true; + expect(runCD).toThrow(); - const contents = cmp.contents.nativeElement; - expect(contents.innerText.replace(/\s+/gm, '')).toEqual('123'); + const contents = cmp.contents.nativeElement; + expect(contents.innerText.replace(/\s+/gm, '')).toEqual('123'); - cmp.exp = false; - expect(runCD).toThrow(); + cmp.exp = false; + expect(runCD).toThrow(); - expect(contents.innerText.trim()).toEqual(''); - }); + expect(contents.innerText.trim()).toEqual(''); + }); describe('errors for not using the animation module', () => { beforeEach(() => { @@ -3711,31 +3746,33 @@ const DEFAULT_COMPONENT_ID = '1'; }); }); - it('should throw when using an @prop binding without the animation module', () => { - @Component({template: `
`}) - class Cmp { - } + fixmeIvy('unknown').it( + 'should throw when using an @prop binding without the animation module', () => { + @Component({template: `
`}) + class Cmp { + } - TestBed.configureTestingModule({declarations: [Cmp]}); - const comp = TestBed.createComponent(Cmp); - expect(() => comp.detectChanges()) - .toThrowError( - 'Found the synthetic property @myAnimation. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.'); - }); + TestBed.configureTestingModule({declarations: [Cmp]}); + const comp = TestBed.createComponent(Cmp); + expect(() => comp.detectChanges()) + .toThrowError( + 'Found the synthetic property @myAnimation. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.'); + }); - it('should throw when using an @prop listener without the animation module', () => { - @Component({template: `
`}) - class Cmp { - a: any; - } + fixmeIvy('unknown').it( + 'should throw when using an @prop listener without the animation module', () => { + @Component({template: `
`}) + class Cmp { + a: any; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - expect(() => TestBed.createComponent(Cmp)) - .toThrowError( - 'Found the synthetic listener @myAnimation.start. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.'); + expect(() => TestBed.createComponent(Cmp)) + .toThrowError( + 'Found the synthetic listener @myAnimation.start. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.'); - }); + }); }); }); })(); diff --git a/packages/core/test/animation/animation_query_integration_spec.ts b/packages/core/test/animation/animation_query_integration_spec.ts index a0d63325c4..028a75722b 100644 --- a/packages/core/test/animation/animation_query_integration_spec.ts +++ b/packages/core/test/animation/animation_query_integration_spec.ts @@ -12,12 +12,11 @@ import {ENTER_CLASSNAME, LEAVE_CLASSNAME} from '@angular/animations/browser/src/ import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/browser/testing'; import {CommonModule} from '@angular/common'; import {Component, HostBinding, ViewChild} from '@angular/core'; +import {TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {fixmeIvy} from '@angular/private/testing'; import {HostListener} from '../../src/metadata/directives'; -import {TestBed} from '../../testing'; -import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; - (function() { // these tests are only mean't to be run within the DOM (for now) @@ -296,71 +295,72 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; expect(p6.element.classList.contains('b3')).toBeTruthy(); }); - it('should be able to query all active animations using :animating in a query', () => { - @Component({ - selector: 'ani-cmp', - template: ` + fixmeIvy('unknown').it( + 'should be able to query all active animations using :animating in a query', () => { + @Component({ + selector: 'ani-cmp', + template: `
`, - animations: [ - trigger( - 'myAnimation', - [ - transition( - '* => a', - [ - query( - '.item:nth-child(odd)', - [ - style({opacity: 0}), - animate(1000, style({opacity: 1})), - ]), - ]), - transition( - '* => b', - [ - query( - '.item:animating', - [ - style({opacity: 1}), - animate(1000, style({opacity: 0})), - ]), - ]), - ]), - ] - }) - class Cmp { - public exp: any; - public items: number[] = [0, 1, 2, 3, 4]; - } + animations: [ + trigger( + 'myAnimation', + [ + transition( + '* => a', + [ + query( + '.item:nth-child(odd)', + [ + style({opacity: 0}), + animate(1000, style({opacity: 1})), + ]), + ]), + transition( + '* => b', + [ + query( + '.item:animating', + [ + style({opacity: 1}), + animate(1000, style({opacity: 0})), + ]), + ]), + ]), + ] + }) + class Cmp { + public exp: any; + public items: number[] = [0, 1, 2, 3, 4]; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = 'a'; - fixture.detectChanges(); - engine.flush(); + cmp.exp = 'a'; + fixture.detectChanges(); + engine.flush(); - let players = getLog(); - expect(players.length).toEqual(3); - resetLog(); + let players = getLog(); + expect(players.length).toEqual(3); + resetLog(); - cmp.exp = 'b'; - fixture.detectChanges(); - engine.flush(); + cmp.exp = 'b'; + fixture.detectChanges(); + engine.flush(); - players = getLog(); - expect(players.length).toEqual(3); - expect(players[0].element.classList.contains('e-0')).toBeTruthy(); - expect(players[1].element.classList.contains('e-2')).toBeTruthy(); - expect(players[2].element.classList.contains('e-4')).toBeTruthy(); - }); + players = getLog(); + expect(players.length).toEqual(3); + expect(players[0].element.classList.contains('e-0')).toBeTruthy(); + expect(players[1].element.classList.contains('e-2')).toBeTruthy(); + expect(players[2].element.classList.contains('e-4')).toBeTruthy(); + }); it('should be able to query all actively queued animation triggers via `@*:animating`', () => { @@ -802,7 +802,7 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; expect(player.element.style.height).toEqual('444px'); }); - it('should find newly inserted items in the component via :enter', () => { + fixmeIvy('unknown').it('should find newly inserted items in the component via :enter', () => { @Component({ selector: 'ani-cmp', template: ` @@ -853,11 +853,12 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; }); }); - it('should cleanup :enter and :leave artifacts from nodes when any animation sequences fail to be built', - () => { - @Component({ - selector: 'ani-cmp', - template: ` + fixmeIvy('unknown').it( + 'should cleanup :enter and :leave artifacts from nodes when any animation sequences fail to be built', + () => { + @Component({ + selector: 'ani-cmp', + template: `
{{ item }} @@ -865,56 +866,56 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async';
Leave!
`, - animations: [ - trigger( - 'myAnimation', - [ - transition('* => 0', []), - transition( - '* => *', - [ - query( - '.child:enter', - [ - style({opacity: 0}), - animate(1000, style({opacity: 1})), - ]), - query( - '.incorrect-child:leave', - [ - animate(1000, style({opacity: 0})), - ]), - ]), - ]), - ] - }) - class Cmp { - @ViewChild('container') public container: any; - public items: any[] = []; - } + animations: [ + trigger( + 'myAnimation', + [ + transition('* => 0', []), + transition( + '* => *', + [ + query( + '.child:enter', + [ + style({opacity: 0}), + animate(1000, style({opacity: 1})), + ]), + query( + '.incorrect-child:leave', + [ + animate(1000, style({opacity: 0})), + ]), + ]), + ]), + ] + }) + class Cmp { + @ViewChild('container') public container: any; + public items: any[] = []; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.items = []; - fixture.detectChanges(); + cmp.items = []; + fixture.detectChanges(); - cmp.items = [0, 1, 2, 3, 4]; + cmp.items = [0, 1, 2, 3, 4]; - expect(() => { fixture.detectChanges(); }).toThrow(); + expect(() => { fixture.detectChanges(); }).toThrow(); - const children = cmp.container.nativeElement.querySelectorAll('.child'); - expect(children.length).toEqual(5); + const children = cmp.container.nativeElement.querySelectorAll('.child'); + expect(children.length).toEqual(5); - for (let i = 0; i < children.length; i++) { - let child = children[i]; - expect(child.classList.contains(ENTER_CLASSNAME)).toBe(false); - expect(child.classList.contains(LEAVE_CLASSNAME)).toBe(false); - } - }); + for (let i = 0; i < children.length; i++) { + let child = children[i]; + expect(child.classList.contains(ENTER_CLASSNAME)).toBe(false); + expect(child.classList.contains(LEAVE_CLASSNAME)).toBe(false); + } + }); it('should find elements that have been removed via :leave', () => { @Component({ @@ -2234,82 +2235,83 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; expect(p3.element.classList.contains('parent1')).toBeTruthy(); }); - it('should emulate a leave animation on the nearest sub host elements when a parent is removed', - fakeAsync(() => { - @Component({ - selector: 'ani-cmp', - template: ` + fixmeIvy('unknown').it( + 'should emulate a leave animation on the nearest sub host elements when a parent is removed', + fakeAsync(() => { + @Component({ + selector: 'ani-cmp', + template: `
`, - animations: [ - trigger( - 'leave', - [ - transition(':leave', [animate(1000, style({color: 'gold'}))]), - ]), - trigger( - 'parent', - [ - transition(':leave', [query(':leave', animateChild())]), - ]), - ] - }) - class ParentCmp { - public exp: boolean = true; - @ViewChild('child') public childElm: any; + animations: [ + trigger( + 'leave', + [ + transition(':leave', [animate(1000, style({color: 'gold'}))]), + ]), + trigger( + 'parent', + [ + transition(':leave', [query(':leave', animateChild())]), + ]), + ] + }) + class ParentCmp { + public exp: boolean = true; + @ViewChild('child') public childElm: any; - public childEvent: any; + public childEvent: any; - animateStart(event: any) { - if (event.toState == 'void') { - this.childEvent = event; - } - } - } + animateStart(event: any) { + if (event.toState == 'void') { + this.childEvent = event; + } + } + } - @Component({ - selector: 'child-cmp', - template: '...', - animations: [ - trigger( - 'child', - [ - transition(':leave', [animate(1000, style({color: 'gold'}))]), - ]), - ] - }) - class ChildCmp { - public childEvent: any; + @Component({ + selector: 'child-cmp', + template: '...', + animations: [ + trigger( + 'child', + [ + transition(':leave', [animate(1000, style({color: 'gold'}))]), + ]), + ] + }) + class ChildCmp { + public childEvent: any; - @HostBinding('@child') public animate = true; + @HostBinding('@child') public animate = true; - @HostListener('@child.start', ['$event']) - animateStart(event: any) { - if (event.toState == 'void') { - this.childEvent = event; - } - } - } + @HostListener('@child.start', ['$event']) + animateStart(event: any) { + if (event.toState == 'void') { + this.childEvent = event; + } + } + } - TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); - const fixture = TestBed.createComponent(ParentCmp); - const cmp = fixture.componentInstance; + TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); + const fixture = TestBed.createComponent(ParentCmp); + const cmp = fixture.componentInstance; - fixture.detectChanges(); + fixture.detectChanges(); - const childCmp = cmp.childElm; + const childCmp = cmp.childElm; - cmp.exp = false; - fixture.detectChanges(); - flushMicrotasks(); + cmp.exp = false; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.childEvent.toState).toEqual('void'); - expect(cmp.childEvent.totalTime).toEqual(1000); - expect(childCmp.childEvent.toState).toEqual('void'); - expect(childCmp.childEvent.totalTime).toEqual(1000); - })); + expect(cmp.childEvent.toState).toEqual('void'); + expect(cmp.childEvent.totalTime).toEqual(1000); + expect(childCmp.childEvent.toState).toEqual('void'); + expect(childCmp.childEvent.totalTime).toEqual(1000); + })); it('should emulate a leave animation on a sub component\'s inner elements when a parent leave animation occurs with animateChild', () => { @@ -2438,27 +2440,28 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; expect(element.innerText.trim()).toMatch(/this\s+child/mg); })); - it('should only mark outermost *directive nodes :enter and :leave when inserts and removals occur', - () => { - @Component({ - selector: 'ani-cmp', - animations: [ - trigger( - 'anim', - [ - transition( - '* => enter', - [ - query(':enter', [animate(1000, style({color: 'red'}))]), - ]), - transition( - '* => leave', - [ - query(':leave', [animate(1000, style({color: 'blue'}))]), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should only mark outermost *directive nodes :enter and :leave when inserts and removals occur', + () => { + @Component({ + selector: 'ani-cmp', + animations: [ + trigger( + 'anim', + [ + transition( + '* => enter', + [ + query(':enter', [animate(1000, style({color: 'red'}))]), + ]), + transition( + '* => leave', + [ + query(':leave', [animate(1000, style({color: 'blue'}))]), + ]), + ]), + ], + template: `
@@ -2474,46 +2477,47 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async';
` - }) - class Cmp { - // TODO(issue/24571): remove '!'. - public exp !: boolean; - } + }) + class Cmp { + // TODO(issue/24571): remove '!'. + public exp !: boolean; + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - const container = fixture.elementRef.nativeElement; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + const container = fixture.elementRef.nativeElement; - cmp.exp = true; - fixture.detectChanges(); - engine.flush(); + cmp.exp = true; + fixture.detectChanges(); + engine.flush(); - let players = getLog(); - resetLog(); - expect(players.length).toEqual(2); - const [p1, p2] = players; + let players = getLog(); + resetLog(); + expect(players.length).toEqual(2); + const [p1, p2] = players; - expect(p1.element.classList.contains('a')); - expect(p2.element.classList.contains('d')); + expect(p1.element.classList.contains('a')); + expect(p2.element.classList.contains('d')); - cmp.exp = false; - fixture.detectChanges(); - engine.flush(); + cmp.exp = false; + fixture.detectChanges(); + engine.flush(); - players = getLog(); - resetLog(); - expect(players.length).toEqual(2); - const [p3, p4] = players; + players = getLog(); + resetLog(); + expect(players.length).toEqual(2); + const [p3, p4] = players; - expect(p3.element.classList.contains('a')); - expect(p4.element.classList.contains('d')); - }); + expect(p3.element.classList.contains('a')); + expect(p4.element.classList.contains('d')); + }); - it('should collect multiple root levels of :enter and :leave nodes', () => { - @Component({ + fixmeIvy('unknown').it( + 'should collect multiple root levels of :enter and :leave nodes', () => { + @Component({ selector: 'ani-cmp', animations: [ trigger('pageAnimation', [ @@ -2548,141 +2552,142 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; ` }) class Cmp { - get title() { - if (this.page1) { - return 'hello from page1'; + get title() { + if (this.page1) { + return 'hello from page1'; + } + return 'greetings from page2'; + } + + page1 = false; + page2 = false; + loading = false; + + get status() { + if (this.loading) return 'loading'; + if (this.page1) return 'page1'; + if (this.page2) return 'page2'; + return ''; + } } - return 'greetings from page2'; - } - page1 = false; - page2 = false; - loading = false; + TestBed.configureTestingModule({declarations: [Cmp]}); - get status() { - if (this.loading) return 'loading'; - if (this.page1) return 'page1'; - if (this.page2) return 'page2'; - return ''; - } - } + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.loading = true; + fixture.detectChanges(); + engine.flush(); - TestBed.configureTestingModule({declarations: [Cmp]}); + let players = getLog(); + resetLog(); + cancelAllPlayers(players); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; - cmp.loading = true; - fixture.detectChanges(); - engine.flush(); + cmp.page1 = true; + cmp.loading = false; + fixture.detectChanges(); + engine.flush(); - let players = getLog(); - resetLog(); - cancelAllPlayers(players); + let p1: MockAnimationPlayer; + let p2: MockAnimationPlayer; + let p3: MockAnimationPlayer; - cmp.page1 = true; - cmp.loading = false; - fixture.detectChanges(); - engine.flush(); + players = getLog(); + expect(players.length).toEqual(3); + [p1, p2, p3] = players; - let p1: MockAnimationPlayer; - let p2: MockAnimationPlayer; - let p3: MockAnimationPlayer; + expect(p1.element.classList.contains('loading')).toBe(true); + expect(p2.element.classList.contains('title')).toBe(true); + expect(p3.element.classList.contains('page1')).toBe(true); - players = getLog(); - expect(players.length).toEqual(3); - [p1, p2, p3] = players; + resetLog(); + cancelAllPlayers(players); - expect(p1.element.classList.contains('loading')).toBe(true); - expect(p2.element.classList.contains('title')).toBe(true); - expect(p3.element.classList.contains('page1')).toBe(true); + cmp.page1 = false; + cmp.loading = true; + fixture.detectChanges(); - resetLog(); - cancelAllPlayers(players); + players = getLog(); + cancelAllPlayers(players); - cmp.page1 = false; - cmp.loading = true; - fixture.detectChanges(); + expect(players.length).toEqual(3); + [p1, p2, p3] = players; - players = getLog(); - cancelAllPlayers(players); + expect(p1.element.classList.contains('title')).toBe(true); + expect(p2.element.classList.contains('page1')).toBe(true); + expect(p3.element.classList.contains('loading')).toBe(true); - expect(players.length).toEqual(3); - [p1, p2, p3] = players; + resetLog(); + cancelAllPlayers(players); - expect(p1.element.classList.contains('title')).toBe(true); - expect(p2.element.classList.contains('page1')).toBe(true); - expect(p3.element.classList.contains('loading')).toBe(true); + cmp.page2 = true; + cmp.loading = false; + fixture.detectChanges(); + engine.flush(); - resetLog(); - cancelAllPlayers(players); + players = getLog(); + expect(players.length).toEqual(3); + [p1, p2, p3] = players; - cmp.page2 = true; - cmp.loading = false; - fixture.detectChanges(); - engine.flush(); + expect(p1.element.classList.contains('loading')).toBe(true); + expect(p2.element.classList.contains('title')).toBe(true); + expect(p3.element.classList.contains('page2')).toBe(true); + }); - players = getLog(); - expect(players.length).toEqual(3); - [p1, p2, p3] = players; - - expect(p1.element.classList.contains('loading')).toBe(true); - expect(p2.element.classList.contains('title')).toBe(true); - expect(p3.element.classList.contains('page2')).toBe(true); - }); - - it('should emulate leave animation callbacks for all sub elements that have leave triggers within the component', - fakeAsync(() => { - @Component({ - selector: 'ani-cmp', - animations: [ - trigger('parent', []), trigger('child', []), - trigger( - 'childWithAnimation', - [ - transition( - ':leave', - [ - animate(1000, style({background: 'red'})), - ]), - ]) - ], - template: ` + fixmeIvy('unknown').it( + 'should emulate leave animation callbacks for all sub elements that have leave triggers within the component', + fakeAsync(() => { + @Component({ + selector: 'ani-cmp', + animations: [ + trigger('parent', []), trigger('child', []), + trigger( + 'childWithAnimation', + [ + transition( + ':leave', + [ + animate(1000, style({background: 'red'})), + ]), + ]) + ], + template: `
` - }) - class Cmp { - // TODO(issue/24571): remove '!'. - public exp !: boolean; - public log: string[] = []; - callback(event: any) { - this.log.push(event.element.getAttribute('data-name') + '-' + event.phaseName); - } - } + }) + class Cmp { + // TODO(issue/24571): remove '!'. + public exp !: boolean; + public log: string[] = []; + callback(event: any) { + this.log.push(event.element.getAttribute('data-name') + '-' + event.phaseName); + } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.exp = true; - fixture.detectChanges(); - flushMicrotasks(); - cmp.log = []; + cmp.exp = true; + fixture.detectChanges(); + flushMicrotasks(); + cmp.log = []; - cmp.exp = false; - fixture.detectChanges(); - flushMicrotasks(); - expect(cmp.log).toEqual([ - 'c1-start', 'c1-done', 'c2-start', 'c2-done', 'p-start', 'c3-start', 'c3-done', - 'p-done' - ]); - })); + cmp.exp = false; + fixture.detectChanges(); + flushMicrotasks(); + expect(cmp.log).toEqual([ + 'c1-start', 'c1-done', 'c2-start', 'c2-done', 'p-start', 'c3-start', 'c3-done', + 'p-done' + ]); + })); it('should build, but not run sub triggers when a parent animation is scheduled', () => { @Component({ @@ -2732,23 +2737,24 @@ import {fakeAsync, flushMicrotasks} from '../../testing/src/fake_async'; expect(engine.players[0].getRealPlayer()).toBe(players[1]); }); - it('should fire and synchronize the start/done callbacks on sub triggers even if they are not allowed to animate within the animation', - fakeAsync(() => { - @Component({ - selector: 'parent-cmp', - animations: [ - trigger( - 'parent', - [ - transition( - '* => go', - [ - style({height: '0px'}), - animate(1000, style({height: '100px'})), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should fire and synchronize the start/done callbacks on sub triggers even if they are not allowed to animate within the animation', + fakeAsync(() => { + @Component({ + selector: 'parent-cmp', + animations: [ + trigger( + 'parent', + [ + transition( + '* => go', + [ + style({height: '0px'}), + animate(1000, style({height: '100px'})), + ]), + ]), + ], + template: `
` - }) - class ParentCmp { - @ViewChild('child') public childCmp: any; + }) + class ParentCmp { + @ViewChild('child') public childCmp: any; - public exp: any; - public log: string[] = []; - public remove = false; + public exp: any; + public log: string[] = []; + public remove = false; - track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } - } + track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } + } - @Component({ - selector: 'child-cmp', - animations: [ - trigger( - 'child', - [ - transition( - '* => go', - [ - style({width: '0px'}), - animate(1000, style({width: '100px'})), - ]), - ]), - ], - template: ` + @Component({ + selector: 'child-cmp', + animations: [ + trigger( + 'child', + [ + transition( + '* => go', + [ + style({width: '0px'}), + animate(1000, style({width: '100px'})), + ]), + ]), + ], + template: `
` - }) - class ChildCmp { - public exp: any; - public log: string[] = []; - track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } - } + }) + class ChildCmp { + public exp: any; + public log: string[] = []; + track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } + } - TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ParentCmp); - fixture.detectChanges(); - flushMicrotasks(); + TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]}); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ParentCmp); + fixture.detectChanges(); + flushMicrotasks(); - const cmp = fixture.componentInstance; - const child = cmp.childCmp; + const cmp = fixture.componentInstance; + const child = cmp.childCmp; - expect(cmp.log).toEqual(['parent-start', 'parent-done']); - expect(child.log).toEqual(['child-start', 'child-done']); + expect(cmp.log).toEqual(['parent-start', 'parent-done']); + expect(child.log).toEqual(['child-start', 'child-done']); - cmp.log = []; - child.log = []; - cmp.exp = 'go'; - cmp.childCmp.exp = 'go'; - fixture.detectChanges(); - flushMicrotasks(); + cmp.log = []; + child.log = []; + cmp.exp = 'go'; + cmp.childCmp.exp = 'go'; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual(['parent-start']); - expect(child.log).toEqual(['child-start']); + expect(cmp.log).toEqual(['parent-start']); + expect(child.log).toEqual(['child-start']); - const players = engine.players; - expect(players.length).toEqual(1); - players[0].finish(); + const players = engine.players; + expect(players.length).toEqual(1); + players[0].finish(); - expect(cmp.log).toEqual(['parent-start', 'parent-done']); - expect(child.log).toEqual(['child-start', 'child-done']); + expect(cmp.log).toEqual(['parent-start', 'parent-done']); + expect(child.log).toEqual(['child-start', 'child-done']); - cmp.log = []; - child.log = []; - cmp.remove = true; - fixture.detectChanges(); - flushMicrotasks(); + cmp.log = []; + child.log = []; + cmp.remove = true; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual(['parent-start', 'parent-done']); - expect(child.log).toEqual(['child-start', 'child-done']); - })); + expect(cmp.log).toEqual(['parent-start', 'parent-done']); + expect(child.log).toEqual(['child-start', 'child-done']); + })); - it('should fire and synchronize the start/done callbacks on multiple blocked sub triggers', - fakeAsync(() => { - @Component({ - selector: 'cmp', - animations: [ - trigger( - 'parent1', - [ - transition( - '* => go, * => go-again', - [ - style({opacity: 0}), - animate('1s', style({opacity: 1})), - ]), - ]), - trigger( - 'parent2', - [ - transition( - '* => go, * => go-again', - [ - style({lineHeight: '0px'}), - animate('1s', style({lineHeight: '10px'})), - ]), - ]), - trigger( - 'child1', - [ - transition( - '* => go, * => go-again', - [ - style({width: '0px'}), - animate('1s', style({width: '100px'})), - ]), - ]), - trigger( - 'child2', - [ - transition( - '* => go, * => go-again', - [ - style({height: '0px'}), - animate('1s', style({height: '100px'})), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should fire and synchronize the start/done callbacks on multiple blocked sub triggers', + fakeAsync(() => { + @Component({ + selector: 'cmp', + animations: [ + trigger( + 'parent1', + [ + transition( + '* => go, * => go-again', + [ + style({opacity: 0}), + animate('1s', style({opacity: 1})), + ]), + ]), + trigger( + 'parent2', + [ + transition( + '* => go, * => go-again', + [ + style({lineHeight: '0px'}), + animate('1s', style({lineHeight: '10px'})), + ]), + ]), + trigger( + 'child1', + [ + transition( + '* => go, * => go-again', + [ + style({width: '0px'}), + animate('1s', style({width: '100px'})), + ]), + ]), + trigger( + 'child2', + [ + transition( + '* => go, * => go-again', + [ + style({height: '0px'}), + animate('1s', style({height: '100px'})), + ]), + ]), + ], + template: `
` - }) - class Cmp { - public parent1Exp = ''; - public parent2Exp = ''; - public child1Exp = ''; - public child2Exp = ''; - public log: string[] = []; + }) + class Cmp { + public parent1Exp = ''; + public parent2Exp = ''; + public child1Exp = ''; + public child2Exp = ''; + public log: string[] = []; - track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } - } + track(event: any) { this.log.push(`${event.triggerName}-${event.phaseName}`); } + } - TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - fixture.detectChanges(); - flushMicrotasks(); + TestBed.configureTestingModule({declarations: [Cmp]}); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + fixture.detectChanges(); + flushMicrotasks(); - const cmp = fixture.componentInstance; - cmp.log = []; - cmp.parent1Exp = 'go'; - cmp.parent2Exp = 'go'; - cmp.child1Exp = 'go'; - cmp.child2Exp = 'go'; - fixture.detectChanges(); - flushMicrotasks(); + const cmp = fixture.componentInstance; + cmp.log = []; + cmp.parent1Exp = 'go'; + cmp.parent2Exp = 'go'; + cmp.child1Exp = 'go'; + cmp.child2Exp = 'go'; + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual( - ['parent1-start', 'parent2-start', 'child1-start', 'child2-start']); + expect(cmp.log).toEqual( + ['parent1-start', 'parent2-start', 'child1-start', 'child2-start']); - cmp.parent1Exp = 'go-again'; - cmp.parent2Exp = 'go-again'; - cmp.child1Exp = 'go-again'; - cmp.child2Exp = 'go-again'; - fixture.detectChanges(); - flushMicrotasks(); - })); + cmp.parent1Exp = 'go-again'; + cmp.parent2Exp = 'go-again'; + cmp.child1Exp = 'go-again'; + cmp.child2Exp = 'go-again'; + fixture.detectChanges(); + flushMicrotasks(); + })); it('should stretch the starting keyframe of a child animation queries are issued by the parent', () => { diff --git a/packages/core/test/animation/animation_router_integration_spec.ts b/packages/core/test/animation/animation_router_integration_spec.ts index 3225a8727f..2dbc90591e 100644 --- a/packages/core/test/animation/animation_router_integration_spec.ts +++ b/packages/core/test/animation/animation_router_integration_spec.ts @@ -11,6 +11,7 @@ import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/brow import {Component, HostBinding} from '@angular/core'; import {TestBed, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {fixmeIvy} from '@angular/private/testing'; import {ActivatedRoute, Router, RouterOutlet} from '@angular/router'; import {RouterTestingModule} from '@angular/router/testing'; @@ -33,349 +34,354 @@ import {RouterTestingModule} from '@angular/router/testing'; }); }); - it('should query the old and new routes via :leave and :enter', fakeAsync(() => { - @Component({ - animations: [ - trigger( - 'routerAnimations', - [ - transition( - 'page1 => page2', - [ - query(':leave', animateChild()), - query(':enter', animateChild()), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should query the old and new routes via :leave and :enter', fakeAsync(() => { + @Component({ + animations: [ + trigger( + 'routerAnimations', + [ + transition( + 'page1 => page2', + [ + query(':leave', animateChild()), + query(':enter', animateChild()), + ]), + ]), + ], + template: `
` - }) - class ContainerCmp { - constructor(public router: Router) {} + }) + class ContainerCmp { + constructor(public router: Router) {} - prepareRouteAnimation(r: RouterOutlet) { - const animation = r.activatedRouteData['animation']; - const value = animation ? animation['value'] : null; - return value; - } - } + prepareRouteAnimation(r: RouterOutlet) { + const animation = r.activatedRouteData['animation']; + const value = animation ? animation['value'] : null; + return value; + } + } - @Component({ - selector: 'page1', - template: `page1`, - animations: [ - trigger( - 'page1Animation', - [ - transition( - ':leave', - [ - style({width: '200px'}), - animate(1000, style({width: '0px'})), - ]), - ]), - ] - }) - class Page1Cmp { - @HostBinding('@page1Animation') public doAnimate = true; - } + @Component({ + selector: 'page1', + template: `page1`, + animations: [ + trigger( + 'page1Animation', + [ + transition( + ':leave', + [ + style({width: '200px'}), + animate(1000, style({width: '0px'})), + ]), + ]), + ] + }) + class Page1Cmp { + @HostBinding('@page1Animation') public doAnimate = true; + } - @Component({ - selector: 'page2', - template: `page2`, - animations: [ - trigger( - 'page2Animation', - [ - transition( - ':enter', - [ - style({opacity: 0}), - animate(1000, style({opacity: 1})), - ]), - ]), - ] - }) - class Page2Cmp { - @HostBinding('@page2Animation') public doAnimate = true; - } + @Component({ + selector: 'page2', + template: `page2`, + animations: [ + trigger( + 'page2Animation', + [ + transition( + ':enter', + [ + style({opacity: 0}), + animate(1000, style({opacity: 1})), + ]), + ]), + ] + }) + class Page2Cmp { + @HostBinding('@page2Animation') public doAnimate = true; + } - TestBed.configureTestingModule({ - declarations: [Page1Cmp, Page2Cmp, ContainerCmp], - imports: [RouterTestingModule.withRoutes([ - {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, - {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} - ])] - }); + TestBed.configureTestingModule({ + declarations: [Page1Cmp, Page2Cmp, ContainerCmp], + imports: [RouterTestingModule.withRoutes([ + {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, + {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} + ])] + }); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ContainerCmp); - const cmp = fixture.componentInstance; - cmp.router.initialNavigation(); - tick(); - fixture.detectChanges(); - engine.flush(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ContainerCmp); + const cmp = fixture.componentInstance; + cmp.router.initialNavigation(); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page1'); - tick(); - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page1'); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page2'); - tick(); - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page2'); + tick(); + fixture.detectChanges(); + engine.flush(); - const player = engine.players[0] !; - const groupPlayer = player.getRealPlayer() as AnimationGroupPlayer; - const players = groupPlayer.players as MockAnimationPlayer[]; + const player = engine.players[0] !; + const groupPlayer = player.getRealPlayer() as AnimationGroupPlayer; + const players = groupPlayer.players as MockAnimationPlayer[]; - expect(players.length).toEqual(2); - const [p1, p2] = players; + expect(players.length).toEqual(2); + const [p1, p2] = players; - expect(p1.duration).toEqual(1000); - expect(p1.keyframes).toEqual([ - {offset: 0, width: '200px'}, - {offset: 1, width: '0px'}, - ]); + expect(p1.duration).toEqual(1000); + expect(p1.keyframes).toEqual([ + {offset: 0, width: '200px'}, + {offset: 1, width: '0px'}, + ]); - expect(p2.duration).toEqual(2000); - expect(p2.keyframes).toEqual([ - {offset: 0, opacity: '0'}, - {offset: .5, opacity: '0'}, - {offset: 1, opacity: '1'}, - ]); - })); + expect(p2.duration).toEqual(2000); + expect(p2.keyframes).toEqual([ + {offset: 0, opacity: '0'}, + {offset: .5, opacity: '0'}, + {offset: 1, opacity: '1'}, + ]); + })); - it('should allow inner enter animations to be emulated within a routed item', fakeAsync(() => { - @Component({ - animations: [ - trigger( - 'routerAnimations', - [ - transition( - 'page1 => page2', - [ - query(':enter', animateChild()), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should allow inner enter animations to be emulated within a routed item', fakeAsync(() => { + @Component({ + animations: [ + trigger( + 'routerAnimations', + [ + transition( + 'page1 => page2', + [ + query(':enter', animateChild()), + ]), + ]), + ], + template: `
` - }) - class ContainerCmp { - constructor(public router: Router) {} + }) + class ContainerCmp { + constructor(public router: Router) {} - prepareRouteAnimation(r: RouterOutlet) { - const animation = r.activatedRouteData['animation']; - const value = animation ? animation['value'] : null; - return value; - } - } + prepareRouteAnimation(r: RouterOutlet) { + const animation = r.activatedRouteData['animation']; + const value = animation ? animation['value'] : null; + return value; + } + } - @Component({selector: 'page1', template: `page1`, animations: []}) - class Page1Cmp { - } + @Component({selector: 'page1', template: `page1`, animations: []}) + class Page1Cmp { + } - @Component({ - selector: 'page2', - template: ` + @Component({ + selector: 'page2', + template: `

Page 2

`, - animations: [ - trigger( - 'page2Animation', - [ - transition( - ':enter', - [query('.if-one', animateChild()), query('.if-two', animateChild())]), - ]), - trigger( - 'ifAnimation', - [transition( - ':enter', [style({opacity: 0}), animate(1000, style({opacity: 1}))])]) - ] - }) - class Page2Cmp { - @HostBinding('@page2Animation') public doAnimate = true; + animations: [ + trigger( + 'page2Animation', + [ + transition( + ':enter', + [query('.if-one', animateChild()), query('.if-two', animateChild())]), + ]), + trigger( + 'ifAnimation', + [transition( + ':enter', [style({opacity: 0}), animate(1000, style({opacity: 1}))])]) + ] + }) + class Page2Cmp { + @HostBinding('@page2Animation') public doAnimate = true; - public exp = true; - } + public exp = true; + } - TestBed.configureTestingModule({ - declarations: [Page1Cmp, Page2Cmp, ContainerCmp], - imports: [RouterTestingModule.withRoutes([ - {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, - {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} - ])] - }); + TestBed.configureTestingModule({ + declarations: [Page1Cmp, Page2Cmp, ContainerCmp], + imports: [RouterTestingModule.withRoutes([ + {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, + {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} + ])] + }); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ContainerCmp); - const cmp = fixture.componentInstance; - cmp.router.initialNavigation(); - tick(); - fixture.detectChanges(); - engine.flush(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ContainerCmp); + const cmp = fixture.componentInstance; + cmp.router.initialNavigation(); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page1'); - tick(); - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page1'); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page2'); - tick(); - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page2'); + tick(); + fixture.detectChanges(); + engine.flush(); - const player = engine.players[0] !; - const groupPlayer = player.getRealPlayer() as AnimationGroupPlayer; - const players = groupPlayer.players as MockAnimationPlayer[]; + const player = engine.players[0] !; + const groupPlayer = player.getRealPlayer() as AnimationGroupPlayer; + const players = groupPlayer.players as MockAnimationPlayer[]; - expect(players.length).toEqual(2); - const [p1, p2] = players; + expect(players.length).toEqual(2); + const [p1, p2] = players; - expect(p1.keyframes).toEqual([ - {offset: 0, opacity: '0'}, - {offset: 1, opacity: '1'}, - ]); + expect(p1.keyframes).toEqual([ + {offset: 0, opacity: '0'}, + {offset: 1, opacity: '1'}, + ]); - expect(p2.keyframes).toEqual([ - {offset: 0, opacity: '0'}, - {offset: .5, opacity: '0'}, - {offset: 1, opacity: '1'}, - ]); - })); + expect(p2.keyframes).toEqual([ + {offset: 0, opacity: '0'}, + {offset: .5, opacity: '0'}, + {offset: 1, opacity: '1'}, + ]); + })); - it('should allow inner leave animations to be emulated within a routed item', fakeAsync(() => { - @Component({ - animations: [ - trigger( - 'routerAnimations', - [ - transition( - 'page1 => page2', - [ - query(':leave', animateChild()), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should allow inner leave animations to be emulated within a routed item', fakeAsync(() => { + @Component({ + animations: [ + trigger( + 'routerAnimations', + [ + transition( + 'page1 => page2', + [ + query(':leave', animateChild()), + ]), + ]), + ], + template: `
` - }) - class ContainerCmp { - constructor(public router: Router) {} + }) + class ContainerCmp { + constructor(public router: Router) {} - prepareRouteAnimation(r: RouterOutlet) { - const animation = r.activatedRouteData['animation']; - const value = animation ? animation['value'] : null; - return value; - } - } + prepareRouteAnimation(r: RouterOutlet) { + const animation = r.activatedRouteData['animation']; + const value = animation ? animation['value'] : null; + return value; + } + } - @Component({ - selector: 'page1', - template: ` + @Component({ + selector: 'page1', + template: `

Page 1

`, - animations: [ - trigger( - 'page1Animation', - [ - transition( - ':leave', - [query('.if-one', animateChild()), query('.if-two', animateChild())]), - ]), - trigger( - 'ifAnimation', - [transition(':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])]), - ] - }) - class Page1Cmp { - @HostBinding('@page1Animation') public doAnimate = true; + animations: [ + trigger( + 'page1Animation', + [ + transition( + ':leave', + [query('.if-one', animateChild()), query('.if-two', animateChild())]), + ]), + trigger( + 'ifAnimation', + [transition( + ':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])]), + ] + }) + class Page1Cmp { + @HostBinding('@page1Animation') public doAnimate = true; - public exp = true; - } + public exp = true; + } - @Component({selector: 'page2', template: `page2`, animations: []}) - class Page2Cmp { - } + @Component({selector: 'page2', template: `page2`, animations: []}) + class Page2Cmp { + } - TestBed.configureTestingModule({ - declarations: [Page1Cmp, Page2Cmp, ContainerCmp], - imports: [RouterTestingModule.withRoutes([ - {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, - {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} - ])] - }); + TestBed.configureTestingModule({ + declarations: [Page1Cmp, Page2Cmp, ContainerCmp], + imports: [RouterTestingModule.withRoutes([ + {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, + {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} + ])] + }); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ContainerCmp); - const cmp = fixture.componentInstance; - cmp.router.initialNavigation(); - tick(); - fixture.detectChanges(); - engine.flush(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ContainerCmp); + const cmp = fixture.componentInstance; + cmp.router.initialNavigation(); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page1'); - tick(); - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page1'); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page2'); - tick(); - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page2'); + tick(); + fixture.detectChanges(); + engine.flush(); - const player = engine.players[0] !; - const groupPlayer = player.getRealPlayer() as AnimationGroupPlayer; - const players = groupPlayer.players as MockAnimationPlayer[]; + const player = engine.players[0] !; + const groupPlayer = player.getRealPlayer() as AnimationGroupPlayer; + const players = groupPlayer.players as MockAnimationPlayer[]; - expect(players.length).toEqual(2); - const [p1, p2] = players; + expect(players.length).toEqual(2); + const [p1, p2] = players; - expect(p1.keyframes).toEqual([ - {offset: 0, opacity: '1'}, - {offset: 1, opacity: '0'}, - ]); + expect(p1.keyframes).toEqual([ + {offset: 0, opacity: '1'}, + {offset: 1, opacity: '0'}, + ]); - expect(p2.keyframes).toEqual([ - {offset: 0, opacity: '1'}, - {offset: .5, opacity: '1'}, - {offset: 1, opacity: '0'}, - ]); - })); + expect(p2.keyframes).toEqual([ + {offset: 0, opacity: '1'}, + {offset: .5, opacity: '1'}, + {offset: 1, opacity: '0'}, + ]); + })); - it('should properly collect :enter / :leave router nodes even when another non-router *template component is within the trigger boundaries', - fakeAsync(() => { - @Component({ - selector: 'ani-cmp', - animations: [ - trigger( - 'pageAnimation', - [ - transition( - 'page1 => page2', - [ - query('.router-container :leave', animate('1s', style({opacity: 0}))), - query('.router-container :enter', animate('1s', style({opacity: 1}))), - ]), - ]), - ], - template: ` + fixmeIvy('unknown').it( + 'should properly collect :enter / :leave router nodes even when another non-router *template component is within the trigger boundaries', + fakeAsync(() => { + @Component({ + selector: 'ani-cmp', + animations: [ + trigger( + 'pageAnimation', + [ + transition( + 'page1 => page2', + [ + query('.router-container :leave', animate('1s', style({opacity: 0}))), + query('.router-container :enter', animate('1s', style({opacity: 1}))), + ]), + ]), + ], + template: `
@@ -388,136 +394,139 @@ import {RouterTestingModule} from '@angular/router/testing';
` - }) - class ContainerCmp { - loading = false; + }) + class ContainerCmp { + loading = false; - constructor(public router: Router) {} + constructor(public router: Router) {} - prepRoute(outlet: any) { return outlet.activatedRouteData['animation']; } - } + prepRoute(outlet: any) { return outlet.activatedRouteData['animation']; } + } - @Component({selector: 'page1', template: `page1`}) - class Page1Cmp { - } + @Component({selector: 'page1', template: `page1`}) + class Page1Cmp { + } - @Component({selector: 'page2', template: `page2`}) - class Page2Cmp { - } + @Component({selector: 'page2', template: `page2`}) + class Page2Cmp { + } - TestBed.configureTestingModule({ - declarations: [Page1Cmp, Page2Cmp, ContainerCmp], - imports: [RouterTestingModule.withRoutes([ - {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, - {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} - ])] - }); + TestBed.configureTestingModule({ + declarations: [Page1Cmp, Page2Cmp, ContainerCmp], + imports: [RouterTestingModule.withRoutes([ + {path: 'page1', component: Page1Cmp, data: makeAnimationData('page1')}, + {path: 'page2', component: Page2Cmp, data: makeAnimationData('page2')} + ])] + }); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(ContainerCmp); - const cmp = fixture.componentInstance; - cmp.router.initialNavigation(); - tick(); - fixture.detectChanges(); - engine.flush(); + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(ContainerCmp); + const cmp = fixture.componentInstance; + cmp.router.initialNavigation(); + tick(); + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page1'); - tick(); - cmp.loading = true; - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page1'); + tick(); + cmp.loading = true; + fixture.detectChanges(); + engine.flush(); - cmp.router.navigateByUrl('/page2'); - tick(); - cmp.loading = false; - fixture.detectChanges(); - engine.flush(); + cmp.router.navigateByUrl('/page2'); + tick(); + cmp.loading = false; + fixture.detectChanges(); + engine.flush(); - const players = engine.players; - expect(players.length).toEqual(1); - const [p1] = players; + const players = engine.players; + expect(players.length).toEqual(1); + const [p1] = players; - const innerPlayers = p1.getRealPlayer().players; - expect(innerPlayers.length).toEqual(2); + const innerPlayers = p1.getRealPlayer().players; + expect(innerPlayers.length).toEqual(2); - const [ip1, ip2] = innerPlayers; - expect(ip1.element.innerText).toEqual('page1'); - expect(ip2.element.innerText).toEqual('page2'); - })); + const [ip1, ip2] = innerPlayers; + expect(ip1.element.innerText).toEqual('page1'); + expect(ip2.element.innerText).toEqual('page2'); + })); - it('should allow a recursive set of :leave animations to occur for nested routes', - fakeAsync(() => { - @Component({selector: 'ani-cmp', template: ''}) - class ContainerCmp { - constructor(private _router: Router) {} - log: string[] = []; + fixmeIvy('unknown').it( + 'should allow a recursive set of :leave animations to occur for nested routes', + fakeAsync(() => { + @Component( + {selector: 'ani-cmp', template: ''}) + class ContainerCmp { + constructor(private _router: Router) {} + log: string[] = []; - enter() { this._router.navigateByUrl('/(recur:recur/nested)'); } + enter() { this._router.navigateByUrl('/(recur:recur/nested)'); } - leave() { this._router.navigateByUrl('/'); } - } + leave() { this._router.navigateByUrl('/'); } + } - @Component({ - selector: 'recur-page', - template: 'Depth: {{ depth }} \n ', - animations: [ - trigger( - 'pageAnimations', - [ - transition(':leave', [group([ - sequence([style({opacity: 1}), animate('1s', style({opacity: 0}))]), - query('@*', animateChild(), {optional: true}) - ])]), - ]), - ] - }) - class RecurPageCmp { - @HostBinding('@pageAnimations') public animatePage = true; + @Component({ + selector: 'recur-page', + template: 'Depth: {{ depth }} \n ', + animations: [ + trigger( + 'pageAnimations', + [ + transition( + ':leave', [group([ + sequence([style({opacity: 1}), animate('1s', style({opacity: 0}))]), + query('@*', animateChild(), {optional: true}) + ])]), + ]), + ] + }) + class RecurPageCmp { + @HostBinding('@pageAnimations') public animatePage = true; - @HostBinding('attr.data-depth') public depth = 0; + @HostBinding('attr.data-depth') public depth = 0; - constructor(private container: ContainerCmp, private route: ActivatedRoute) { - this.route.data.subscribe(data => { - this.container.log.push(`DEPTH ${data.depth}`); - this.depth = data.depth; - }); - } - } + constructor(private container: ContainerCmp, private route: ActivatedRoute) { + this.route.data.subscribe(data => { + this.container.log.push(`DEPTH ${data.depth}`); + this.depth = data.depth; + }); + } + } - TestBed.configureTestingModule({ - declarations: [ContainerCmp, RecurPageCmp], - imports: [RouterTestingModule.withRoutes([{ - path: 'recur', - component: RecurPageCmp, - outlet: 'recur', - data: {depth: 0}, - children: [{path: 'nested', component: RecurPageCmp, data: {depth: 1}}] - }])] - }); + TestBed.configureTestingModule({ + declarations: [ContainerCmp, RecurPageCmp], + imports: [RouterTestingModule.withRoutes([{ + path: 'recur', + component: RecurPageCmp, + outlet: 'recur', + data: {depth: 0}, + children: [{path: 'nested', component: RecurPageCmp, data: {depth: 1}}] + }])] + }); - const fixture = TestBed.createComponent(ContainerCmp); - const cmp = fixture.componentInstance; - cmp.enter(); - tick(); - fixture.detectChanges(); - flushMicrotasks(); + const fixture = TestBed.createComponent(ContainerCmp); + const cmp = fixture.componentInstance; + cmp.enter(); + tick(); + fixture.detectChanges(); + flushMicrotasks(); - expect(cmp.log).toEqual([ - 'DEPTH 0', - 'DEPTH 1', - ]); + expect(cmp.log).toEqual([ + 'DEPTH 0', + 'DEPTH 1', + ]); - cmp.leave(); - tick(); - fixture.detectChanges(); + cmp.leave(); + tick(); + fixture.detectChanges(); - const players = getLog(); - expect(players.length).toEqual(2); + const players = getLog(); + expect(players.length).toEqual(2); - const [p1, p2] = players; - expect(p1.element.getAttribute('data-depth')).toEqual('0'); - expect(p2.element.getAttribute('data-depth')).toEqual('1'); - })); + const [p1, p2] = players; + expect(p1.element.getAttribute('data-depth')).toEqual('0'); + expect(p2.element.getAttribute('data-depth')).toEqual('1'); + })); }); }); diff --git a/packages/core/test/animation/animations_with_web_animations_integration_spec.ts b/packages/core/test/animation/animations_with_web_animations_integration_spec.ts index 53bdd3cd59..7b2ec1ec2a 100644 --- a/packages/core/test/animation/animations_with_web_animations_integration_spec.ts +++ b/packages/core/test/animation/animations_with_web_animations_integration_spec.ts @@ -5,15 +5,15 @@ * 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 {animate, group, query, state, style, transition, trigger} from '@angular/animations'; +import {animate, query, state, style, transition, trigger} from '@angular/animations'; import {AnimationDriver, ɵAnimationEngine, ɵWebAnimationsDriver, ɵWebAnimationsPlayer, ɵsupportsWebAnimations} from '@angular/animations/browser'; import {TransitionAnimationPlayer} from '@angular/animations/browser/src/render/transition_animation_engine'; import {AnimationGroupPlayer} from '@angular/animations/src/players/animation_group_player'; import {Component} from '@angular/core'; +import {TestBed} from '@angular/core/testing'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {browserDetection} from '@angular/platform-browser/testing/src/browser_util'; - -import {TestBed} from '../../testing'; +import {fixmeIvy} from '@angular/private/testing'; (function() { // these tests are only mean't to be run within the DOM (for now) @@ -242,9 +242,10 @@ import {TestBed} from '../../testing'; ]); }); - it('should treat * styles as ! for queried items that are collected in a container that is being removed', - () => { - @Component({ + fixmeIvy('unknown').it( + 'should treat * styles as ! for queried items that are collected in a container that is being removed', + () => { + @Component({ selector: 'my-app', styles: [` .list .outer { @@ -285,58 +286,58 @@ import {TestBed} from '../../testing'; ] }) class Cmp { - items: any[] = []; + items: any[] = []; - get exp() { return this.items.length ? 'full' : 'empty'; } + get exp() { return this.items.length ? 'full' : 'empty'; } - empty() { this.items = []; } + empty() { this.items = []; } - full() { this.items = [0, 1, 2, 3, 4]; } - } + full() { this.items = [0, 1, 2, 3, 4]; } + } - TestBed.configureTestingModule({declarations: [Cmp]}); + TestBed.configureTestingModule({declarations: [Cmp]}); - const engine = TestBed.get(ɵAnimationEngine); - const fixture = TestBed.createComponent(Cmp); - const cmp = fixture.componentInstance; + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; - cmp.empty(); - fixture.detectChanges(); - let player = engine.players[0] !as TransitionAnimationPlayer; - player.finish(); + cmp.empty(); + fixture.detectChanges(); + let player = engine.players[0] !as TransitionAnimationPlayer; + player.finish(); - cmp.full(); - fixture.detectChanges(); + cmp.full(); + fixture.detectChanges(); - player = engine.players[0] !as TransitionAnimationPlayer; - let queriedPlayers = (player.getRealPlayer() as AnimationGroupPlayer).players; - expect(queriedPlayers.length).toEqual(5); + player = engine.players[0] !as TransitionAnimationPlayer; + let queriedPlayers = (player.getRealPlayer() as AnimationGroupPlayer).players; + expect(queriedPlayers.length).toEqual(5); - let i = 0; - for (i = 0; i < queriedPlayers.length; i++) { - let player = queriedPlayers[i] as ɵWebAnimationsPlayer; - expect(player.keyframes).toEqual([ - {height: '0px', offset: 0}, - {height: '50px', offset: 1}, - ]); - player.finish(); - } + let i = 0; + for (i = 0; i < queriedPlayers.length; i++) { + let player = queriedPlayers[i] as ɵWebAnimationsPlayer; + expect(player.keyframes).toEqual([ + {height: '0px', offset: 0}, + {height: '50px', offset: 1}, + ]); + player.finish(); + } - cmp.empty(); - fixture.detectChanges(); + cmp.empty(); + fixture.detectChanges(); - player = engine.players[0] !as TransitionAnimationPlayer; - queriedPlayers = (player.getRealPlayer() as AnimationGroupPlayer).players; - expect(queriedPlayers.length).toEqual(5); + player = engine.players[0] !as TransitionAnimationPlayer; + queriedPlayers = (player.getRealPlayer() as AnimationGroupPlayer).players; + expect(queriedPlayers.length).toEqual(5); - for (i = 0; i < queriedPlayers.length; i++) { - let player = queriedPlayers[i] as ɵWebAnimationsPlayer; - expect(player.keyframes).toEqual([ - {height: '50px', offset: 0}, - {height: '0px', offset: 1}, - ]); - } - }); + for (i = 0; i < queriedPlayers.length; i++) { + let player = queriedPlayers[i] as ɵWebAnimationsPlayer; + expect(player.keyframes).toEqual([ + {height: '50px', offset: 0}, + {height: '0px', offset: 1}, + ]); + } + }); it('should compute intermediate styles properly when an animation is cancelled', () => { @Component({ diff --git a/packages/core/test/linker/change_detection_integration_spec.ts b/packages/core/test/linker/change_detection_integration_spec.ts index 2a4f42deb4..8bded58d0f 100644 --- a/packages/core/test/linker/change_detection_integration_spec.ts +++ b/packages/core/test/linker/change_detection_integration_spec.ts @@ -13,6 +13,7 @@ import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing'; import {By} from '@angular/platform-browser/src/dom/debug/by'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {expect} from '@angular/platform-browser/testing/src/matchers'; +import {fixmeIvy} from '@angular/private/testing'; export function createUrlResolverWithoutPackagePrefix(): UrlResolver { return new UrlResolver(); @@ -445,13 +446,14 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ })); - it('should ignore empty bindings', fakeAsync(() => { - const ctx = _bindSimpleProp('[someProp]', TestData); - ctx.componentInstance.a = 'value'; - ctx.detectChanges(false); + fixmeIvy('FW-814: Bindings with an empty value should be ignored in the compiler') + .it('should ignore empty bindings', fakeAsync(() => { + const ctx = _bindSimpleProp('[someProp]', TestData); + ctx.componentInstance.a = 'value'; + ctx.detectChanges(false); - expect(renderLog.log).toEqual([]); - })); + expect(renderLog.log).toEqual([]); + })); it('should support interpolation', fakeAsync(() => { const ctx = _bindSimpleProp('someProp="B{{a}}A"', TestData); @@ -537,27 +539,28 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ expect(renderLog.log).toEqual(['someProp=Megatron']); })); - it('should record unwrapped values via ngOnChanges', fakeAsync(() => { - const ctx = createCompFixture( - '
'); - const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0]; - ctx.detectChanges(false); - dir.changes = {}; - ctx.detectChanges(false); + fixmeIvy('unknown').it( + 'should record unwrapped values via ngOnChanges', fakeAsync(() => { + const ctx = createCompFixture( + '
'); + const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0]; + ctx.detectChanges(false); + dir.changes = {}; + ctx.detectChanges(false); - // Note: the binding for `b` did not change and has no ValueWrapper, - // and should therefore stay unchanged. - expect(dir.changes).toEqual({ - 'name': new SimpleChange('aName', 'aName', false), - 'b': new SimpleChange(2, 2, false) - }); + // Note: the binding for `b` did not change and has no ValueWrapper, + // and should therefore stay unchanged. + expect(dir.changes).toEqual({ + 'name': new SimpleChange('aName', 'aName', false), + 'b': new SimpleChange(2, 2, false) + }); - ctx.detectChanges(false); - expect(dir.changes).toEqual({ - 'name': new SimpleChange('aName', 'aName', false), - 'b': new SimpleChange(2, 2, false) - }); - })); + ctx.detectChanges(false); + expect(dir.changes).toEqual({ + 'name': new SimpleChange('aName', 'aName', false), + 'b': new SimpleChange(2, 2, false) + }); + })); it('should call pure pipes only if the arguments change', fakeAsync(() => { const ctx = _bindSimpleValue('name | countingPipe', Person); @@ -588,29 +591,30 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ })); - it('should call pure pipes that are used multiple times only when the arguments change', - fakeAsync(() => { - const ctx = createCompFixture( - `
` + - '
', - Person); - ctx.componentInstance.name = 'a'; - ctx.componentInstance.age = 10; - ctx.componentInstance.address = new Address('mtv'); - ctx.detectChanges(false); - expect(renderLog.loggedValues).toEqual([ - 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3' - ]); - ctx.detectChanges(false); - expect(renderLog.loggedValues).toEqual([ - 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3' - ]); - ctx.componentInstance.age = 11; - ctx.detectChanges(false); - expect(renderLog.loggedValues).toEqual([ - 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3', '11 state:4' - ]); - })); + fixmeIvy('unknown').it( + 'should call pure pipes that are used multiple times only when the arguments change', + fakeAsync(() => { + const ctx = createCompFixture( + `
` + + '
', + Person); + ctx.componentInstance.name = 'a'; + ctx.componentInstance.age = 10; + ctx.componentInstance.address = new Address('mtv'); + ctx.detectChanges(false); + expect(renderLog.loggedValues).toEqual([ + 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3' + ]); + ctx.detectChanges(false); + expect(renderLog.loggedValues).toEqual([ + 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3' + ]); + ctx.componentInstance.age = 11; + ctx.detectChanges(false); + expect(renderLog.loggedValues).toEqual([ + 'mtv state:0', 'mtv state:1', 'a state:2', '10 state:3', '11 state:4' + ]); + })); it('should call impure pipes on each change detection run', fakeAsync(() => { const ctx = _bindSimpleValue('name | countingImpurePipe', Person); @@ -994,31 +998,32 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]); })); - it('should not call ngAfterViewInit again if it throws', fakeAsync(() => { - const ctx = - createCompFixture('
'); + fixmeIvy('unknown').it( + 'should not call ngAfterViewInit again if it throws', fakeAsync(() => { + const ctx = + createCompFixture('
'); - let errored = false; - // First pass fails, but ngAfterViewInit should be called. - try { - ctx.detectChanges(false); - } catch (e) { - errored = true; - } - expect(errored).toBe(true); + let errored = false; + // First pass fails, but ngAfterViewInit should be called. + try { + ctx.detectChanges(false); + } catch (e) { + errored = true; + } + expect(errored).toBe(true); - expect(directiveLog.filter(['ngAfterViewInit'])).toEqual(['dir.ngAfterViewInit']); - directiveLog.clear(); + expect(directiveLog.filter(['ngAfterViewInit'])).toEqual(['dir.ngAfterViewInit']); + directiveLog.clear(); - // Second change detection also fails, but this time ngAfterViewInit should not be - // called. - try { - ctx.detectChanges(false); - } catch (e) { - throw new Error('Second detectChanges() should not have run detection.'); - } - expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]); - })); + // Second change detection also fails, but this time ngAfterViewInit should not be + // called. + try { + ctx.detectChanges(false); + } catch (e) { + throw new Error('Second detectChanges() should not have run detection.'); + } + expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]); + })); }); describe('ngAfterViewChecked', () => { @@ -1073,111 +1078,119 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ }); describe('ngOnDestroy', () => { - it('should be called on view destruction', fakeAsync(() => { - const ctx = createCompFixture('
'); - ctx.detectChanges(false); + fixmeIvy('unknown').it( + 'should be called on view destruction', fakeAsync(() => { + const ctx = createCompFixture('
'); + ctx.detectChanges(false); - ctx.destroy(); + ctx.destroy(); - expect(directiveLog.filter(['ngOnDestroy'])).toEqual(['dir.ngOnDestroy']); - })); + expect(directiveLog.filter(['ngOnDestroy'])).toEqual(['dir.ngOnDestroy']); + })); - it('should be called after processing the content and view children', fakeAsync(() => { - TestBed.overrideComponent(AnotherComponent, { - set: new Component( - {selector: 'other-cmp', template: '
'}) - }); + fixmeIvy('unknown').it( + 'should be called after processing the content and view children', fakeAsync(() => { + TestBed.overrideComponent(AnotherComponent, { + set: new Component( + {selector: 'other-cmp', template: '
'}) + }); - const ctx = createCompFixture( - '
' + - '
', - TestComponent); + const ctx = createCompFixture( + '
' + + '
', + TestComponent); - ctx.detectChanges(false); - ctx.destroy(); + ctx.detectChanges(false); + ctx.destroy(); - expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ - 'contentChild0.ngOnDestroy', 'contentChild1.ngOnDestroy', 'viewChild.ngOnDestroy', - 'parent.ngOnDestroy' - ]); - })); + expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ + 'contentChild0.ngOnDestroy', 'contentChild1.ngOnDestroy', 'viewChild.ngOnDestroy', + 'parent.ngOnDestroy' + ]); + })); - it('should be called in reverse order so the child is always notified before the parent', - fakeAsync(() => { - const ctx = createCompFixture( - '
'); + fixmeIvy('unknown').it( + 'should be called in reverse order so the child is always notified before the parent', + fakeAsync(() => { + const ctx = createCompFixture( + '
'); - ctx.detectChanges(false); - ctx.destroy(); + ctx.detectChanges(false); + ctx.destroy(); - expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ - 'child.ngOnDestroy', 'parent.ngOnDestroy', 'sibling.ngOnDestroy' - ]); - })); + expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ + 'child.ngOnDestroy', 'parent.ngOnDestroy', 'sibling.ngOnDestroy' + ]); + })); - it('should deliver synchronous events to parent', fakeAsync(() => { - const ctx = createCompFixture('
'); + fixmeIvy('unknown').it( + 'should deliver synchronous events to parent', fakeAsync(() => { + const ctx = createCompFixture('
'); - ctx.detectChanges(false); - ctx.destroy(); + ctx.detectChanges(false); + ctx.destroy(); - expect(ctx.componentInstance.a).toEqual('destroyed'); - })); + expect(ctx.componentInstance.a).toEqual('destroyed'); + })); - it('should call ngOnDestroy on pipes', fakeAsync(() => { - const ctx = createCompFixture('{{true | pipeWithOnDestroy }}'); + fixmeIvy('unknown').it('should call ngOnDestroy on pipes', fakeAsync(() => { + const ctx = createCompFixture('{{true | pipeWithOnDestroy }}'); - ctx.detectChanges(false); - ctx.destroy(); + ctx.detectChanges(false); + ctx.destroy(); - expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ - 'pipeWithOnDestroy.ngOnDestroy' - ]); - })); + expect(directiveLog.filter(['ngOnDestroy'])).toEqual([ + 'pipeWithOnDestroy.ngOnDestroy' + ]); + })); - it('should call ngOnDestroy on an injectable class', fakeAsync(() => { - TestBed.overrideDirective( - TestDirective, {set: {providers: [InjectableWithLifecycle]}}); + fixmeIvy('unknown').it('should call ngOnDestroy on an injectable class', fakeAsync(() => { + TestBed.overrideDirective( + TestDirective, {set: {providers: [InjectableWithLifecycle]}}); - const ctx = createCompFixture('
', TestComponent); + const ctx = createCompFixture( + '
', TestComponent); - ctx.debugElement.children[0].injector.get(InjectableWithLifecycle); - ctx.detectChanges(false); + ctx.debugElement.children[0].injector.get(InjectableWithLifecycle); + ctx.detectChanges(false); - ctx.destroy(); + ctx.destroy(); - // We don't care about the exact order in this test. - expect(directiveLog.filter(['ngOnDestroy']).sort()).toEqual([ - 'dir.ngOnDestroy', 'injectable.ngOnDestroy' - ]); - })); + // We don't care about the exact order in this test. + expect(directiveLog.filter(['ngOnDestroy']).sort()).toEqual([ + 'dir.ngOnDestroy', 'injectable.ngOnDestroy' + ]); + })); }); }); describe('enforce no new changes', () => { - it('should throw when a record gets changed after it has been checked', fakeAsync(() => { - @Directive({selector: '[changed]'}) - class ChangingDirective { - @Input() changed: any; - } + fixmeIvy('unknown').it( + 'should throw when a record gets changed after it has been checked', fakeAsync(() => { + @Directive({selector: '[changed]'}) + class ChangingDirective { + @Input() changed: any; + } - TestBed.configureTestingModule({declarations: [ChangingDirective]}); + TestBed.configureTestingModule({declarations: [ChangingDirective]}); - const ctx = createCompFixture('
', TestData); + const ctx = createCompFixture('
', TestData); - ctx.componentInstance.b = 1; + ctx.componentInstance.b = 1; - expect(() => ctx.checkNoChanges()) - .toThrowError(/Previous value: 'changed: undefined'\. Current value: 'changed: 1'/g); - })); + expect(() => ctx.checkNoChanges()) + .toThrowError( + /Previous value: 'changed: undefined'\. Current value: 'changed: 1'/g); + })); - it('should warn when the view has been created in a cd hook', fakeAsync(() => { - const ctx = createCompFixture('
{{ a }}
', TestData); - ctx.componentInstance.a = 1; - expect(() => ctx.detectChanges()) - .toThrowError( - /It seems like the view has been created after its parent and its children have been dirty checked/); - })); + fixmeIvy('unknown').it( + 'should warn when the view has been created in a cd hook', fakeAsync(() => { + const ctx = createCompFixture('
{{ a }}
', TestData); + ctx.componentInstance.a = 1; + expect(() => ctx.detectChanges()) + .toThrowError( + /It seems like the view has been created after its parent and its children have been dirty checked/); + })); it('should not throw when two arrays are structurally the same', fakeAsync(() => { const ctx = _bindSimpleValue('a', TestData); @@ -1187,27 +1200,27 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ expect(() => ctx.checkNoChanges()).not.toThrow(); })); - it('should not break the next run', fakeAsync(() => { - const ctx = _bindSimpleValue('a', TestData); - ctx.componentInstance.a = 'value'; - expect(() => ctx.checkNoChanges()).toThrow(); + fixmeIvy('unknown').it('should not break the next run', fakeAsync(() => { + const ctx = _bindSimpleValue('a', TestData); + ctx.componentInstance.a = 'value'; + expect(() => ctx.checkNoChanges()).toThrow(); - ctx.detectChanges(); - expect(renderLog.loggedValues).toEqual(['value']); - })); + ctx.detectChanges(); + expect(renderLog.loggedValues).toEqual(['value']); + })); }); describe('mode', () => { - it('Detached', fakeAsync(() => { - const ctx = createCompFixture(''); - const cmp: CompWithRef = queryDirs(ctx.debugElement, CompWithRef)[0]; - cmp.value = 'hello'; - cmp.changeDetectorRef.detach(); + fixmeIvy('unknown').it('Detached', fakeAsync(() => { + const ctx = createCompFixture(''); + const cmp: CompWithRef = queryDirs(ctx.debugElement, CompWithRef)[0]; + cmp.value = 'hello'; + cmp.changeDetectorRef.detach(); - ctx.detectChanges(); + ctx.detectChanges(); - expect(renderLog.log).toEqual([]); - })); + expect(renderLog.log).toEqual([]); + })); it('Detached should disable OnPush', fakeAsync(() => { const ctx = createCompFixture(''); @@ -1260,34 +1273,36 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ })); - it('Reattaches in the original cd mode', fakeAsync(() => { - const ctx = createCompFixture(''); - const cmp: PushComp = queryDirs(ctx.debugElement, PushComp)[0]; - cmp.changeDetectorRef.detach(); - cmp.changeDetectorRef.reattach(); + fixmeIvy('unknown').it('Reattaches in the original cd mode', fakeAsync(() => { + const ctx = createCompFixture(''); + const cmp: PushComp = queryDirs(ctx.debugElement, PushComp)[0]; + cmp.changeDetectorRef.detach(); + cmp.changeDetectorRef.reattach(); - // renderCount should NOT be incremented with each CD as CD mode should be resetted to - // on-push - ctx.detectChanges(); - expect(cmp.renderCount).toBeGreaterThan(0); - const count = cmp.renderCount; + // renderCount should NOT be incremented with each CD as CD mode + // should be resetted to + // on-push + ctx.detectChanges(); + expect(cmp.renderCount).toBeGreaterThan(0); + const count = cmp.renderCount; - ctx.detectChanges(); - expect(cmp.renderCount).toBe(count); - })); + ctx.detectChanges(); + expect(cmp.renderCount).toBe(count); + })); }); describe('multi directive order', () => { - it('should follow the DI order for the same element', fakeAsync(() => { - const ctx = - createCompFixture('
'); + fixmeIvy('unknown').it( + 'should follow the DI order for the same element', fakeAsync(() => { + const ctx = + createCompFixture('
'); - ctx.detectChanges(false); - ctx.destroy(); + ctx.detectChanges(false); + ctx.destroy(); - expect(directiveLog.filter(['set'])).toEqual(['0.set', '1.set', '2.set']); - })); + expect(directiveLog.filter(['set'])).toEqual(['0.set', '1.set', '2.set']); + })); }); describe('nested view recursion', () => { @@ -1424,25 +1439,26 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ expect(log).toEqual(['inner-start', 'main-tpl', 'outer-tpl']); }); - it('should dirty check projected views if the declaration place is dirty checked', () => { - ctx.detectChanges(false); - log = []; - innerComp.cdRef.detach(); - mainComp.cdRef.detectChanges(); + fixmeIvy('unknown').it( + 'should dirty check projected views if the declaration place is dirty checked', () => { + ctx.detectChanges(false); + log = []; + innerComp.cdRef.detach(); + mainComp.cdRef.detectChanges(); - expect(log).toEqual(['main-start', 'outer-start', 'main-tpl', 'outer-tpl']); + expect(log).toEqual(['main-start', 'outer-start', 'main-tpl', 'outer-tpl']); - log = []; - outerComp.cdRef.detectChanges(); + log = []; + outerComp.cdRef.detectChanges(); - expect(log).toEqual(['outer-start', 'outer-tpl']); + expect(log).toEqual(['outer-start', 'outer-tpl']); - log = []; - outerComp.cdRef.detach(); - mainComp.cdRef.detectChanges(); + log = []; + outerComp.cdRef.detach(); + mainComp.cdRef.detectChanges(); - expect(log).toEqual(['main-start', 'main-tpl']); - }); + expect(log).toEqual(['main-start', 'main-tpl']); + }); }); }); @@ -1516,7 +1532,7 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [ childThrows: LifetimeMethods; } - describe('calling init', () => { + fixmeIvy('unknown').describe('calling init', () => { function initialize(options: Options) { @Component({selector: 'my-child', template: ''}) class MyChild { diff --git a/packages/core/test/linker/integration_spec.ts b/packages/core/test/linker/integration_spec.ts index 63a7186d81..079bb2132b 100644 --- a/packages/core/test/linker/integration_spec.ts +++ b/packages/core/test/linker/integration_spec.ts @@ -700,30 +700,31 @@ function declareTests(config?: {useJit: boolean}) { }); if (getDOM().supportsDOMEvents()) { - it('should be checked when an async pipe requests a check', fakeAsync(() => { - TestBed.configureTestingModule( - {declarations: [MyComp, PushCmpWithAsyncPipe], imports: [CommonModule]}); - const template = ''; - TestBed.overrideComponent(MyComp, {set: {template}}); - const fixture = TestBed.createComponent(MyComp); + fixmeIvy('unknown').it( + 'should be checked when an async pipe requests a check', fakeAsync(() => { + TestBed.configureTestingModule( + {declarations: [MyComp, PushCmpWithAsyncPipe], imports: [CommonModule]}); + const template = ''; + TestBed.overrideComponent(MyComp, {set: {template}}); + const fixture = TestBed.createComponent(MyComp); - tick(); + tick(); - const cmp: PushCmpWithAsyncPipe = - fixture.debugElement.children[0].references !['cmp']; - fixture.detectChanges(); - expect(cmp.numberOfChecks).toEqual(1); + const cmp: PushCmpWithAsyncPipe = + fixture.debugElement.children[0].references !['cmp']; + fixture.detectChanges(); + expect(cmp.numberOfChecks).toEqual(1); - fixture.detectChanges(); - fixture.detectChanges(); - expect(cmp.numberOfChecks).toEqual(1); + fixture.detectChanges(); + fixture.detectChanges(); + expect(cmp.numberOfChecks).toEqual(1); - cmp.resolve(2); - tick(); + cmp.resolve(2); + tick(); - fixture.detectChanges(); - expect(cmp.numberOfChecks).toEqual(2); - })); + fixture.detectChanges(); + expect(cmp.numberOfChecks).toEqual(2); + })); } }); @@ -1872,7 +1873,7 @@ function declareTests(config?: {useJit: boolean}) { if (getDOM().supportsDOMEvents()) { describe('svg', () => { - it('should support svg elements', () => { + fixmeIvy('unknown').it('should support svg elements', () => { TestBed.configureTestingModule({declarations: [MyComp]}); const template = ''; TestBed.overrideComponent(MyComp, {set: {template}}); @@ -1891,7 +1892,7 @@ function declareTests(config?: {useJit: boolean}) { expect(firstAttribute.namespaceURI).toEqual('http://www.w3.org/1999/xlink'); }); - it('should support foreignObjects with document fragments', () => { + fixmeIvy('unknown').it('should support foreignObjects with document fragments', () => { TestBed.configureTestingModule({declarations: [MyComp]}); const template = '

Test

'; @@ -1913,7 +1914,7 @@ function declareTests(config?: {useJit: boolean}) { describe('attributes', () => { - it('should support attributes with namespace', () => { + fixmeIvy('unknown').it('should support attributes with namespace', () => { TestBed.configureTestingModule({declarations: [MyComp, SomeCmp]}); const template = ''; TestBed.overrideComponent(SomeCmp, {set: {template}}); @@ -1924,7 +1925,7 @@ function declareTests(config?: {useJit: boolean}) { .toEqual('#id'); }); - it('should support binding to attributes with namespace', () => { + fixmeIvy('unknown').it('should support binding to attributes with namespace', () => { TestBed.configureTestingModule({declarations: [MyComp, SomeCmp]}); const template = ''; TestBed.overrideComponent(SomeCmp, {set: {template}}); diff --git a/packages/core/test/linker/projection_integration_spec.ts b/packages/core/test/linker/projection_integration_spec.ts index 534c24e5d7..8e6f0f0bdc 100644 --- a/packages/core/test/linker/projection_integration_spec.ts +++ b/packages/core/test/linker/projection_integration_spec.ts @@ -370,21 +370,22 @@ describe('projection', () => { }); if (getDOM().supportsNativeShadowDOM()) { - it('should support native content projection and isolate styles per component', () => { - TestBed.configureTestingModule({declarations: [SimpleNative1, SimpleNative2]}); - TestBed.overrideComponent(MainComp, { - set: { - template: '
A
' + - '
B
' - } - }); - const main = TestBed.createComponent(MainComp); + fixmeIvy('unknown').it( + 'should support native content projection and isolate styles per component', () => { + TestBed.configureTestingModule({declarations: [SimpleNative1, SimpleNative2]}); + TestBed.overrideComponent(MainComp, { + set: { + template: '
A
' + + '
B
' + } + }); + const main = TestBed.createComponent(MainComp); - const childNodes = getDOM().childNodes(main.nativeElement); - expect(childNodes[0]).toHaveText('div {color: red}SIMPLE1(A)'); - expect(childNodes[1]).toHaveText('div {color: blue}SIMPLE2(B)'); - main.destroy(); - }); + const childNodes = getDOM().childNodes(main.nativeElement); + expect(childNodes[0]).toHaveText('div {color: red}SIMPLE1(A)'); + expect(childNodes[1]).toHaveText('div {color: blue}SIMPLE2(B)'); + main.destroy(); + }); } if (getDOM().supportsDOMEvents()) { diff --git a/packages/core/test/linker/regression_integration_spec.ts b/packages/core/test/linker/regression_integration_spec.ts index 02f5fa71be..92f79c131c 100644 --- a/packages/core/test/linker/regression_integration_spec.ts +++ b/packages/core/test/linker/regression_integration_spec.ts @@ -428,7 +428,7 @@ function declareTestsUsingBootstrap() { if (getDOM().supportsDOMEvents()) { // This test needs a real DOM.... - it('should keep change detecting if there was an error', (done) => { + fixmeIvy('unknown').it('should keep change detecting if there was an error', (done) => { @Component({ selector: COMP_SELECTOR, template: diff --git a/packages/core/test/linker/view_injector_integration_spec.ts b/packages/core/test/linker/view_injector_integration_spec.ts index f957b03656..f58ea53887 100644 --- a/packages/core/test/linker/view_injector_integration_spec.ts +++ b/packages/core/test/linker/view_injector_integration_spec.ts @@ -10,6 +10,7 @@ import {Attribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, Compon import {ComponentFixture, TestBed, fakeAsync} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {expect} from '@angular/platform-browser/testing/src/matchers'; +import {fixmeIvy} from '@angular/private/testing'; @Directive({selector: '[simpleDirective]'}) class SimpleDirective { @@ -291,7 +292,7 @@ class TestComp { expect(el.children[0].injector.get('injectable2')).toEqual('injectable1-injectable2'); }); - it('should instantiate viewProviders that have dependencies', () => { + fixmeIvy('unknown').it('should instantiate viewProviders that have dependencies', () => { TestBed.configureTestingModule({declarations: [SimpleComponent]}); const viewProviders = [ {provide: 'injectable1', useValue: 'injectable1'}, { @@ -428,7 +429,7 @@ class TestComp { expect(ctx.debugElement.injector.get('eager2')).toBe('v2: v1'); }); - it('should inject providers that were declared after it', () => { + fixmeIvy('unknown').it('should inject providers that were declared after it', () => { @Component({ template: '', providers: [ @@ -464,7 +465,7 @@ class TestComp { expect(comp.componentInstance.a).toBe('aValue'); }); - it('should support ngOnDestroy for lazy providers', () => { + fixmeIvy('unknown').it('should support ngOnDestroy for lazy providers', () => { let created = false; let destroyed = false; @@ -496,7 +497,7 @@ class TestComp { expect(destroyed).toBe(true); }); - it('should instantiate view providers lazily', () => { + fixmeIvy('unknown').it('should instantiate view providers lazily', () => { let created = false; TestBed.configureTestingModule({declarations: [SimpleComponent]}); TestBed.overrideComponent( @@ -551,38 +552,45 @@ class TestComp { .toEqual('parentService'); }); - it('should instantiate directives that depend on providers of a component', () => { - TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]}); - TestBed.overrideComponent( - SimpleComponent, {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent(SimpleComponent, {set: {template: '
'}}); - const el = createComponent('
'); - expect(el.children[0].children[0].injector.get(NeedsService).service) - .toEqual('hostService'); - }); + fixmeIvy('unknown').it( + 'should instantiate directives that depend on providers of a component', () => { + TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + const el = createComponent('
'); + expect(el.children[0].children[0].injector.get(NeedsService).service) + .toEqual('hostService'); + }); - it('should instantiate directives that depend on view providers of a component', () => { - TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]}); - TestBed.overrideComponent( - SimpleComponent, {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent(SimpleComponent, {set: {template: '
'}}); - const el = createComponent('
'); - expect(el.children[0].children[0].injector.get(NeedsService).service) - .toEqual('hostService'); - }); + fixmeIvy('unknown').it( + 'should instantiate directives that depend on view providers of a component', () => { + TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + const el = createComponent('
'); + expect(el.children[0].children[0].injector.get(NeedsService).service) + .toEqual('hostService'); + }); - it('should instantiate directives in a root embedded view that depend on view providers of a component', - () => { - TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]}); - TestBed.overrideComponent( - SimpleComponent, - {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); - const el = createComponent('
'); - expect(el.children[0].children[0].injector.get(NeedsService).service) - .toEqual('hostService'); - }); + fixmeIvy('unknown').it( + 'should instantiate directives in a root embedded view that depend on view providers of a component', + () => { + TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsService]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + const el = createComponent('
'); + expect(el.children[0].children[0].injector.get(NeedsService).service) + .toEqual('hostService'); + }); it('should instantiate directives that depend on instances in the app injector', () => { TestBed.configureTestingModule({declarations: [NeedsAppService]}); @@ -590,54 +598,57 @@ class TestComp { expect(el.children[0].injector.get(NeedsAppService).service).toEqual('appService'); }); - it('should not instantiate a directive with cyclic dependencies', () => { + fixmeIvy('unknown').it('should not instantiate a directive with cyclic dependencies', () => { TestBed.configureTestingModule({declarations: [CycleDirective]}); expect(() => createComponent('
')) .toThrowError( /Template parse errors:\nCannot instantiate cyclic dependency! CycleDirective \("\[ERROR ->\]
<\/div>"\): .*TestComp.html@0:0/); }); - it('should not instantiate a directive in a view that has a host dependency on providers' + - ' of the component', - () => { - TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsServiceFromHost]}); - TestBed.overrideComponent( - SimpleComponent, - {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); + fixmeIvy('unknown').it( + 'should not instantiate a directive in a view that has a host dependency on providers' + + ' of the component', + () => { + TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsServiceFromHost]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); - expect(() => createComponent('
')) - .toThrowError( - /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); - }); + expect(() => createComponent('
')) + .toThrowError( + /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); + }); - it('should not instantiate a directive in a view that has a host dependency on providers' + - ' of a decorator directive', - () => { - TestBed.configureTestingModule( - {declarations: [SimpleComponent, SomeOtherDirective, NeedsServiceFromHost]}); - TestBed.overrideComponent( - SimpleComponent, - {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); + fixmeIvy('unknown').it( + 'should not instantiate a directive in a view that has a host dependency on providers' + + ' of a decorator directive', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, SomeOtherDirective, NeedsServiceFromHost]}); + TestBed.overrideComponent( + SimpleComponent, + {set: {providers: [{provide: 'service', useValue: 'hostService'}]}}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); - expect(() => createComponent('
')) - .toThrowError( - /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); - }); + expect(() => createComponent('
')) + .toThrowError( + /Template parse errors:\nNo provider for service \("\[ERROR ->\]
"\): .*SimpleComponent.html@0:0/); + }); - it('should not instantiate a directive in a view that has a self dependency on a parent directive', - () => { - TestBed.configureTestingModule( - {declarations: [SimpleDirective, NeedsDirectiveFromSelf]}); - expect( - () => - createComponent('
')) - .toThrowError( - /Template parse errors:\nNo provider for SimpleDirective \("
\[ERROR ->\]
<\/div><\/div>"\): .*TestComp.html@0:21/); - }); + fixmeIvy('unknown').it( + 'should not instantiate a directive in a view that has a self dependency on a parent directive', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleDirective, NeedsDirectiveFromSelf]}); + expect( + () => createComponent( + '
')) + .toThrowError( + /Template parse errors:\nNo provider for SimpleDirective \("
\[ERROR ->\]
<\/div><\/div>"\): .*TestComp.html@0:21/); + }); it('should instantiate directives that depend on other directives', fakeAsync(() => { TestBed.configureTestingModule({declarations: [SimpleDirective, NeedsDirective]}); @@ -662,48 +673,54 @@ class TestComp { expect(d.dependency).toBeNull(); }); - it('should instantiate directives that depends on the host component', () => { - TestBed.configureTestingModule({declarations: [SimpleComponent, NeedsComponentFromHost]}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); - const el = createComponent('
'); - const d = el.children[0].children[0].injector.get(NeedsComponentFromHost); - expect(d.dependency).toBeAnInstanceOf(SimpleComponent); - }); + fixmeIvy('unknown').it( + 'should instantiate directives that depends on the host component', () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, NeedsComponentFromHost]}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + const el = createComponent('
'); + const d = el.children[0].children[0].injector.get(NeedsComponentFromHost); + expect(d.dependency).toBeAnInstanceOf(SimpleComponent); + }); - it('should instantiate host views for components that have a @Host dependency ', () => { - TestBed.configureTestingModule({declarations: [NeedsHostAppService]}); - const el = createComponent('', [], NeedsHostAppService); - expect(el.componentInstance.service).toEqual('appService'); - }); + fixmeIvy('unknown').it( + 'should instantiate host views for components that have a @Host dependency ', () => { + TestBed.configureTestingModule({declarations: [NeedsHostAppService]}); + const el = createComponent('', [], NeedsHostAppService); + expect(el.componentInstance.service).toEqual('appService'); + }); - it('should not instantiate directives that depend on other directives on the host element', () => { - TestBed.configureTestingModule( - {declarations: [SimpleComponent, SimpleDirective, NeedsDirectiveFromHost]}); - TestBed.overrideComponent( - SimpleComponent, {set: {template: '
'}}); - expect(() => createComponent('
')) - .toThrowError( - /Template parse errors:\nNo provider for SimpleDirective \("\[ERROR ->\]
<\/div>"\): .*SimpleComponent.html@0:0/); - }); + fixmeIvy('unknown').it( + 'should not instantiate directives that depend on other directives on the host element', + () => { + TestBed.configureTestingModule( + {declarations: [SimpleComponent, SimpleDirective, NeedsDirectiveFromHost]}); + TestBed.overrideComponent( + SimpleComponent, {set: {template: '
'}}); + expect(() => createComponent('
')) + .toThrowError( + /Template parse errors:\nNo provider for SimpleDirective \("\[ERROR ->\]
<\/div>"\): .*SimpleComponent.html@0:0/); + }); - it('should allow to use the NgModule injector from a root ViewContainerRef.parentInjector', - () => { - @Component({template: ''}) - class MyComp { - constructor(public vc: ViewContainerRef) {} - } + fixmeIvy('unknown').it( + 'should allow to use the NgModule injector from a root ViewContainerRef.parentInjector', + () => { + @Component({template: ''}) + class MyComp { + constructor(public vc: ViewContainerRef) {} + } - const compFixture = TestBed - .configureTestingModule({ - declarations: [MyComp], - providers: [{provide: 'someToken', useValue: 'someValue'}] - }) - .createComponent(MyComp); + const compFixture = TestBed + .configureTestingModule({ + declarations: [MyComp], + providers: [{provide: 'someToken', useValue: 'someValue'}] + }) + .createComponent(MyComp); - expect(compFixture.componentInstance.vc.parentInjector.get('someToken')) - .toBe('someValue'); - }); + expect(compFixture.componentInstance.vc.parentInjector.get('someToken')) + .toBe('someValue'); + }); }); describe('static attributes', () => { @@ -734,85 +751,97 @@ class TestComp { .toBe(el.children[0].nativeElement); }); - it('should inject ChangeDetectorRef of the component\'s view into the component', () => { - TestBed.configureTestingModule({declarations: [PushComponentNeedsChangeDetectorRef]}); - const cf = createComponentFixture('
'); - cf.detectChanges(); - const compEl = cf.debugElement.children[0]; - const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); - comp.counter = 1; - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('0'); - comp.changeDetectorRef.markForCheck(); - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('1'); - }); + fixmeIvy('unknown').it( + 'should inject ChangeDetectorRef of the component\'s view into the component', () => { + TestBed.configureTestingModule({declarations: [PushComponentNeedsChangeDetectorRef]}); + const cf = createComponentFixture('
'); + cf.detectChanges(); + const compEl = cf.debugElement.children[0]; + const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); + comp.counter = 1; + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + comp.changeDetectorRef.markForCheck(); + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('1'); + }); - it('should inject ChangeDetectorRef of the containing component into directives', () => { - TestBed.configureTestingModule( - {declarations: [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef]}); - TestBed.overrideComponent(PushComponentNeedsChangeDetectorRef, { - set: { - template: - '{{counter}}
' - } - }); - const cf = createComponentFixture('
'); - cf.detectChanges(); - const compEl = cf.debugElement.children[0]; - const comp: PushComponentNeedsChangeDetectorRef = - compEl.injector.get(PushComponentNeedsChangeDetectorRef); - comp.counter = 1; - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('0'); - expect(compEl.children[0].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef) - .toEqual(comp.changeDetectorRef); - expect(compEl.children[1].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef) - .toEqual(comp.changeDetectorRef); - comp.changeDetectorRef.markForCheck(); - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('1'); - }); + fixmeIvy('unknown').it( + 'should inject ChangeDetectorRef of the containing component into directives', () => { + TestBed.configureTestingModule({ + declarations: + [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef] + }); + TestBed.overrideComponent(PushComponentNeedsChangeDetectorRef, { + set: { + template: + '{{counter}}
' + } + }); + const cf = createComponentFixture('
'); + cf.detectChanges(); + const compEl = cf.debugElement.children[0]; + const comp: PushComponentNeedsChangeDetectorRef = + compEl.injector.get(PushComponentNeedsChangeDetectorRef); + comp.counter = 1; + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + expect( + compEl.children[0].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef) + .toEqual(comp.changeDetectorRef); + expect( + compEl.children[1].injector.get(DirectiveNeedsChangeDetectorRef).changeDetectorRef) + .toEqual(comp.changeDetectorRef); + comp.changeDetectorRef.markForCheck(); + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('1'); + }); - it('should inject ChangeDetectorRef of a same element component into a directive', () => { - TestBed.configureTestingModule( - {declarations: [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef]}); - const cf = createComponentFixture( - '
'); - cf.detectChanges(); - const compEl = cf.debugElement.children[0]; - const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); - const dir = compEl.injector.get(DirectiveNeedsChangeDetectorRef); - comp.counter = 1; - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('0'); - dir.changeDetectorRef.markForCheck(); - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('1'); - }); + fixmeIvy('unknown').it( + 'should inject ChangeDetectorRef of a same element component into a directive', () => { + TestBed.configureTestingModule({ + declarations: + [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef] + }); + const cf = createComponentFixture( + '
'); + cf.detectChanges(); + const compEl = cf.debugElement.children[0]; + const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); + const dir = compEl.injector.get(DirectiveNeedsChangeDetectorRef); + comp.counter = 1; + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + dir.changeDetectorRef.markForCheck(); + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('1'); + }); - it(`should not inject ChangeDetectorRef of a parent element's component into a directive`, () => { - TestBed - .configureTestingModule({ - declarations: [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef] - }) - .overrideComponent( - PushComponentNeedsChangeDetectorRef, - {set: {template: '{{counter}}'}}); - const cf = createComponentFixture( - '
'); - cf.detectChanges(); - const compEl = cf.debugElement.children[0]; - const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); - const dirEl = compEl.children[0]; - const dir = dirEl.injector.get(DirectiveNeedsChangeDetectorRef); - comp.counter = 1; - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('0'); - dir.changeDetectorRef.markForCheck(); - cf.detectChanges(); - expect(compEl.nativeElement).toHaveText('0'); - }); + fixmeIvy('unknown').it( + `should not inject ChangeDetectorRef of a parent element's component into a directive`, + () => { + TestBed + .configureTestingModule({ + declarations: + [PushComponentNeedsChangeDetectorRef, DirectiveNeedsChangeDetectorRef] + }) + .overrideComponent( + PushComponentNeedsChangeDetectorRef, + {set: {template: '{{counter}}'}}); + const cf = createComponentFixture( + '
'); + cf.detectChanges(); + const compEl = cf.debugElement.children[0]; + const comp = compEl.injector.get(PushComponentNeedsChangeDetectorRef); + const dirEl = compEl.children[0]; + const dir = dirEl.injector.get(DirectiveNeedsChangeDetectorRef); + comp.counter = 1; + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + dir.changeDetectorRef.markForCheck(); + cf.detectChanges(); + expect(compEl.nativeElement).toHaveText('0'); + }); it('should inject ViewContainerRef', () => { TestBed.configureTestingModule({declarations: [NeedsViewContainerRef]}); @@ -822,7 +851,7 @@ class TestComp { .toBe(el.children[0].nativeElement); }); - it('should inject ViewContainerRef', () => { + fixmeIvy('unknown').it('should inject ViewContainerRef', () => { @Component({template: ''}) class TestComp { constructor(public vcr: ViewContainerRef) {} @@ -847,7 +876,7 @@ class TestComp { expect(component.instance.vcr.parentInjector.get('someToken')).toBe('someNewValue'); }); - it('should inject TemplateRef', () => { + fixmeIvy('unknown').it('should inject TemplateRef', () => { TestBed.configureTestingModule({declarations: [NeedsViewContainerRef, NeedsTemplateRef]}); const el = createComponent(''); @@ -855,7 +884,7 @@ class TestComp { .toEqual(el.childNodes[0].injector.get(NeedsViewContainerRef).viewContainer.element); }); - it('should throw if there is no TemplateRef', () => { + fixmeIvy('unknown').it('should throw if there is no TemplateRef', () => { TestBed.configureTestingModule({declarations: [NeedsTemplateRef]}); expect(() => createComponent('
')) .toThrowError(/No provider for TemplateRef!/); @@ -870,7 +899,7 @@ class TestComp { }); describe('pipes', () => { - it('should instantiate pipes that have dependencies', () => { + fixmeIvy('unknown').it('should instantiate pipes that have dependencies', () => { TestBed.configureTestingModule({declarations: [SimpleDirective, PipeNeedsService]}); const el = createComponent( @@ -879,7 +908,7 @@ class TestComp { expect(el.children[0].injector.get(SimpleDirective).value.service).toEqual('pipeService'); }); - it('should overwrite pipes with later entry in the pipes array', () => { + fixmeIvy('unknown').it('should overwrite pipes with later entry in the pipes array', () => { TestBed.configureTestingModule( {declarations: [SimpleDirective, DuplicatePipe1, DuplicatePipe2]}); const el = createComponent('
'); @@ -898,7 +927,7 @@ class TestComp { expect(el.children[0].injector.get(SimpleDirective).value.changeDetectorRef).toEqual(cdRef); }); - it('should cache pure pipes', () => { + fixmeIvy('unknown').it('should cache pure pipes', () => { TestBed.configureTestingModule({declarations: [SimpleDirective, PurePipe]}); const el = createComponent( '
' + diff --git a/packages/core/test/view/component_view_spec.ts b/packages/core/test/view/component_view_spec.ts index 2c5aa1a0e1..c8d97015e0 100644 --- a/packages/core/test/view/component_view_spec.ts +++ b/packages/core/test/view/component_view_spec.ts @@ -9,6 +9,7 @@ import {SecurityContext} from '@angular/core'; import {ArgumentType, BindingFlags, NodeCheckFn, NodeFlags, Services, ViewData, ViewFlags, ViewState, asElementData, directiveDef, elementDef, rootRenderNodes} from '@angular/core/src/view/index'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; +import {fixmeIvy} from '@angular/private/testing'; import {callMostRecentEventListenerHandler, compViewDef, createAndGetRootNodes, createRootView, isBrowser, recordNodeToRemove} from './helper'; @@ -199,62 +200,64 @@ const addEventListener = '__zone_symbol__addEventListener' as 'addEventListener' }); if (isBrowser()) { - it('should support OnPush components', () => { - let compInputValue: any; - class AComp { - a: any; - } + fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') + .it('should support OnPush components', () => { + let compInputValue: any; + class AComp { + a: any; + } - const update = jasmine.createSpy('updater'); + const update = jasmine.createSpy('updater'); - const addListenerSpy = spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); + const addListenerSpy = + spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); - const {view} = createAndGetRootNodes(compViewDef( - [ - elementDef( - 0, NodeFlags.None, null, null, 1, 'div', null, null, null, null, - () => { - return compViewDef( - [ - elementDef( - 0, NodeFlags.None, null, null, 0, 'span', null, null, - [[null !, 'click']]), - ], - update, null, ViewFlags.OnPush); - }), - directiveDef(1, NodeFlags.Component, null, 0, AComp, [], {a: [0, 'a']}), - ], - (check, view) => { check(view, 1, ArgumentType.Inline, compInputValue); })); + const {view} = createAndGetRootNodes(compViewDef( + [ + elementDef( + 0, NodeFlags.None, null, null, 1, 'div', null, null, null, null, + () => { + return compViewDef( + [ + elementDef( + 0, NodeFlags.None, null, null, 0, 'span', null, null, + [[null !, 'click']]), + ], + update, null, ViewFlags.OnPush); + }), + directiveDef(1, NodeFlags.Component, null, 0, AComp, [], {a: [0, 'a']}), + ], + (check, view) => { check(view, 1, ArgumentType.Inline, compInputValue); })); - Services.checkAndUpdateView(view); + Services.checkAndUpdateView(view); - // auto detach - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).not.toHaveBeenCalled(); + // auto detach + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).not.toHaveBeenCalled(); - // auto attach on input changes - update.calls.reset(); - compInputValue = 'v1'; - Services.checkAndUpdateView(view); - expect(update).toHaveBeenCalled(); + // auto attach on input changes + update.calls.reset(); + compInputValue = 'v1'; + Services.checkAndUpdateView(view); + expect(update).toHaveBeenCalled(); - // auto detach - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).not.toHaveBeenCalled(); + // auto detach + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).not.toHaveBeenCalled(); - // auto attach on events - callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).toHaveBeenCalled(); + // auto attach on events + callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).toHaveBeenCalled(); - // auto detach - update.calls.reset(); - Services.checkAndUpdateView(view); - expect(update).not.toHaveBeenCalled(); - }); + // auto detach + update.calls.reset(); + Services.checkAndUpdateView(view); + expect(update).not.toHaveBeenCalled(); + }); } it('should not stop dirty checking views that threw errors in change detection', () => { diff --git a/packages/core/test/view/element_spec.ts b/packages/core/test/view/element_spec.ts index 5e9fe24afd..868675c97e 100644 --- a/packages/core/test/view/element_spec.ts +++ b/packages/core/test/view/element_spec.ts @@ -11,6 +11,7 @@ import {getDebugContext} from '@angular/core/src/errors'; import {BindingFlags, NodeFlags, Services, ViewData, ViewDefinition, asElementData, elementDef} from '@angular/core/src/view/index'; import {TestBed} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; +import {fixmeIvy} from '@angular/private/testing'; import {ARG_TYPE_VALUES, callMostRecentEventListenerHandler, checkNodeInlineOrDynamic, compViewDef, createAndGetRootNodes, isBrowser, recordNodeToRemove} from './helper'; @@ -184,26 +185,27 @@ const removeEventListener = '__zone_symbol__removeEventListener' as 'removeEvent return result; } - it('should listen to DOM events', () => { - const handleEventSpy = jasmine.createSpy('handleEvent'); - const removeListenerSpy = - spyOn(HTMLElement.prototype, removeEventListener).and.callThrough(); - const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( - 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], - handleEventSpy)])); + fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') + .it('should listen to DOM events', () => { + const handleEventSpy = jasmine.createSpy('handleEvent'); + const removeListenerSpy = + spyOn(HTMLElement.prototype, removeEventListener).and.callThrough(); + const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( + 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], + handleEventSpy)])); - rootNodes[0].click(); + rootNodes[0].click(); - expect(handleEventSpy).toHaveBeenCalled(); - let handleEventArgs = handleEventSpy.calls.mostRecent().args; - expect(handleEventArgs[0]).toBe(view); - expect(handleEventArgs[1]).toBe('click'); - expect(handleEventArgs[2]).toBeTruthy(); + expect(handleEventSpy).toHaveBeenCalled(); + let handleEventArgs = handleEventSpy.calls.mostRecent().args; + expect(handleEventArgs[0]).toBe(view); + expect(handleEventArgs[1]).toBe('click'); + expect(handleEventArgs[2]).toBeTruthy(); - Services.destroyView(view); + Services.destroyView(view); - expect(removeListenerSpy).toHaveBeenCalled(); - }); + expect(removeListenerSpy).toHaveBeenCalled(); + }); it('should listen to window events', () => { const handleEventSpy = jasmine.createSpy('handleEvent'); @@ -251,49 +253,52 @@ const removeEventListener = '__zone_symbol__removeEventListener' as 'removeEvent expect(removeListenerSpy).toHaveBeenCalled(); }); - it('should preventDefault only if the handler returns false', () => { - let eventHandlerResult: any; - let preventDefaultSpy: jasmine.Spy = undefined !; + fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') + .it('should preventDefault only if the handler returns false', () => { + let eventHandlerResult: any; + let preventDefaultSpy: jasmine.Spy = undefined !; - const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( - 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], - (view, eventName, event) => { - preventDefaultSpy = spyOn(event, 'preventDefault').and.callThrough(); - return eventHandlerResult; - })])); + const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( + 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], + (view, eventName, event) => { + preventDefaultSpy = spyOn(event, 'preventDefault').and.callThrough(); + return eventHandlerResult; + })])); - eventHandlerResult = undefined; - rootNodes[0].click(); - expect(preventDefaultSpy).not.toHaveBeenCalled(); + eventHandlerResult = undefined; + rootNodes[0].click(); + expect(preventDefaultSpy).not.toHaveBeenCalled(); - eventHandlerResult = true; - rootNodes[0].click(); - expect(preventDefaultSpy).not.toHaveBeenCalled(); + eventHandlerResult = true; + rootNodes[0].click(); + expect(preventDefaultSpy).not.toHaveBeenCalled(); - eventHandlerResult = 'someString'; - rootNodes[0].click(); - expect(preventDefaultSpy).not.toHaveBeenCalled(); + eventHandlerResult = 'someString'; + rootNodes[0].click(); + expect(preventDefaultSpy).not.toHaveBeenCalled(); - eventHandlerResult = false; - rootNodes[0].click(); - expect(preventDefaultSpy).toHaveBeenCalled(); - }); + eventHandlerResult = false; + rootNodes[0].click(); + expect(preventDefaultSpy).toHaveBeenCalled(); + }); - it('should report debug info on event errors', () => { - const handleErrorSpy = spyOn(TestBed.get(ErrorHandler), 'handleError'); - const addListenerSpy = spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); - const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( - 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], - () => { throw new Error('Test'); })])); + fixmeIvy('FW-665: Discovery util fails with "Unable to find context associated with ..."') + .it('should report debug info on event errors', () => { + const handleErrorSpy = spyOn(TestBed.get(ErrorHandler), 'handleError'); + const addListenerSpy = + spyOn(HTMLElement.prototype, addEventListener).and.callThrough(); + const {view, rootNodes} = createAndAttachAndGetRootNodes(compViewDef([elementDef( + 0, NodeFlags.None, null, null, 0, 'button', null, null, [[null !, 'click']], + () => { throw new Error('Test'); })])); - callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); - const err = handleErrorSpy.calls.mostRecent().args[0]; - expect(err).toBeTruthy(); - expect(err.message).toBe('Test'); - const debugCtx = getDebugContext(err); - expect(debugCtx.view).toBe(view); - expect(debugCtx.nodeIndex).toBe(0); - }); + callMostRecentEventListenerHandler(addListenerSpy, 'SomeEvent'); + const err = handleErrorSpy.calls.mostRecent().args[0]; + expect(err).toBeTruthy(); + expect(err.message).toBe('Test'); + const debugCtx = getDebugContext(err); + expect(debugCtx.view).toBe(view); + expect(debugCtx.nodeIndex).toBe(0); + }); }); } });