| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 
 | <!DOCTYPE html>
<meta charset=utf-8>
<title>Test basic functionality of scroll linked animation.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/web-animations/testcommon.js"></script>
<script src="testcommon.js"></script>
<style>
  .scroller {
    overflow: auto;
    height: 100px;
    width: 100px;
    will-change: transform;
  }
  .contents {
    height: 1000px;
    width: 100%;
  }
</style>
<div id="log"></div>
<script>
'use strict';
promise_test(async t => {
    const animation = createScrollLinkedAnimation(t);
    const scroller = animation.timeline.source;
    // Ensure we have a valid animation frame time before continuing the test.
    // This is so that we can properly determine frame advancement after the
    // style change.
    await waitForNextFrame();
    // Make the scroll timeline inactive.
    scroller.style.overflow = 'visible';
    // Wait for new animation frame which allows the timeline to compute new
    // current time.
    await waitForNextFrame();
    assert_equals(animation.timeline.currentTime, null,
                  'Sanity check the timeline is inactive.');
    // Play the animation when the timeline is inactive.
    animation.play();
    assert_equals(animation.currentTime, null,
                  'The current time is null when the timeline is inactive.');
    assert_equals(animation.startTime, null,
                  'The start time is unresolved while play-pending.');
    await waitForNextFrame();
    assert_true(animation.pending,
                'Animation has play pending task while timeline is inactive.');
    assert_equals(animation.playState, 'running',
                  `State is 'running' in Pending state.`);
}, `Play pending task doesn't run when the timeline is inactive.`);
promise_test(async t => {
    const animation = createScrollLinkedAnimation(t);
    const scroller = animation.timeline.source;
    await waitForNextFrame();
    // Make the scroll timeline inactive.
    scroller.style.overflow = 'visible';
    // Wait for new animation frame which allows the timeline to compute new
    // current time.
    await waitForNextFrame();
    assert_equals(animation.timeline.currentTime, null,
                  'Sanity check the timeline is inactive.');
    // Play the animation when the timeline is inactive.
    animation.play();
    // Make the scroll timeline active.
    scroller.style.overflow = 'auto';
    await animation.ready;
    // Ready promise is resolved as a result of the timeline becoming active.
    assert_percents_equal(animation.currentTime, 0,
        'Animation current time is resolved when the animation is ready.');
    assert_percents_equal(animation.startTime, 0,
        'Animation start time is resolved when the animation is ready.');
}, 'Animation start and current times are correct if scroll timeline is ' +
   'activated after animation.play call.');
promise_test(async t => {
    const animation = createScrollLinkedAnimation(t);
    const scroller = animation.timeline.source;
    const target = animation.effect.target;
    await waitForNextFrame();
    // Make the scroll timeline inactive.
    scroller.style.overflow = 'visible';
    scroller.scrollTop;
    // Wait for new animation frame which allows the timeline to compute new
    // current time.
    await waitForNextFrame();
    assert_equals(animation.timeline.currentTime, null,
                  'Sanity check the timeline is inactive.');
    // Set start time when the timeline is inactive.
    animation.startTime = CSSNumericValue.parse("0%");
    assert_equals(animation.currentTime, null,
                  'Sanity check current time is unresolved when the timeline ' +
                  'is inactive.');
    // Make the scroll timeline active.
    scroller.style.overflow = 'auto';
    // Wait for new animation frame which allows the timeline to compute new
    // current time.
    await waitForNextFrame();
    assert_percents_equal(animation.currentTime, 0,
        'Animation current time is resolved when the timeline is active.');
    assert_percents_equal(animation.startTime, 0,
                          'Animation start time is resolved.');
    assert_percents_equal(animation.effect.getComputedTiming().localTime, 0,
        'Effect local time is resolved when the timeline is active.');
    assert_equals(Number(getComputedStyle(target).opacity), 0,
        'Animation has an effect when the timeline is active.');
}, 'Animation start and current times are correct if scroll timeline is ' +
   'activated after setting start time.');
promise_test(async t => {
    const animation = createScrollLinkedAnimation(t);
    const scroller = animation.timeline.source;
    const maxScroll = scroller.scrollHeight - scroller.clientHeight;
    const target = animation.effect.target;
    await waitForNextFrame();
    // Advance the scroller.
    scroller.scrollTop = 0.2 * maxScroll;
    // Wait for new animation frame which allows the timeline to compute new
    // current time.
    await waitForNextFrame();
    // Play the animation when the timeline is active.
    animation.play();
    await animation.ready;
    // Make the scroll timeline inactive.
    scroller.style.overflow = 'visible';
    scroller.scrollTop;
    await waitForNextFrame();
    assert_equals(animation.timeline.currentTime, null,
                  'Sanity check the timeline is inactive.');
    assert_equals(animation.playState, 'running',
                  `State is 'running' when the timeline is inactive.`);
    assert_equals(animation.currentTime, null,
                  'Current time is unresolved when the timeline is inactive.');
    assert_percents_equal(animation.startTime, 0,
                          'Start time is zero when the timeline is inactive.');
    assert_equals(animation.effect.getComputedTiming().localTime, null,
                  'Effect local time is null when the timeline is inactive.');
    assert_equals(Number(getComputedStyle(target).opacity), 1,
        'Animation does not have an effect when the timeline is inactive.');
    // Make the scroll timeline active.
    scroller.style.overflow = 'auto';
    await waitForNextFrame();
    assert_equals(animation.playState, 'running',
                  `State is 'running' when the timeline is active.`);
    assert_percents_equal(animation.currentTime, 20,
        'Current time is resolved when the timeline is active.');
    assert_percents_equal(animation.startTime, 0,
                          'Start time is zero when the timeline is active.');
    assert_percents_equal(animation.effect.getComputedTiming().localTime, 20,
        'Effect local time is resolved when the timeline is active.');
    assert_equals(Number(getComputedStyle(target).opacity), 0.2,
        'Animation has an effect when the timeline is active.');
}, 'Animation current time is correct when the timeline becomes newly ' +
   'inactive and then active again.');
</script>
 |