tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CSSAnimation-effect.tentative.html (7490B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>CSSAnimation.effect</title>
      4 <meta name="timeout" content="long">
      5 <!-- TODO: Add a more specific link for this once it is specified. -->
      6 <link rel="help" href="https://drafts.csswg.org/css-animations-2/#cssanimation">
      7 <script src="/resources/testharness.js"></script>
      8 <script src="/resources/testharnessreport.js"></script>
      9 <script src="support/testcommon.js"></script>
     10 <style>
     11 @keyframes anim {
     12  from {
     13    margin-left: 0px;
     14  }
     15  to {
     16    margin-left: 100px;
     17  }
     18 }
     19 </style>
     20 <div id="log"></div>
     21 <script>
     22 'use strict';
     23 
     24 promise_test(async t => {
     25  const div = addDiv(t);
     26  div.style.animation = 'anim 100s';
     27 
     28  const watcher = new EventWatcher(t, div, [ 'animationend',
     29                                             'animationcancel' ],
     30                                   fastEventsTimeout);
     31  const animation = div.getAnimations()[0];
     32  await animation.ready;
     33 
     34  animation.currentTime = 50 * MS_PER_SEC;
     35  animation.effect = null;
     36  assert_equals(animation.playState, 'finished');
     37  assert_equals(getComputedStyle(div).marginLeft, '0px');
     38  await watcher.wait_for('animationend');
     39 }, 'Setting a null effect on a running animation fires an animationend event');
     40 
     41 promise_test(async t => {
     42  const div = addDiv(t);
     43  div.style.animation = 'anim 100s';
     44 
     45  const animation = div.getAnimations()[0];
     46  await animation.ready;
     47 
     48  animation.currentTime = 50 * MS_PER_SEC;
     49  animation.effect = new KeyframeEffect(div,
     50                                        { left: [ '0px' , '100px'] },
     51                                        100 * MS_PER_SEC);
     52  assert_equals(getComputedStyle(div).marginLeft, '0px');
     53  assert_equals(getComputedStyle(div).left, '50px');
     54 }, 'Replacing an animation\'s effect with an effect that targets a different ' +
     55   'property should update both properties');
     56 
     57 promise_test(async t => {
     58  const div = addDiv(t);
     59  div.style.animation = 'anim 100s';
     60 
     61  const animation = div.getAnimations()[0];
     62  await animation.ready;
     63 
     64  animation.currentTime = 50 * MS_PER_SEC;
     65  animation.effect = new KeyframeEffect(div,
     66                                        { left: [ '0px' , '100px'] },
     67                                        20 * MS_PER_SEC);
     68  assert_equals(animation.playState, 'finished');
     69 }, 'Replacing an animation\'s effect with a shorter one that should have ' +
     70   'already finished, the animation finishes immediately');
     71 
     72 promise_test(async t => {
     73  const div = addDiv(t);
     74  div.style.animation = 'anim 100s';
     75 
     76  const animation = div.getAnimations()[0];
     77  assert_true(animation.pending);
     78 
     79  animation.effect = new KeyframeEffect(div,
     80                                        { left: [ '0px' , '100px'] },
     81                                        100 * MS_PER_SEC);
     82  assert_true(animation.pending);
     83 
     84  await animation.ready;
     85 
     86  assert_false(animation.pending);
     87 }, 'A play-pending animation\'s effect whose effect is replaced still exits ' +
     88   'the pending state');
     89 
     90 promise_test(async t => {
     91  const div1 = addDiv(t);
     92  const div2 = addDiv(t);
     93 
     94  const watcher1 = new EventWatcher(t, div1, 'animationstart',
     95                                    fastEventsTimeout);
     96  // Watch |div2| as well to ensure it does *not* get events.
     97  const watcher2 = new EventWatcher(t, div2, 'animationstart');
     98 
     99  div1.style.animation = 'anim 100s';
    100 
    101  const animation = div1.getAnimations()[0];
    102  animation.effect = new KeyframeEffect(div2,
    103                                        { left: [ '0px', '100px' ] },
    104                                        100 * MS_PER_SEC);
    105 
    106  await watcher1.wait_for('animationstart');
    107 
    108  assert_equals(animation.effect.target, div2);
    109 
    110  // Then wait a couple of frames and check that no event was dispatched.
    111  await waitForAnimationFrames(2);
    112 }, 'CSS animation events are dispatched at the original element even after'
    113   + ' setting an effect with a different target element');
    114 
    115 promise_test(async t => {
    116  const div = addDiv(t);
    117  const watcher = new EventWatcher(t, div, [ 'animationstart',
    118                                             'animationend',
    119                                             'animationcancel' ],
    120                                   fastEventsTimeout);
    121  div.style.animation = 'anim 100s';
    122  const animation = div.getAnimations()[0];
    123  animation.finish();
    124 
    125  await watcher.wait_for([ 'animationstart', 'animationend' ]);
    126  // Set a longer effect
    127  animation.effect = new KeyframeEffect(div,
    128                                        { left: [ '0px', '100px' ] },
    129                                        200 * MS_PER_SEC);
    130  await watcher.wait_for('animationstart');
    131 }, 'After replacing a finished animation\'s effect with a longer one ' +
    132   'it fires an animationstart event');
    133 
    134 test(t => {
    135  const div = addDiv(t);
    136  div.style.animation = 'anim 100s';
    137  div.style.animationComposition = 'add';
    138  const animation = div.getAnimations()[0];
    139  assert_equals(animation.effect.composite, 'add');
    140 }, 'Setting animation-composition sets the composite property on the effect');
    141 
    142 test(t => {
    143  const div = addDiv(t);
    144 
    145  // Create custom keyframes so we can tweak them
    146  const stylesheet = document.styleSheets[0];
    147  const keyframes = '@keyframes anim-custom { to { left: 100px } }';
    148  const ruleIndex = stylesheet.insertRule(keyframes, 0);
    149  const keyframesRule = stylesheet.cssRules[ruleIndex];
    150 
    151  t.add_cleanup(function() {
    152    stylesheet.deleteRule(ruleIndex);
    153  });
    154 
    155  div.style.animation = 'anim-custom 100s';
    156 
    157  // Replace the effect
    158  const animation = div.getAnimations()[0];
    159  animation.effect = new KeyframeEffect(
    160    div,
    161    { left: '200px' },
    162    200 * MS_PER_SEC
    163  );
    164 
    165  // Update the timing properties
    166  div.style.animationDuration = '4s';
    167  div.style.animationIterationCount = '6';
    168  div.style.animationDirection = 'reverse';
    169  div.style.animationDelay = '8s';
    170  div.style.animationFillMode = 'both';
    171  div.style.animationPlayState = 'paused';
    172  div.style.animationComposition = 'add';
    173  div.style.animationTimeline = 'none';
    174 
    175  // Update the keyframes
    176  keyframesRule.deleteRule(0);
    177  keyframesRule.appendRule('to { left: 300px }');
    178 
    179  // Check nothing (except the play state) changed
    180  assert_equals(
    181    animation.effect.getTiming().duration,
    182    200 * MS_PER_SEC,
    183    'duration should be the value set by the API'
    184  );
    185  assert_equals(
    186    animation.effect.getTiming().iterations,
    187    1,
    188    'iterations should be the value set by the API'
    189  );
    190  assert_equals(
    191    animation.effect.getTiming().direction,
    192    'normal',
    193    'direction should be the value set by the API'
    194  );
    195  assert_equals(
    196    animation.effect.getTiming().delay,
    197    0,
    198    'delay should be the value set by the API'
    199  );
    200  assert_equals(
    201    animation.effect.getTiming().fill,
    202    'auto',
    203    'fill should be the value set by the API'
    204  );
    205  assert_equals(
    206    animation.effect.getKeyframes()[0].left,
    207    '200px',
    208    'keyframes should be the value set by the API'
    209  );
    210  assert_equals(
    211    animation.effect.composite,
    212    'replace',
    213    'composite should be the value set by the API'
    214  );
    215 
    216  // Unlike the other properties animation-play-state and animation-timeline map
    217  // to the Animation, not the KeyframeEffect, so they should be overridden.
    218  assert_equals(
    219    animation.playState,
    220    'paused',
    221    'play state should be the value set by style'
    222  );
    223  assert_equals(
    224    animation.timeline,
    225    null,
    226    'timeline should be the value set by style'
    227  );
    228 }, 'Replacing the effect of a CSSAnimation causes subsequent changes to'
    229   + ' corresponding animation-* properties to be ignored');
    230 
    231 </script>