blob: b7ad517113e731e8f469d9a4a1128f54fd95bbc1 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as Protocol from '../../generated/protocol.js';
import {createTarget} from '../../testing/EnvironmentHelpers.js';
import {
clearAllMockConnectionResponseHandlers,
describeWithMockConnection,
setMockConnectionResponseHandler,
} from '../../testing/MockConnection.js';
import * as SDK from './sdk.js';
function createAnimationPayload(payload: Partial<Protocol.Animation.Animation>): Protocol.Animation.Animation {
return {
id: '1',
name: 'animation-name',
pausedState: false,
playbackRate: 1,
startTime: 0,
currentTime: 0,
type: Protocol.Animation.AnimationType.CSSAnimation,
playState: 'running',
...payload,
source: {
backendNodeId: 1 as Protocol.DOM.BackendNodeId,
delay: 0,
endDelay: 0,
iterationStart: 0,
iterations: 1,
duration: 100,
direction: 'forward',
fill: 'forwards',
easing: 'linear',
...(payload.source ? payload.source : null),
},
};
}
describeWithMockConnection('AnimationModel', () => {
afterEach(() => {
clearAllMockConnectionResponseHandlers();
});
it('can be instantiated', () => {
assert.doesNotThrow(() => {
const target = createTarget();
new SDK.AnimationModel.AnimationModel(target);
});
});
describe('getAnimationGroupForAnimation', () => {
const NODE_ID = 1 as Protocol.DOM.NodeId;
beforeEach(() => {
const stubDOMNode = sinon.createStubInstance(SDK.DOMModel.DOMNode);
stubDOMNode.id = NODE_ID;
sinon.stub(SDK.AnimationModel.AnimationEffect.prototype, 'node').resolves(stubDOMNode);
});
it('should resolve the containing animation group if the animation with given name and node id exists in the group',
async () => {
const target = createTarget();
const model = new SDK.AnimationModel.AnimationModel(target);
const animationGroupStartedPromiseWithResolvers = Promise.withResolvers<void>();
model.addEventListener(SDK.AnimationModel.Events.AnimationGroupStarted, () => {
animationGroupStartedPromiseWithResolvers.resolve();
});
void model.animationStarted(createAnimationPayload({name: 'animation-name'}));
await animationGroupStartedPromiseWithResolvers.promise;
const receivedAnimationGroup = await model.getAnimationGroupForAnimation('animation-name', NODE_ID);
assert.isNotNull(receivedAnimationGroup);
});
it('should resolve null if there is no animations with matching name', async () => {
const target = createTarget();
const model = new SDK.AnimationModel.AnimationModel(target);
const animationGroupStartedPromiseWithResolvers = Promise.withResolvers<void>();
model.addEventListener(SDK.AnimationModel.Events.AnimationGroupStarted, () => {
animationGroupStartedPromiseWithResolvers.resolve();
});
void model.animationStarted(createAnimationPayload({name: 'animation-name'}));
await animationGroupStartedPromiseWithResolvers.promise;
const receivedAnimationGroup = await model.getAnimationGroupForAnimation('not-a-matching-name', NODE_ID);
assert.isNull(receivedAnimationGroup);
});
it('should resolve null if there is an animation with the same name but for a different node id', async () => {
const target = createTarget();
const model = new SDK.AnimationModel.AnimationModel(target);
const animationGroupStartedPromiseWithResolvers = Promise.withResolvers<void>();
model.addEventListener(SDK.AnimationModel.Events.AnimationGroupStarted, () => {
animationGroupStartedPromiseWithResolvers.resolve();
});
void model.animationStarted(createAnimationPayload({name: 'animation-name'}));
await animationGroupStartedPromiseWithResolvers.promise;
const receivedAnimationGroup =
await model.getAnimationGroupForAnimation('animation-name', 9999 as Protocol.DOM.NodeId);
assert.isNull(receivedAnimationGroup);
});
});
describe('AnimationImpl', () => {
it('setPayload should update values returned from the relevant value functions for time based animations',
async () => {
const target = createTarget();
const model = new SDK.AnimationModel.AnimationModel(target);
const animationImpl = await SDK.AnimationModel.AnimationImpl.parsePayload(model, {
id: '1',
name: 'animation-name',
pausedState: false,
playbackRate: 1,
startTime: 0,
currentTime: 0,
type: Protocol.Animation.AnimationType.CSSAnimation,
playState: 'running',
source: {
delay: 0,
endDelay: 0,
iterationStart: 0,
iterations: 1,
duration: 100,
direction: 'forward',
fill: 'forwards',
easing: 'linear',
},
});
assert.strictEqual(animationImpl.name(), 'animation-name');
assert.isFalse(animationImpl.paused());
assert.strictEqual(animationImpl.playState(), 'running');
assert.strictEqual(animationImpl.playbackRate(), 1);
assert.strictEqual(animationImpl.startTime(), 0);
assert.strictEqual(animationImpl.currentTime(), 0);
assert.strictEqual(animationImpl.iterationDuration(), 100);
assert.strictEqual(animationImpl.delayOrStartTime(), 0);
assert.strictEqual(animationImpl.type(), Protocol.Animation.AnimationType.CSSAnimation);
await animationImpl.setPayload({
id: '1',
name: 'updated-name',
pausedState: true,
playbackRate: 2,
startTime: 100,
currentTime: 120,
type: Protocol.Animation.AnimationType.CSSTransition,
playState: 'paused',
source: {
delay: 10,
endDelay: 10,
iterationStart: 20,
iterations: 2,
duration: 120,
direction: 'reverse',
fill: 'backward',
easing: 'ease',
},
});
assert.strictEqual(animationImpl.name(), 'updated-name');
assert.isTrue(animationImpl.paused());
assert.strictEqual(animationImpl.playState(), 'paused');
assert.strictEqual(animationImpl.playbackRate(), 2);
assert.strictEqual(animationImpl.startTime(), 100);
assert.strictEqual(animationImpl.currentTime(), 120);
assert.strictEqual(animationImpl.iterationDuration(), 120);
assert.strictEqual(animationImpl.delayOrStartTime(), 10);
assert.strictEqual(animationImpl.type(), Protocol.Animation.AnimationType.CSSTransition);
});
it('setPayload should update values returned from the relevant value functions for scroll based animations',
async () => {
setMockConnectionResponseHandler('Runtime.evaluate', () => {
return {
result: {
type: 'number',
value: 1,
},
} as Protocol.Runtime.EvaluateResponse;
});
const target = createTarget();
const model = new SDK.AnimationModel.AnimationModel(target);
const animationImpl = await SDK.AnimationModel.AnimationImpl.parsePayload(model, {
id: '1',
name: 'animation-name',
pausedState: false,
playbackRate: 1,
startTime: 0,
currentTime: 0,
type: Protocol.Animation.AnimationType.CSSAnimation,
playState: 'running',
source: {
delay: 0,
endDelay: 0,
iterationStart: 0,
iterations: 1,
duration: 100,
direction: 'forward',
fill: 'forwards',
easing: 'linear',
},
viewOrScrollTimeline: {
axis: Protocol.DOM.ScrollOrientation.Vertical,
startOffset: 100,
endOffset: 200,
sourceNodeId: 1 as Protocol.DOM.BackendNodeId,
},
});
assert.strictEqual(animationImpl.name(), 'animation-name');
assert.isFalse(animationImpl.paused());
assert.strictEqual(animationImpl.playState(), 'running');
assert.strictEqual(animationImpl.playbackRate(), 1);
assert.strictEqual(animationImpl.startTime(), 100); // in pixels
assert.strictEqual(animationImpl.currentTime(), 0);
assert.strictEqual(animationImpl.iterationDuration(), 100); // in pixels
assert.strictEqual(animationImpl.delayOrStartTime(), 100); // in pixels
await animationImpl.setPayload({
id: '1',
name: 'updated-name',
pausedState: true,
playbackRate: 2,
startTime: 0,
currentTime: 120,
type: Protocol.Animation.AnimationType.CSSAnimation,
playState: 'paused',
source: {
delay: 10,
endDelay: 10,
iterationStart: 20,
iterations: 2,
duration: 20,
direction: 'reverse',
fill: 'backward',
easing: 'ease',
},
viewOrScrollTimeline: {
axis: Protocol.DOM.ScrollOrientation.Horizontal,
startOffset: 0,
endOffset: 100,
sourceNodeId: 1 as Protocol.DOM.BackendNodeId,
},
});
assert.strictEqual(animationImpl.name(), 'updated-name');
assert.isTrue(animationImpl.paused());
assert.strictEqual(animationImpl.playState(), 'paused');
assert.strictEqual(animationImpl.playbackRate(), 2);
assert.strictEqual(animationImpl.startTime(), 0); // in pixels
assert.strictEqual(animationImpl.currentTime(), 120); // in pixels
assert.strictEqual(animationImpl.iterationDuration(), 20); // in pixels
assert.strictEqual(animationImpl.delayOrStartTime(), 0); // in pixels
});
});
});