<!DOCTYPE html>
<meta charset="utf-8">
<title>Reversal of accelerated in-flight CSS Transitions</title>
<style type="text/css" media="screen">

.target.opacity {
    transition: opacity 2s linear;
}

.target.opacity.in-flight {
    opacity: 0;
}

.target.transform {
    transition: transform 2s linear;
}

.target.transform.in-flight {
    transform: scale(0);
}

</style>
<body>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>

'use strict';

function targetTest(propertyName)
{
    promise_test(async() => {
        return new Promise(resolve => {
            const target = document.body.appendChild(document.createElement("div"));
            target.classList.add("target");
            target.classList.add(propertyName);

            let initialTransition;
            let reversedTransition;

            // Start the initial transition.
            requestAnimationFrame(() => {
                target.classList.add("in-flight");
                const animations = target.getAnimations();
                assert_equals(animations.length, 1, "There is one animation applied to the target after starting the initial transition.");

                initialTransition = animations[0];
                assert_true(initialTransition instanceof CSSTransition, "There is one animation applied to the target after starting the initial transition.");

                // Wait for the initial transition to start and then two frames before reversing the transition, to be certain that the animation did start.
                // Indeed, the "transitionstart" event will be fired right before the next rAF callback is called, as the animation starts in that very same
                // frame, and so progress will be 0 and the transition wouldn't be reversable until the next frame when the animation has progress > 0.
                target.addEventListener("transitionstart", event => {
                    requestAnimationFrame(() => {
                        requestAnimationFrame(() => {
                            target.classList.remove("in-flight");
                            const animations = target.getAnimations();
                            assert_equals(animations.length, 1, "There is one animation applied to the target after reversing the initial transition.");

                            reversedTransition = animations[0];
                            assert_true(reversedTransition instanceof CSSTransition, "There is one animation applied to the target after reversing the initial transition.");
                            assert_not_equals(initialTransition, reversedTransition, "The animation applied to the target after reversing the initial transition is different than the original transition.");

                            target.remove();
                            resolve();
                        });
                    });
                });
            });
        });
    }, `A CSS transition targeting ${propertyName} can be reversed in-flight.`);
}

targetTest("opacity");
targetTest("transform");

</script>
</body>