122 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			122 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @license
							 | 
						||
| 
								 | 
							
								 * Copyright Google Inc. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * 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 {AnimationMetadata, animate, style} from '@angular/animations';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import {AnimationStyleNormalizer, NoopAnimationStyleNormalizer} from '../../src/dsl/style_normalization/animation_style_normalizer';
							 | 
						||
| 
								 | 
							
								import {AnimationDriver} from '../../src/render/animation_driver';
							 | 
						||
| 
								 | 
							
								import {TimelineAnimationEngine} from '../../src/render/timeline_animation_engine';
							 | 
						||
| 
								 | 
							
								import {MockAnimationDriver, MockAnimationPlayer} from '../../testing/src/mock_animation_driver';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function main() {
							 | 
						||
| 
								 | 
							
								  const defaultDriver = new MockAnimationDriver();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function makeEngine(driver?: AnimationDriver, normalizer?: AnimationStyleNormalizer) {
							 | 
						||
| 
								 | 
							
								    return new TimelineAnimationEngine(
							 | 
						||
| 
								 | 
							
								        driver || defaultDriver, normalizer || new NoopAnimationStyleNormalizer());
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // these tests are only mean't to be run within the DOM
							 | 
						||
| 
								 | 
							
								  if (typeof Element == 'undefined') 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();
							 | 
						||
| 
								 | 
							
								      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);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    it('should not destroy timeline-based animations after they have finished', () => {
							 | 
						||
| 
								 | 
							
								      const engine = makeEngine();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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']);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    it('should normalize the style values that are animateTransitioned within an a timeline animation',
							 | 
						||
| 
								 | 
							
								       () => {
							 | 
						||
| 
								 | 
							
								         const engine = makeEngine(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(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}]);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function invokeAnimation(
							 | 
						||
| 
								 | 
							
								    engine: TimelineAnimationEngine, element: any, steps: AnimationMetadata | AnimationMetadata[],
							 | 
						||
| 
								 | 
							
								    id: string = 'id') {
							 | 
						||
| 
								 | 
							
								  engine.register(id, steps);
							 | 
						||
| 
								 | 
							
								  return engine.create(id, element);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SuffixNormalizer extends AnimationStyleNormalizer {
							 | 
						||
| 
								 | 
							
								  constructor(private _suffix: string) { super(); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  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 {
							 | 
						||
| 
								 | 
							
								  computeStyle(element: any, prop: string, defaultValue?: string): string { return '*star*'; }
							 | 
						||
| 
								 | 
							
								}
							 |