124 lines
4.2 KiB
TypeScript
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*'; }
|
|
}
|