angular-cn/packages/animations/browser/test/render/timeline_animation_engine_s...

124 lines
4.2 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 {getBodyNode} from '../../src/render/shared';
import {TimelineAnimationEngine} from '../../src/render/timeline_animation_engine';
import {MockAnimationDriver, MockAnimationPlayer} from '../../testing/src/mock_animation_driver';
(function() {
const defaultDriver = new MockAnimationDriver();
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);
});
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']);
});
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}]);
});
});
})();
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*'; }
}