// 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 { assert } from 'chai';
import sinon from 'sinon';
import { setupLocaleHooks } from '../../testing/LocaleHelpers.js';
import { MockCDPConnection } from '../../testing/MockCDPConnection.js';
import { setupRuntimeHooks } from '../../testing/RuntimeHelpers.js';
import { setupSettingsHooks } from '../../testing/SettingsHelpers.js';
import { TestUniverse } from '../../testing/TestUniverse.js';
import * as SDK from './sdk.js';
function createAnimationPayload(payload) {
    return {
        id: '1',
        name: 'animation-name',
        pausedState: false,
        playbackRate: 1,
        startTime: 0,
        currentTime: 0,
        type: "CSSAnimation" /* Protocol.Animation.AnimationType.CSSAnimation */,
        playState: 'running',
        ...payload,
        source: {
            backendNodeId: 1,
            delay: 0,
            endDelay: 0,
            iterationStart: 0,
            iterations: 1,
            duration: 100,
            direction: 'forward',
            fill: 'forwards',
            easing: 'linear',
            ...(payload.source ? payload.source : null),
        },
    };
}
describe('AnimationModel', () => {
    setupLocaleHooks();
    setupSettingsHooks();
    setupRuntimeHooks();
    let universe;
    beforeEach(() => {
        universe = new TestUniverse();
    });
    it('can be instantiated', () => {
        assert.doesNotThrow(() => {
            const target = universe.createTarget();
            new SDK.AnimationModel.AnimationModel(target);
        });
    });
    describe('getAnimationGroupForAnimation', () => {
        const NODE_ID = 1;
        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 = universe.createTarget();
            const model = new SDK.AnimationModel.AnimationModel(target);
            const animationGroupStartedPromiseWithResolvers = Promise.withResolvers();
            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 = universe.createTarget();
            const model = new SDK.AnimationModel.AnimationModel(target);
            const animationGroupStartedPromiseWithResolvers = Promise.withResolvers();
            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 = universe.createTarget();
            const model = new SDK.AnimationModel.AnimationModel(target);
            const animationGroupStartedPromiseWithResolvers = Promise.withResolvers();
            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);
            assert.isNull(receivedAnimationGroup);
        });
    });
    describe('AnimationImpl', () => {
        it('setPayload should update values returned from the relevant value functions for time based animations', async () => {
            const target = universe.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: "CSSAnimation" /* 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(), "CSSAnimation" /* Protocol.Animation.AnimationType.CSSAnimation */);
            await animationImpl.setPayload({
                id: '1',
                name: 'updated-name',
                pausedState: true,
                playbackRate: 2,
                startTime: 100,
                currentTime: 120,
                type: "CSSTransition" /* 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(), "CSSTransition" /* Protocol.Animation.AnimationType.CSSTransition */);
        });
        it('setPayload should update values returned from the relevant value functions for scroll based animations', async () => {
            const connection = new MockCDPConnection();
            connection.setSuccessHandler('Runtime.evaluate', () => ({
                result: {
                    type: "number" /* Protocol.Runtime.RemoteObjectType.Number */,
                    value: 1,
                },
            }));
            const target = universe.createTarget({ connection });
            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: "CSSAnimation" /* 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: "vertical" /* Protocol.DOM.ScrollOrientation.Vertical */,
                    startOffset: 100,
                    endOffset: 200,
                    sourceNodeId: 1,
                },
            });
            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: "CSSAnimation" /* 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: "horizontal" /* Protocol.DOM.ScrollOrientation.Horizontal */,
                    startOffset: 0,
                    endOffset: 100,
                    sourceNodeId: 1,
                },
            });
            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
        });
    });
});
//# sourceMappingURL=AnimationModel.test.js.map