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*'; }
 | 
						|
}
 |