| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | import {animate, AnimationMetadata, style} from '@angular/animations'; | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | import {AnimationStyleNormalizer, NoopAnimationStyleNormalizer} from '../../src/dsl/style_normalization/animation_style_normalizer'; | 
					
						
							|  |  |  | import {AnimationDriver} from '../../src/render/animation_driver'; | 
					
						
							| 
									
										
										
										
											2018-04-10 15:10:29 -07:00
										 |  |  | import {getBodyNode} from '../../src/render/shared'; | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | import {TimelineAnimationEngine} from '../../src/render/timeline_animation_engine'; | 
					
						
							|  |  |  | import {MockAnimationDriver, MockAnimationPlayer} from '../../testing/src/mock_animation_driver'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 15:10:54 -08:00
										 |  |  | (function() { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | const defaultDriver = new MockAnimationDriver(); | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | function makeEngine(body: any, driver?: AnimationDriver, normalizer?: AnimationStyleNormalizer) { | 
					
						
							|  |  |  |   return new TimelineAnimationEngine( | 
					
						
							|  |  |  |       body, driver || defaultDriver, normalizer || new NoopAnimationStyleNormalizer()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // these tests are only mean't to be run within the DOM
 | 
					
						
							|  |  |  | if (isNode) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe('TimelineAnimationEngine', () => { | 
					
						
							|  |  |  |   let element: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     MockAnimationDriver.log = []; | 
					
						
							|  |  |  |     element = document.createElement('div'); | 
					
						
							|  |  |  |     document.body.appendChild(element); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   afterEach(() => document.body.removeChild(element)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should animate a timeline', () => { | 
					
						
							|  |  |  |     const engine = makeEngine(getBodyNode()); | 
					
						
							|  |  |  |     const steps = [style({height: 100}), animate(1000, style({height: 0}))]; | 
					
						
							|  |  |  |     expect(MockAnimationDriver.log.length).toEqual(0); | 
					
						
							|  |  |  |     invokeAnimation(engine, element, steps); | 
					
						
							|  |  |  |     expect(MockAnimationDriver.log.length).toEqual(1); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   it('should not destroy timeline-based animations after they have finished', () => { | 
					
						
							|  |  |  |     const engine = makeEngine(getBodyNode()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const log: string[] = []; | 
					
						
							|  |  |  |     function capture(value: string) { | 
					
						
							|  |  |  |       return () => { | 
					
						
							|  |  |  |         log.push(value); | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const steps = [style({height: 0}), animate(1000, style({height: 500}))]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const player = invokeAnimation(engine, element, steps); | 
					
						
							|  |  |  |     player.onDone(capture('done')); | 
					
						
							|  |  |  |     player.onDestroy(capture('destroy')); | 
					
						
							|  |  |  |     expect(log).toEqual([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     player.finish(); | 
					
						
							|  |  |  |     expect(log).toEqual(['done']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     player.destroy(); | 
					
						
							|  |  |  |     expect(log).toEqual(['done', 'destroy']); | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   it('should normalize the style values that are animateTransitioned within an a timeline animation', | 
					
						
							|  |  |  |      () => { | 
					
						
							|  |  |  |        const engine = makeEngine(getBodyNode(), defaultDriver, new SuffixNormalizer('-normalized')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        const steps = [ | 
					
						
							|  |  |  |          style({width: '333px'}), | 
					
						
							|  |  |  |          animate(1000, style({width: '999px'})), | 
					
						
							|  |  |  |        ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        const player = invokeAnimation(engine, element, steps) as MockAnimationPlayer; | 
					
						
							|  |  |  |        expect(player.keyframes).toEqual([ | 
					
						
							|  |  |  |          {'width-normalized': '333px-normalized', offset: 0}, | 
					
						
							|  |  |  |          {'width-normalized': '999px-normalized', offset: 1} | 
					
						
							|  |  |  |        ]); | 
					
						
							|  |  |  |      }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should normalize `*` values', () => { | 
					
						
							|  |  |  |     const driver = new SuperMockDriver(); | 
					
						
							|  |  |  |     const engine = makeEngine(getBodyNode(), driver); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const steps = [ | 
					
						
							|  |  |  |       style({width: '*'}), | 
					
						
							|  |  |  |       animate(1000, style({width: '999px'})), | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const player = invokeAnimation(engine, element, steps) as MockAnimationPlayer; | 
					
						
							|  |  |  |     expect(player.keyframes).toEqual([{width: '*star*', offset: 0}, {width: '999px', offset: 1}]); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2017-12-16 14:42:55 -08:00
										 |  |  | })(); | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | function invokeAnimation( | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |     engine: TimelineAnimationEngine, element: any, steps: AnimationMetadata|AnimationMetadata[], | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  |     id: string = 'id') { | 
					
						
							|  |  |  |   engine.register(id, steps); | 
					
						
							|  |  |  |   return engine.create(id, element); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SuffixNormalizer extends AnimationStyleNormalizer { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   constructor(private _suffix: string) { | 
					
						
							|  |  |  |     super(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   normalizePropertyName(propertyName: string, errors: string[]): string { | 
					
						
							|  |  |  |     return propertyName + this._suffix; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   normalizeStyleValue( | 
					
						
							|  |  |  |       userProvidedProperty: string, normalizedProperty: string, value: string|number, | 
					
						
							|  |  |  |       errors: string[]): string { | 
					
						
							|  |  |  |     return value + this._suffix; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SuperMockDriver extends MockAnimationDriver { | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   computeStyle(element: any, prop: string, defaultValue?: string): string { | 
					
						
							|  |  |  |     return '*star*'; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-04-26 10:44:28 -07:00
										 |  |  | } |