From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- testing/web-platform/tests/web-animations/META.yml | 5 + .../web-platform/tests/web-animations/README.md | 116 + .../tests/web-animations/WEB_FEATURES.yml | 3 + .../accumulation-per-property-001.html | 24 + .../accumulation-per-property-002.html | 24 + .../animation-types/addition-per-property-001.html | 24 + .../animation-types/addition-per-property-002.html | 24 + .../animation-model/animation-types/discrete.html | 135 + .../animation-types/display.tentative.html | 34 + .../interpolation-per-property-001.html | 24 + .../interpolation-per-property-002.html | 24 + .../animation-types/property-list.js | 1618 +++++++++++ .../animation-types/property-types.js | 2936 ++++++++++++++++++++ .../animation-types/property-utils.js | 38 + .../animation-types/scrollbar-interpolation.html | 91 + .../animation-types/visibility.html | 57 + .../applying-interpolated-transform.html | 87 + .../applying-the-composited-result.html | 29 + .../combining-effects/effect-composition.html | 154 + .../computed-keyframes-shorthands.html | 30 + .../effect-in-removed-iframe-crash.html | 22 + .../effect-on-marquee-parent-crash.html | 21 + .../effect-value-context-filling.html | 377 +++ .../keyframe-effects/effect-value-context.html | 105 + .../effect-value-interval-distance.html | 36 + ...effect-value-iteration-composite-operation.html | 824 ++++++ ...opacity-replaced-effect-in-shadow-root-ref.html | 9 + ...lue-opacity-replaced-effect-in-shadow-root.html | 26 + .../effect-value-opacity-replaced-effect-ref.html | 9 + .../effect-value-opacity-replaced-effect.html | 32 + .../effect-value-overlapping-keyframes.html | 77 + .../effect-value-replaced-animations.html | 161 ++ .../effect-value-transformed-distance.html | 84 + .../keyframe-effects/keyframe-exceptions.html | 39 + .../transform-and-opacity-on-inline-001-ref.html | 14 + .../transform-and-opacity-on-inline-001.html | 27 + .../resources/side-effects-common.js | 81 + .../side-effects-of-animations-current-ref.html | 109 + .../side-effects-of-animations-current.html | 174 ++ .../side-effects-of-animations-in-effect-ref.html | 109 + .../side-effects-of-animations-in-effect.html | 174 ++ .../side-effects-of-animations-none-ref.html | 48 + .../side-effects-of-animations-none.html | 79 + .../crashtests/color-mix-crashtest.html | 35 + .../crashtests/get-computed-timing-crash.html | 20 + .../crashtests/infinite-active-duration.html | 68 + ...overlapping-animations-one-not-current-001.html | 17 + .../crashtests/reparent-animating-element-001.html | 40 + .../crashtests/reparent-animating-element-002.html | 44 + .../tests/web-animations/idlharness.window.js | 21 + .../Animatable/animate-no-browsing-context.html | 107 + .../interfaces/Animatable/animate.html | 363 +++ .../Animatable/getAnimations-iframe.html | 51 + .../interfaces/Animatable/getAnimations.html | 355 +++ .../interfaces/Animation/cancel.html | 133 + .../interfaces/Animation/commitStyles-crash.html | 26 + .../Animation/commitStyles-svg-crash.html | 12 + .../interfaces/Animation/commitStyles.html | 577 ++++ .../interfaces/Animation/constructor.html | 124 + .../interfaces/Animation/effect.html | 42 + .../interfaces/Animation/finished.html | 416 +++ .../web-animations/interfaces/Animation/id.html | 28 + .../interfaces/Animation/oncancel.html | 33 + .../interfaces/Animation/onfinish.html | 119 + .../interfaces/Animation/onremove.html | 58 + .../web-animations/interfaces/Animation/pause.html | 98 + .../interfaces/Animation/pending.html | 55 + .../interfaces/Animation/persist.html | 40 + .../web-animations/interfaces/Animation/play.html | 34 + .../web-animations/interfaces/Animation/ready.html | 78 + .../interfaces/Animation/startTime.html | 55 + .../interfaces/Animation/style-change-events.html | 376 +++ .../AnimationEffect/getComputedTiming.html | 214 ++ .../interfaces/AnimationEffect/updateTiming.html | 475 ++++ .../AnimationPlaybackEvent/constructor.html | 30 + .../interfaces/Document/timeline.html | 23 + .../DocumentOrShadowRoot/getAnimations.html | 234 ++ .../interfaces/DocumentTimeline/constructor.html | 43 + .../DocumentTimeline/style-change-events.html | 92 + .../interfaces/KeyframeEffect/composite.html | 47 + .../interfaces/KeyframeEffect/constructor.html | 195 ++ .../KeyframeEffect/copy-constructor.html | 93 + .../interfaces/KeyframeEffect/getKeyframes.html | 25 + .../KeyframeEffect/iterationComposite.html | 36 + .../processing-a-keyframes-argument-001.html | 602 ++++ .../processing-a-keyframes-argument-002.html | 125 + .../interfaces/KeyframeEffect/setKeyframes.html | 55 + .../KeyframeEffect/style-change-events.html | 242 ++ .../interfaces/KeyframeEffect/target.html | 271 ++ .../tests/web-animations/resources/easing-tests.js | 121 + .../tests/web-animations/resources/effect-tests.js | 75 + .../web-animations/resources/keyframe-tests.js | 827 ++++++ .../web-animations/resources/keyframe-utils.js | 51 + .../web-animations/resources/timing-override.js | 18 + .../tests/web-animations/resources/timing-tests.js | 46 + .../tests/web-animations/resources/timing-utils.js | 52 + .../tests/web-animations/resources/xhr-doc.py | 5 + .../responsive/assorted-lengths.html | 102 + .../responsive/backgroundPosition.html | 25 + .../web-animations/responsive/backgroundSize.html | 22 + .../web-animations/responsive/baselineShift.html | 43 + .../responsive/borderImageWidth.html | 22 + .../web-animations/responsive/borderRadius.html | 39 + .../web-animations/responsive/borderWidth.html | 33 + .../tests/web-animations/responsive/boxShadow.html | 30 + .../tests/web-animations/responsive/clip.html | 45 + .../web-animations/responsive/columnCount.html | 32 + .../tests/web-animations/responsive/columnGap.html | 49 + .../tests/web-animations/responsive/d.html | 27 + .../responsive/font-size-adjust.html | 32 + .../tests/web-animations/responsive/fontSize.html | 72 + .../web-animations/responsive/fontWeight.html | 42 + .../web-animations/responsive/lineHeight.html | 80 + .../tests/web-animations/responsive/minHeight.html | 35 + .../web-animations/responsive/offset-path.html | 27 + .../web-animations/responsive/offsetDistance.html | 57 + .../web-animations/responsive/offsetRotate.html | 43 + .../tests/web-animations/responsive/opacity.html | 48 + .../web-animations/responsive/perspective.html | 49 + .../web-animations/responsive/resources/block.html | 10 + .../tests/web-animations/responsive/rotate.html | 22 + .../tests/web-animations/responsive/rowGap.html | 49 + .../web-animations/responsive/shapeMargin.html | 24 + .../web-animations/responsive/shapeOutside.html | 59 + .../web-animations/responsive/strokeDasharray.html | 28 + .../responsive/text-size-adjust.html | 29 + .../web-animations/responsive/textIndent.html | 59 + .../web-animations/responsive/to-color-change.html | 253 ++ .../responsive/to-inherited-change.html | 56 + .../web-animations/responsive/to-style-change.html | 44 + .../toggle-animated-iframe-visibility-ref.html | 10 + .../toggle-animated-iframe-visibility.html | 55 + .../tests/web-animations/responsive/transform.html | 22 + .../tests/web-animations/responsive/translate.html | 22 + .../web-animations/responsive/verticalAlign.html | 22 + .../tests/web-animations/testcommon.js | 342 +++ .../animation-effects/active-time.html | 141 + .../animation-effects/current-iteration.html | 620 +++++ .../timing-model/animation-effects/local-time.html | 29 + .../animation-effects/phases-and-states.html | 149 + .../simple-iteration-progress.html | 600 ++++ .../animations/canceling-an-animation.html | 127 + .../document-timeline-animation-ref.html | 19 + .../animations/document-timeline-animation.html | 63 + .../animations/finishing-an-animation.html | 330 +++ .../infinite-duration-animation-ref.html | 19 + .../animations/infinite-duration-animation.html | 64 + ...idating-animation-before-start-time-synced.html | 71 + .../animations/pausing-an-animation.html | 119 + .../timing-model/animations/play-states.html | 185 ++ .../animations/playing-an-animation.html | 177 ++ .../animations/reverse-running-animation-ref.html | 17 + .../animations/reverse-running-animation.html | 50 + .../animations/reversing-an-animation.html | 266 ++ ...updating-the-playback-rate-of-an-animation.html | 171 ++ .../setting-the-current-time-of-an-animation.html | 167 ++ .../setting-the-playback-rate-of-an-animation.html | 110 + .../setting-the-start-time-of-an-animation.html | 329 +++ .../setting-the-target-effect-of-an-animation.html | 129 + .../setting-the-timeline-of-an-animation.html | 255 ++ .../animations/sync-start-times-ref.html | 20 + .../timing-model/animations/sync-start-times.html | 72 + .../the-current-time-of-an-animation.html | 75 + .../animations/update-playback-rate-fast-ref.html | 17 + .../animations/update-playback-rate-fast.html | 52 + .../animations/update-playback-rate-zero-ref.html | 16 + .../animations/update-playback-rate-zero.html | 46 + .../animations/updating-the-finished-state.html | 457 +++ .../time-transformations/transformed-progress.html | 391 +++ .../timing-model/timelines/document-timelines.html | 50 + .../timelines/resources/target-frame.html | 76 + .../timelines/resources/timeline-frame.html | 20 + .../timelines/sibling-iframe-timeline.html | 58 + .../timing-model/timelines/timelines.html | 144 + .../update-and-send-events-replacement.html | 1017 +++++++ .../timelines/update-and-send-events.html | 257 ++ 176 files changed, 24571 insertions(+) create mode 100644 testing/web-platform/tests/web-animations/META.yml create mode 100644 testing/web-platform/tests/web-animations/README.md create mode 100644 testing/web-platform/tests/web-animations/WEB_FEATURES.yml create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-001.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-002.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-001.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-002.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/discrete.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/display.tentative.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-001.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-002.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/property-list.js create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/property-utils.js create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/animation-types/visibility.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-interpolated-transform.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-the-composited-result.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/combining-effects/effect-composition.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/computed-keyframes-shorthands.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-in-removed-iframe-crash.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root-ref.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-ref.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-replaced-animations.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/keyframe-exceptions.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001-ref.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/resources/side-effects-common.js create mode 100644 testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current-ref.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect-ref.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none-ref.html create mode 100644 testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none.html create mode 100644 testing/web-platform/tests/web-animations/crashtests/color-mix-crashtest.html create mode 100644 testing/web-platform/tests/web-animations/crashtests/get-computed-timing-crash.html create mode 100644 testing/web-platform/tests/web-animations/crashtests/infinite-active-duration.html create mode 100644 testing/web-platform/tests/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html create mode 100644 testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-001.html create mode 100644 testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-002.html create mode 100644 testing/web-platform/tests/web-animations/idlharness.window.js create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animatable/animate.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations-iframe.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-crash.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-svg-crash.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/effect.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/finished.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/id.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/onremove.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/pause.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/pending.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/persist.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/play.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/ready.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Animation/style-change-events.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/AnimationEffect/getComputedTiming.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/AnimationEffect/updateTiming.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/Document/timeline.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/DocumentOrShadowRoot/getAnimations.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/constructor.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/style-change-events.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/composite.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/constructor.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/getKeyframes.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/style-change-events.html create mode 100644 testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html create mode 100644 testing/web-platform/tests/web-animations/resources/easing-tests.js create mode 100644 testing/web-platform/tests/web-animations/resources/effect-tests.js create mode 100644 testing/web-platform/tests/web-animations/resources/keyframe-tests.js create mode 100644 testing/web-platform/tests/web-animations/resources/keyframe-utils.js create mode 100644 testing/web-platform/tests/web-animations/resources/timing-override.js create mode 100644 testing/web-platform/tests/web-animations/resources/timing-tests.js create mode 100644 testing/web-platform/tests/web-animations/resources/timing-utils.js create mode 100644 testing/web-platform/tests/web-animations/resources/xhr-doc.py create mode 100644 testing/web-platform/tests/web-animations/responsive/assorted-lengths.html create mode 100644 testing/web-platform/tests/web-animations/responsive/backgroundPosition.html create mode 100644 testing/web-platform/tests/web-animations/responsive/backgroundSize.html create mode 100644 testing/web-platform/tests/web-animations/responsive/baselineShift.html create mode 100644 testing/web-platform/tests/web-animations/responsive/borderImageWidth.html create mode 100644 testing/web-platform/tests/web-animations/responsive/borderRadius.html create mode 100644 testing/web-platform/tests/web-animations/responsive/borderWidth.html create mode 100644 testing/web-platform/tests/web-animations/responsive/boxShadow.html create mode 100644 testing/web-platform/tests/web-animations/responsive/clip.html create mode 100644 testing/web-platform/tests/web-animations/responsive/columnCount.html create mode 100644 testing/web-platform/tests/web-animations/responsive/columnGap.html create mode 100644 testing/web-platform/tests/web-animations/responsive/d.html create mode 100644 testing/web-platform/tests/web-animations/responsive/font-size-adjust.html create mode 100644 testing/web-platform/tests/web-animations/responsive/fontSize.html create mode 100644 testing/web-platform/tests/web-animations/responsive/fontWeight.html create mode 100644 testing/web-platform/tests/web-animations/responsive/lineHeight.html create mode 100644 testing/web-platform/tests/web-animations/responsive/minHeight.html create mode 100644 testing/web-platform/tests/web-animations/responsive/offset-path.html create mode 100644 testing/web-platform/tests/web-animations/responsive/offsetDistance.html create mode 100644 testing/web-platform/tests/web-animations/responsive/offsetRotate.html create mode 100644 testing/web-platform/tests/web-animations/responsive/opacity.html create mode 100644 testing/web-platform/tests/web-animations/responsive/perspective.html create mode 100644 testing/web-platform/tests/web-animations/responsive/resources/block.html create mode 100644 testing/web-platform/tests/web-animations/responsive/rotate.html create mode 100644 testing/web-platform/tests/web-animations/responsive/rowGap.html create mode 100644 testing/web-platform/tests/web-animations/responsive/shapeMargin.html create mode 100644 testing/web-platform/tests/web-animations/responsive/shapeOutside.html create mode 100644 testing/web-platform/tests/web-animations/responsive/strokeDasharray.html create mode 100644 testing/web-platform/tests/web-animations/responsive/text-size-adjust.html create mode 100644 testing/web-platform/tests/web-animations/responsive/textIndent.html create mode 100644 testing/web-platform/tests/web-animations/responsive/to-color-change.html create mode 100644 testing/web-platform/tests/web-animations/responsive/to-inherited-change.html create mode 100644 testing/web-platform/tests/web-animations/responsive/to-style-change.html create mode 100644 testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility-ref.html create mode 100644 testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility.html create mode 100644 testing/web-platform/tests/web-animations/responsive/transform.html create mode 100644 testing/web-platform/tests/web-animations/responsive/translate.html create mode 100644 testing/web-platform/tests/web-animations/responsive/verticalAlign.html create mode 100644 testing/web-platform/tests/web-animations/testcommon.js create mode 100644 testing/web-platform/tests/web-animations/timing-model/animation-effects/active-time.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animation-effects/current-iteration.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animation-effects/local-time.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animation-effects/phases-and-states.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation-ref.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation-ref.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/invalidating-animation-before-start-time-synced.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/play-states.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation-ref.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/reversing-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/setting-the-current-time-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/setting-the-playback-rate-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times-ref.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/the-current-time-of-an-animation.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast-ref.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero-ref.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/animations/updating-the-finished-state.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/time-transformations/transformed-progress.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/document-timelines.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/resources/target-frame.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/resources/timeline-frame.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/sibling-iframe-timeline.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/timelines.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events-replacement.html create mode 100644 testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events.html (limited to 'testing/web-platform/tests/web-animations') diff --git a/testing/web-platform/tests/web-animations/META.yml b/testing/web-platform/tests/web-animations/META.yml new file mode 100644 index 0000000000..9ba1245bde --- /dev/null +++ b/testing/web-platform/tests/web-animations/META.yml @@ -0,0 +1,5 @@ +spec: https://drafts.csswg.org/web-animations/ +suggested_reviewers: + - birtles + - flackr + - graouts diff --git a/testing/web-platform/tests/web-animations/README.md b/testing/web-platform/tests/web-animations/README.md new file mode 100644 index 0000000000..c41e0e048e --- /dev/null +++ b/testing/web-platform/tests/web-animations/README.md @@ -0,0 +1,116 @@ +Web Animations Test Suite +========================= + +Specification: https://drafts.csswg.org/web-animations/ + + +Guidelines for writing tests +---------------------------- + +* Try to follow the spec outline where possible. + + For example, if you want to test setting the start time, you might be + tempted to put all the tests in: + + > `/web-animations/interfaces/Animation/startTime.html` + + However, in the spec most of the logic is in the “Set the animation + start time“ procedure in the “Timing model” section. + + Instead, try something like: + + > * `/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html`
+ > Tests all the branches and inputs to the procedure as defined in the + > spec (using the `Animation.startTime` API). + > * `/web-animations/interfaces/Animation/startTime.html`
+ > Tests API-layer specific issues like mapping unresolved values to + > null, etc. + + On that note, two levels of subdirectories is enough even if the spec has + deeper nesting. + + Note that most of the existing tests in the suite _don't_ do this well yet. + That's the direction we're heading, however. + +* Test the spec. + + * If the spec defines a timing calculation that is directly + reflected in the iteration progress + (i.e. `anim.effect.getComputedTiming().progress`), test that instead + of calling `getComputedStyle(elem).marginLeft`. + + * Likewise, don't add needless tests for `anim.playbackState`. + The playback state is a calculated value based on other values. + It's rarely necessary to test directly unless you need, for example, + to check that a pending task is scheduled (which isn't observable + elsewhere other than waiting for the corresponding promise to + complete). + +* Try to keep tests as simple and focused as possible. + + e.g. + + ```javascript + test(t => { + const animation = createDiv(t).animate(null); + assert_class_string(animation, 'Animation', 'Returned object is an Animation'); + }, 'Element.animate() creates an Animation object'); + ``` + + ```javascript + test(t => { + assert_throws_js(TypeError, () => { + createDiv(t).animate(null, -1); + }); + }, 'Setting a negative duration throws a TypeError'); + ``` + + ```javascript + promise_test(t => { + const animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + return animation.ready.then(() => { + assert_greater_than(animation.startTime, 0, 'startTime when running'); + }); + }, 'startTime is resolved when running'); + ``` + + If you're generating complex test loops and factoring out utility functions + that affect the logic of the test (other than, say, simple assertion utility + functions), you're probably doing it wrong. + + It should be possible to understand exactly what the test is doing at a + glance without having to scroll up and down the test file and refer to + other files. + + See Justin Searls' presentation, [“How to stop hating your + tests”](http://blog.testdouble.com/posts/2015-11-16-how-to-stop-hating-your-tests.html) + for some tips on making your tests simpler. + +* Assume tests will run on under-performing hardware where the time between + animation frames might run into 10s of seconds. + As a result, animations that are expected to still be running during + the test should be at least 100s in length. + +* Avoid using `GLOBAL_CONSTS` that make the test harder to read. + It's fine to repeat the the same parameter values like `100 * MS_PER_SEC` + over and over again since it makes it easy to read and debug a test in + isolation. + Remember, even if we do need to make all tests take, say 200s each, text + editors are very good at search and replace. + +* Use the `assert_times_equal` assertion for comparing times returned from + the API. This asserts that the time values are equal using a tolerance + based on the precision recommended in the spec. This tolerance is applied + to *both* of the values being compared. That is, it effectively allows + double the epsilon that is used when comparing with an absolute value. + + For comparing a time value returned from the API to an absolute value, use + `assert_time_equals_literal`. This tests that the actual value is equal to + the expected value within the precision recommended in the spec. + + Both `assert_times_equal` and `assert_time_equals_literal` are defined in a + way that implementations can override them to meet their own precision + requirements. + +* There are quite a few bad tests in the repository. We're learning as + we go. Don't just copy them blindly—please fix them! diff --git a/testing/web-platform/tests/web-animations/WEB_FEATURES.yml b/testing/web-platform/tests/web-animations/WEB_FEATURES.yml new file mode 100644 index 0000000000..be78a70b81 --- /dev/null +++ b/testing/web-platform/tests/web-animations/WEB_FEATURES.yml @@ -0,0 +1,3 @@ +features: +- name: web-animations + files: "**" diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-001.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-001.html new file mode 100644 index 0000000000..a3fd115563 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-001.html @@ -0,0 +1,24 @@ + + +Accumulation for each property + + + + + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-002.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-002.html new file mode 100644 index 0000000000..5cf411edf6 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/accumulation-per-property-002.html @@ -0,0 +1,24 @@ + + +Accumulation for each property + + + + + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-001.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-001.html new file mode 100644 index 0000000000..2fbec2c4cd --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-001.html @@ -0,0 +1,24 @@ + + +Addition for each property + + + + + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-002.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-002.html new file mode 100644 index 0000000000..3b1c40e3c7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/addition-per-property-002.html @@ -0,0 +1,24 @@ + + +Addition for each property + + + + + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/discrete.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/discrete.html new file mode 100644 index 0000000000..76f42bc7a4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/discrete.html @@ -0,0 +1,135 @@ + + +Discrete animation type + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/display.tentative.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/display.tentative.html new file mode 100644 index 0000000000..6b28dcd964 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/display.tentative.html @@ -0,0 +1,34 @@ + + +Animation type for the 'display' property + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-001.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-001.html new file mode 100644 index 0000000000..97f2822473 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-001.html @@ -0,0 +1,24 @@ + + +Interpolation for each property + + + + + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-002.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-002.html new file mode 100644 index 0000000000..9ccc613cfc --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/interpolation-per-property-002.html @@ -0,0 +1,24 @@ + + +Interpolation for each property + + + + + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/property-list.js b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-list.js new file mode 100644 index 0000000000..98ab02a122 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-list.js @@ -0,0 +1,1618 @@ +'use strict'; + +const gCSSProperties1 = { + 'align-content': { + // https://drafts.csswg.org/css-align/#propdef-align-content + types: [ + { type: 'discrete' , options: [ [ 'flex-start', 'flex-end' ] ] } + ] + }, + 'align-items': { + // https://drafts.csswg.org/css-align/#propdef-align-items + types: [ + { type: 'discrete', options: [ [ 'flex-start', 'flex-end' ] ] } + ] + }, + 'align-self': { + // https://drafts.csswg.org/css-align/#propdef-align-self + types: [ + { type: 'discrete', options: [ [ 'flex-start', 'flex-end' ] ] } + ] + }, + 'backface-visibility': { + // https://drafts.csswg.org/css-transforms/#propdef-backface-visibility + types: [ + { type: 'discrete', options: [ [ 'visible', 'hidden' ] ] } + ] + }, + 'background-attachment': { + // https://drafts.csswg.org/css-backgrounds-3/#background-attachment + types: [ + { type: 'discrete', options: [ [ 'fixed', 'local' ] ] } + ] + }, + 'background-color': { + // https://drafts.csswg.org/css-backgrounds-3/#background-color + types: [ 'color' ] + }, + 'background-blend-mode': { + // https://drafts.fxtf.org/compositing-1/#propdef-background-blend-mode + types: [ + { type: 'discrete', options: [ [ 'multiply', 'screen' ] ] } + ] + }, + 'background-clip': { + // https://drafts.csswg.org/css-backgrounds-3/#background-clip + types: [ + { type: 'discrete', options: [ [ 'padding-box', 'content-box' ] ] } + ] + }, + 'background-image': { + // https://drafts.csswg.org/css-backgrounds-3/#background-image + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'background-origin': { + // https://drafts.csswg.org/css-backgrounds-3/#background-origin + types: [ + { type: 'discrete', options: [ [ 'padding-box', 'content-box' ] ] } + ] + }, + 'background-position': { + // https://drafts.csswg.org/css-backgrounds-3/#background-position + types: [ + ] + }, + 'background-position-x': { + // https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-x + types: [ + ] + }, + 'background-position-y': { + // https://drafts.csswg.org/css-backgrounds-4/#propdef-background-position-y + types: [ + ] + }, + 'background-repeat': { + // https://drafts.csswg.org/css-backgrounds-3/#background-repeat + types: [ + { type: 'discrete', options: [ [ 'space', 'round' ] ] } + ] + }, + 'background-size': { + // https://drafts.csswg.org/css-backgrounds-3/#background-size + types: [ + ] + }, + 'block-size': { + // https://drafts.csswg.org/css-logical-props/#propdef-block-size + types: [ + ] + }, + 'border-block-end-color': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-end-color + types: [ + ] + }, + 'border-block-end-style': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-end-style + types: [ + ] + }, + 'border-block-end-width': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-end-width + types: [ + ] + }, + 'border-block-start-color': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-start-color + types: [ + ] + }, + 'border-block-start-style': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-start-style + types: [ + ] + }, + 'border-block-start-width': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-start-width + types: [ + ] + }, + 'border-bottom-color': { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-color + types: [ 'color' ] + }, + 'border-bottom-left-radius': { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-left-radius + types: [ + ] + }, + 'border-bottom-right-radius': { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-right-radius + types: [ + ] + }, + 'border-bottom-style': { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-style + types: [ + { type: 'discrete', options: [ [ 'dotted', 'solid' ] ] } + ] + }, + 'border-bottom-width': { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-width + types: [ 'length' ], + setup: t => { + const element = createElement(t); + element.style.borderBottomStyle = 'solid'; + return element; + } + }, + 'border-collapse': { + // https://drafts.csswg.org/css-tables/#propdef-border-collapse + types: [ + { type: 'discrete', options: [ [ 'collapse', 'separate' ] ] } + ] + }, + 'border-inline-end-color': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-inline-end-color + types: [ + ] + }, + 'border-inline-end-style': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-inline-end-style + types: [ + ] + }, + 'border-inline-end-width': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-inline-end-width + types: [ + ] + }, + 'border-inline-start-color': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-inline-start-color + types: [ + ] + }, + 'border-inline-start-style': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-block-start-style + types: [ + ] + }, + 'border-inline-start-width': { + // https://drafts.csswg.org/css-logical-props/#propdef-border-inline-start-width + types: [ + ] + }, + 'border-image-outset': { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-outset + types: [ + ] + }, + 'border-image-repeat': { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-repeat + types: [ + { type: 'discrete', options: [ [ 'stretch repeat', 'round space' ] ] } + ] + }, + 'border-image-slice': { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-slice + types: [ + ] + }, + 'border-image-source': { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-source + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'border-image-width': { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-width + types: [ + ] + }, + 'border-left-color': { + // https://drafts.csswg.org/css-backgrounds-3/#border-left-color + types: [ 'color' ] + }, + 'border-left-style': { + // https://drafts.csswg.org/css-backgrounds-3/#border-left-style + types: [ + { type: 'discrete', options: [ [ 'dotted', 'solid' ] ] } + ] + }, + 'border-left-width': { + // https://drafts.csswg.org/css-backgrounds-3/#border-left-width + types: [ 'length' ], + setup: t => { + const element = createElement(t); + element.style.borderLeftStyle = 'solid'; + return element; + } + }, + 'border-right-color': { + // https://drafts.csswg.org/css-backgrounds-3/#border-right-color + types: [ 'color' ] + }, + 'border-right-style': { + // https://drafts.csswg.org/css-backgrounds-3/#border-right-style + types: [ + { type: 'discrete', options: [ [ 'dotted', 'solid' ] ] } + ] + }, + 'border-right-width': { + // https://drafts.csswg.org/css-backgrounds-3/#border-right-width + types: [ 'length' ], + setup: t => { + const element = createElement(t); + element.style.borderRightStyle = 'solid'; + return element; + } + }, + 'border-spacing': { + // https://drafts.csswg.org/css-tables/#propdef-border-spacing + types: [ 'lengthPair' ] + }, + 'border-top-color': { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-color + types: [ 'color' ] + }, + 'border-top-left-radius': { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-left-radius + types: [ + ] + }, + 'border-top-right-radius': { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-right-radius + types: [ + ] + }, + 'border-top-style': { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-style + types: [ + { type: 'discrete', options: [ [ 'dotted', 'solid' ] ] } + ] + }, + 'border-top-width': { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-width + types: [ 'length' ], + setup: t => { + const element = createElement(t); + element.style.borderTopStyle = 'solid'; + return element; + } + }, + 'bottom': { + // https://drafts.csswg.org/css-position/#propdef-bottom + types: [ + ] + }, + 'box-decoration-break': { + // https://drafts.csswg.org/css-break/#propdef-box-decoration-break + types: [ + { type: 'discrete', options: [ [ 'slice', 'clone' ] ] } + ] + }, + 'box-shadow': { + // https://drafts.csswg.org/css-backgrounds/#box-shadow + types: [ 'boxShadowList' ], + }, + 'box-sizing': { + // https://drafts.csswg.org/css-ui-4/#box-sizing + types: [ + { type: 'discrete', options: [ [ 'content-box', 'border-box' ] ] } + ] + }, + 'caption-side': { + // https://drafts.csswg.org/css-tables/#propdef-caption-side + types: [ + { type: 'discrete', options: [ [ 'top', 'bottom' ] ] } + ] + }, + 'caret-color': { + // https://drafts.csswg.org/css-ui/#propdef-caret-color + types: [ 'color' ] + }, + 'clear': { + // https://drafts.csswg.org/css-page-floats/#propdef-clear + types: [ + { type: 'discrete', options: [ [ 'left', 'right' ] ] } + ] + }, + 'clip': { + // https://drafts.fxtf.org/css-masking-1/#propdef-clip + types: [ + 'rect', + { type: 'discrete', options: [ [ 'rect(10px, 10px, 10px, 10px)', + 'auto' ], + [ 'rect(10px, 10px, 10px, 10px)', + 'rect(10px, 10px, 10px, auto)'] ] } + ] + }, + 'clip-path': { + // https://drafts.fxtf.org/css-masking-1/#propdef-clip-path + types: [ + ] + }, + 'clip-rule': { + // https://drafts.fxtf.org/css-masking-1/#propdef-clip-rule + types: [ + { type: 'discrete', options: [ [ 'evenodd', 'nonzero' ] ] } + ] + }, + 'color': { + // https://drafts.csswg.org/css-color/#propdef-color + types: [ 'color' ] + }, + 'color-adjust': { + // https://drafts.csswg.org/css-color-4/#color-adjust + types: [ + { type: 'discrete', options: [ [ 'economy', 'exact' ] ] } + ] + }, + 'color-interpolation': { + // https://svgwg.org/svg2-draft/painting.html#ColorInterpolationProperty + types: [ + { type: 'discrete', options: [ [ 'linearrgb', 'auto' ] ] } + ] + }, + 'color-interpolation-filters': { + // https://drafts.fxtf.org/filters-1/#propdef-color-interpolation-filters + types: [ + { type: 'discrete', options: [ [ 'srgb', 'linearrgb' ] ] } + ] + }, + 'column-count': { + // https://drafts.csswg.org/css-multicol/#propdef-column-count + types: [ 'positiveInteger', + { type: 'discrete', options: [ [ 'auto', '10' ] ] } + ] + }, + 'column-gap': { + // https://drafts.csswg.org/css-multicol/#propdef-column-gap + types: [ 'length', + { type: 'discrete', options: [ [ 'normal', '200px' ] ] } + ] + }, + 'column-rule-color': { + // https://drafts.csswg.org/css-multicol/#propdef-column-rule-color + types: [ 'color' ] + }, + 'column-fill': { + // https://drafts.csswg.org/css-multicol/#propdef-column-fill + types: [ + { type: 'discrete', options: [ [ 'auto', 'balance' ] ] } + ] + }, + 'column-rule-style': { + // https://drafts.csswg.org/css-multicol/#propdef-column-rule-style + types: [ + { type: 'discrete', options: [ [ 'none', 'dotted' ] ] } + ] + }, + 'column-rule-width': { + // https://drafts.csswg.org/css-multicol/#propdef-column-rule-width + types: [ 'length' ], + setup: t => { + const element = createElement(t); + element.style.columnRuleStyle = 'solid'; + return element; + } + }, + 'column-width': { + // https://drafts.csswg.org/css-multicol/#propdef-column-width + types: [ 'length', + { type: 'discrete', options: [ [ 'auto', '1px' ] ] } + ] + }, + 'counter-increment': { + // https://drafts.csswg.org/css-lists-3/#propdef-counter-increment + types: [ + { type: 'discrete', options: [ [ 'ident-1 1', 'ident-2 2' ] ] } + ] + }, + 'counter-reset': { + // https://drafts.csswg.org/css-lists-3/#propdef-counter-reset + types: [ + { type: 'discrete', options: [ [ 'ident-1 1', 'ident-2 2' ] ] } + ] + }, + 'cursor': { + // https://drafts.csswg.org/css2/ui.html#propdef-cursor + types: [ + { type: 'discrete', options: [ [ 'pointer', 'wait' ] ] } + ] + }, + 'dominant-baseline': { + // https://drafts.csswg.org/css-inline/#propdef-dominant-baseline + types: [ + { type: 'discrete', options: [ [ 'ideographic', 'alphabetic' ] ] } + ] + }, + 'empty-cells': { + // https://drafts.csswg.org/css-tables/#propdef-empty-cells + types: [ + { type: 'discrete', options: [ [ 'show', 'hide' ] ] } + ] + }, + 'field-sizing': { + // https://drafts.csswg.org/css-ui/#field-sizing + types: [ + { type: 'discrete', options: [ [ 'fixed', 'content' ] ] } + ] + }, + 'fill': { + // https://svgwg.org/svg2-draft/painting.html#FillProperty + types: [ + ] + }, + 'fill-opacity': { + // https://svgwg.org/svg2-draft/painting.html#FillOpacityProperty + types: [ 'opacity' ] + }, + 'fill-rule': { + // https://svgwg.org/svg2-draft/painting.html#FillRuleProperty + types: [ + { type: 'discrete', options: [ [ 'evenodd', 'nonzero' ] ] } + ] + }, + 'filter': { + // https://drafts.fxtf.org/filters/#propdef-filter + types: [ 'filterList' ] + }, + 'flex-basis': { + // https://drafts.csswg.org/css-flexbox/#propdef-flex-basis + types: [ + 'lengthPercentageOrCalc', + { type: 'discrete', options: [ [ 'auto', '10px' ] ] } + ] + }, + 'flex-direction': { + // https://drafts.csswg.org/css-flexbox/#propdef-flex-direction + types: [ + { type: 'discrete', options: [ [ 'row', 'row-reverse' ] ] } + ] + }, + 'flex-grow': { + // https://drafts.csswg.org/css-flexbox/#flex-grow-property + types: [ 'positiveNumber' ] + }, + 'flex-shrink': { + // https://drafts.csswg.org/css-flexbox/#propdef-flex-shrink + types: [ 'positiveNumber' ] + }, + 'flex-wrap': { + // https://drafts.csswg.org/css-flexbox/#propdef-flex-wrap + types: [ + { type: 'discrete', options: [ [ 'nowrap', 'wrap' ] ] } + ] + }, + 'flood-color': { + // https://drafts.fxtf.org/filters/#FloodColorProperty + types: [ 'color' ] + }, + 'flood-opacity': { + // https://drafts.fxtf.org/filters/#propdef-flood-opacity + types: [ 'opacity' ] + }, + 'font-size': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-size + types: [ + ] + }, + 'font-size-adjust': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-size-adjust + types: [ + ] + }, + 'font-stretch': { + // https://drafts.csswg.org/css-fonts-4/#propdef-font-stretch + types: [ 'percentage' ] + }, + 'font-style': { + // https://drafts.csswg.org/css-fonts/#propdef-font-style + types: [ + { type: 'discrete', options: [ [ 'italic', 'oblique' ] ] } + ] + }, + 'float': { + // https://drafts.csswg.org/css-page-floats/#propdef-float + types: [ + { type: 'discrete', options: [ [ 'left', 'right' ] ] } + ] + }, + 'font-family': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-family + types: [ + { type: 'discrete', options: [ [ 'helvetica', 'verdana' ] ] } + ] + }, + 'font-feature-settings': { + // https://drafts.csswg.org/css-fonts/#descdef-font-feature-settings + types: [ + { type: 'discrete', options: [ [ '"liga" 5', 'normal' ] ] } + ] + }, + 'font-kerning': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-kerning + types: [ + { type: 'discrete', options: [ [ 'auto', 'normal' ] ] } + ] + }, + 'font-language-override': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override + types: [ + { type: 'discrete', options: [ [ '"eng"', 'normal' ] ] } + ] + }, + 'font-style': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-style + types: [ + { type: 'discrete', options: [ [ 'italic', 'oblique' ] ] } + ] + }, + 'font-synthesis': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-synthesis + types: [ + { type: 'discrete', options: [ [ 'none', 'weight style' ] ] } + ] + }, + 'font-variant-alternates': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-alternates + types: [ + { type: 'discrete', + options: [ [ 'swash(unknown)', 'stylistic(unknown)' ] ] } + ] + }, + 'font-variant-caps': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-caps + types: [ + { type: 'discrete', options: [ [ 'small-caps', 'unicase' ] ] } + ] + }, + 'font-variant-east-asian': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-east-asian + types: [ + { type: 'discrete', options: [ [ 'full-width', 'proportional-width' ] ] } + ] + }, + 'font-variant-emoji': { + // https://drafts.csswg.org/css-fonts/#propdef-font-variant-emoji + types: [ + { type: 'discrete', options: [ [ 'text', 'emoji' ] ] } + ] + }, + 'font-variant-ligatures': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-ligatures + types: [ + { type: 'discrete', + options: [ [ 'common-ligatures', 'no-common-ligatures' ] ] } + ] + }, + 'font-variant-numeric': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-numeric + types: [ + { type: 'discrete', options: [ [ 'lining-nums', 'oldstyle-nums' ] ] } + ] + }, + 'font-variant-position': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-position + types: [ + { type: 'discrete', options: [ [ 'sub', 'super' ] ] } + ] + }, + 'font-variation-settings': { + // https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-variation-settings + types: [ + 'fontVariationSettings', + { type: 'discrete', + options: [ ['"wdth" 1, "wght" 1.1', '"wdth" 5'], + ['"wdth" 5', 'normal'] + ] }, + ] + }, + 'font-weight': { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-weight + types: [ + ] + }, + 'grid-auto-columns': { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-columns + types: [ + { type: 'discrete', options: [ [ '1px', '5px' ] ] } + ] + }, + 'grid-auto-flow': { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow + types: [ + { type: 'discrete', options: [ [ 'row', 'column' ] ] } + ] + }, + 'grid-auto-rows': { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-rows + types: [ + { type: 'discrete', options: [ [ '1px', '5px' ] ] } + ] + }, + 'grid-column-end': { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-end + types: [ + { type: 'discrete', options: [ [ '1', '5' ] ] } + ] + }, + 'grid-column-gap': { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-gap + types: [ + ] + }, + 'grid-column-start': { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-start + types: [ + { type: 'discrete', options: [ [ '1', '5' ] ] } + ] + }, + 'grid-row-end': { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-end + types: [ + { type: 'discrete', options: [ [ '1', '5' ] ] } + ] + }, + 'grid-row-gap': { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-gap + types: [ + ] + }, + 'grid-row-start': { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-start + types: [ + { type: 'discrete', options: [ [ '1', '5' ] ] } + ] + }, + 'grid-template-areas': { + // https://drafts.csswg.org/css-template/#grid-template-areas + types: [ + { type: 'discrete', options: [ [ '". . a b" ". . a b"', 'none' ] ] } + ] + }, + 'height': { + // https://drafts.csswg.org/css21/visudet.html#propdef-height + types: [ + ] + }, + 'hyphens': { + // https://drafts.csswg.org/css-text-3/#propdef-hyphens + types: [ + { type: 'discrete', options: [ [ 'manual', 'none' ] ] } + ] + }, + 'image-orientation': { + // https://drafts.csswg.org/css-images-3/#propdef-image-orientation + types: [ + { type: 'discrete', options: [ [ 'none', 'from-image' ] ] } + ] + }, + 'image-rendering': { + // https://drafts.csswg.org/css-images-3/#propdef-image-rendering + types: [ + ] + }, + 'ime-mode': { + // https://drafts.csswg.org/css-ui/#input-method-editor + types: [ + { type: 'discrete', options: [ [ 'disabled', 'auto' ] ] } + ] + }, + 'initial-letter': { + // https://drafts.csswg.org/css-inline/#propdef-initial-letter + types: [ + { type: 'discrete', options: [ [ '1 2', '3 4' ] ] } + ] + }, +}; + +const gCSSProperties2 = { + 'inline-size': { + // https://drafts.csswg.org/css-logical-props/#propdef-inline-size + types: [ + ] + }, + 'isolation': { + // https://drafts.fxtf.org/compositing-1/#propdef-isolation + types: [ + { type: 'discrete', options: [ [ 'auto', 'isolate' ] ] } + ] + }, + 'justify-content': { + // https://drafts.csswg.org/css-align/#propdef-justify-content + types: [ + { type: 'discrete', options: [ [ 'start', 'end' ] ] } + ] + }, + 'justify-items': { + // https://drafts.csswg.org/css-align/#propdef-justify-items + types: [ + { type: 'discrete', options: [ [ 'start', 'end' ] ] } + ] + }, + 'justify-self': { + // https://drafts.csswg.org/css-align/#propdef-justify-self + types: [ + { type: 'discrete', options: [ [ 'start', 'end' ] ] } + ] + }, + 'left': { + // https://drafts.csswg.org/css-position/#propdef-left + types: [ + ] + }, + 'letter-spacing': { + // https://drafts.csswg.org/css-text-3/#propdef-letter-spacing + types: [ 'length' ] + }, + 'lighting-color': { + // https://drafts.fxtf.org/filters/#LightingColorProperty + types: [ 'color' ] + }, + 'line-height': { + // https://drafts.csswg.org/css-inline/#line-height-property + types: [ + { type: 'discrete', options: [ [ 'normal', '10px' ], + [ 'normal', '10', 'normal', '100px' ] ] } + ] + }, + 'list-style-image': { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-image + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'list-style-position': { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-position + types: [ + { type: 'discrete', options: [ [ 'inside', 'outside' ] ] } + ] + }, + 'list-style-type': { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-type + types: [ + { type: 'discrete', options: [ [ 'circle', 'square' ] ] } + ] + }, + 'margin-block-end': { + // https://drafts.csswg.org/css-logical-props/#propdef-margin-block-end + types: [ + ] + }, + 'margin-block-start': { + // https://drafts.csswg.org/css-logical-props/#propdef-margin-block-start + types: [ + ] + }, + 'margin-bottom': { + // https://drafts.csswg.org/css-box/#propdef-margin-bottom + types: [ + ] + }, + 'margin-inline-end': { + // https://drafts.csswg.org/css-logical-props/#propdef-margin-inline-end + types: [ + ] + }, + 'margin-inline-start': { + // https://drafts.csswg.org/css-logical-props/#propdef-margin-inline-start + types: [ + ] + }, + 'margin-left': { + // https://drafts.csswg.org/css-box/#propdef-margin-left + types: [ + ] + }, + 'margin-right': { + // https://drafts.csswg.org/css-box/#propdef-margin-right + types: [ + ] + }, + 'margin-top': { + // https://drafts.csswg.org/css-box/#propdef-margin-top + types: [ + ] + }, + 'marker-end': { + // https://svgwg.org/specs/markers/#MarkerEndProperty + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'marker-mid': { + // https://svgwg.org/specs/markers/#MarkerMidProperty + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'marker-start': { + // https://svgwg.org/specs/markers/#MarkerStartProperty + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'mask': { + // https://drafts.fxtf.org/css-masking-1/#the-mask + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'mask-clip': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-clip + types: [ + { type: 'discrete', options: [ [ 'content-box', 'border-box' ] ] } + ] + }, + 'mask-composite': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-composite + types: [ + { type: 'discrete', options: [ [ 'add', 'subtract' ] ] } + ] + }, + 'mask-image': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-image + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'mask-mode': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-mode + types: [ + { type: 'discrete', options: [ [ 'alpha', 'luminance' ] ] } + ] + }, + 'mask-origin': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-origin + types: [ + { type: 'discrete', options: [ [ 'content-box', 'border-box' ] ] } + ] + }, + 'mask-position': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-position + types: [ + ] + }, + 'mask-position-x': { + // https://lists.w3.org/Archives/Public/www-style/2014Jun/0166.html + types: [ + ] + }, + 'mask-position-y': { + // https://lists.w3.org/Archives/Public/www-style/2014Jun/0166.html + types: [ + ] + }, + 'mask-repeat': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-repeat + types: [ + { type: 'discrete', options: [ [ 'space', 'round' ] ] } + ] + }, + 'mask-size': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-size + types: [ + ] + }, + 'mask-type': { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-type + types: [ + { type: 'discrete', options: [ [ 'alpha', 'luminance' ] ] } + ] + }, + 'max-block-size': { + // https://drafts.csswg.org/css-logical-props/#propdef-max-block-size + types: [ + ] + }, + 'max-height': { + // https://drafts.csswg.org/css21/visudet.html#propdef-max-height + types: [ + ] + }, + 'max-inline-size': { + // https://drafts.csswg.org/css-logical-props/#propdef-max-inline-size + types: [ + ] + }, + 'max-width': { + // https://drafts.csswg.org/css21/visudet.html#propdef-max-width + types: [ + ] + }, + 'min-block-size': { + // https://drafts.csswg.org/css-logical-props/#propdef-min-block-size + types: [ + ] + }, + 'min-height': { + // https://drafts.csswg.org/css21/visudet.html#propdef-min-height + types: [ + ] + }, + 'min-inline-size': { + // https://drafts.csswg.org/css-logical-props/#propdef-min-inline-size + types: [ + ] + }, + 'min-width': { + // https://drafts.csswg.org/css21/visudet.html#propdef-min-width + types: [ + ] + }, + 'mix-blend-mode': { + // https://drafts.fxtf.org/compositing-1/#propdef-mix-blend-mode + types: [ + { type: 'discrete', options: [ [ 'multiply', 'screen' ] ] } + ] + }, + 'object-fit': { + // https://drafts.csswg.org/css-images-3/#propdef-object-fit + types: [ + { type: 'discrete', options: [ [ 'fill', 'contain' ] ] } + ] + }, + 'object-position': { + // https://drafts.csswg.org/css-images-3/#propdef-object-position + types: [ + ] + }, + 'inset-block-end': { + // https://drafts.csswg.org/css-logical-props/#propdef-inset-block-end + types: [ + ] + }, + 'inset-block-start': { + // https://drafts.csswg.org/css-logical-props/#propdef-inset-block-start + types: [ + ] + }, + 'inset-inline-end': { + // https://drafts.csswg.org/css-logical-props/#propdef-inset-inline-end + types: [ + ] + }, + 'inset-inline-start': { + // https://drafts.csswg.org/css-logical-props/#propdef-inset-inline-start + types: [ + ] + }, + 'offset-distance': { + // https://drafts.fxtf.org/motion-1/#offset-distance-property + types: [ 'lengthPercentageOrCalc' ] + }, + 'offset-path': { + // https://drafts.fxtf.org/motion-1/#offset-path-property + types: [ + ] + }, + 'opacity': { + // https://drafts.csswg.org/css-color/#propdef-opacity + types: [ + ] + }, + 'order': { + // https://drafts.csswg.org/css-flexbox/#propdef-order + types: [ 'integer' ] + }, + 'outline-color': { + // https://drafts.csswg.org/css-ui-3/#propdef-outline-color + types: [ 'color' ] + }, + 'outline-offset': { + // https://drafts.csswg.org/css-ui-3/#propdef-outline-offset + types: [ 'length' ] + }, + 'outline-style': { + // https://drafts.csswg.org/css-ui/#propdef-outline-style + types: [ + { type: 'discrete', options: [ [ 'none', 'dotted' ] ] } + ] + }, + 'outline-width': { + // https://drafts.csswg.org/css-ui-3/#propdef-outline-width + types: [ 'length' ], + setup: t => { + const element = createElement(t); + element.style.outlineStyle = 'solid'; + return element; + } + }, + 'overflow': { + // https://drafts.csswg.org/css-overflow/#propdef-overflow + types: [ + ] + }, + 'overflow-wrap': { + // https://drafts.csswg.org/css-text-3/#propdef-overflow-wrap + types: [ + { type: 'discrete', options: [ [ 'normal', 'break-word' ] ] } + ] + }, + 'overflow-x': { + // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-x + types: [ + { type: 'discrete', options: [ [ 'visible', 'hidden' ] ] } + ] + }, + 'overflow-y': { + // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-y + types: [ + { type: 'discrete', options: [ [ 'visible', 'hidden' ] ] } + ] + }, + 'padding-block-end': { + // https://drafts.csswg.org/css-logical-props/#propdef-padding-block-end + types: [ + ] + }, + 'padding-block-start': { + // https://drafts.csswg.org/css-logical-props/#propdef-padding-block-start + types: [ + ] + }, + 'padding-bottom': { + // https://drafts.csswg.org/css-box/#propdef-padding-bottom + types: [ + ] + }, + 'padding-inline-end': { + // https://drafts.csswg.org/css-logical-props/#propdef-padding-inline-end + types: [ + ] + }, + 'padding-inline-start': { + // https://drafts.csswg.org/css-logical-props/#propdef-padding-inline-start + types: [ + ] + }, + 'padding-left': { + // https://drafts.csswg.org/css-box/#propdef-padding-left + types: [ + ] + }, + 'padding-right': { + // https://drafts.csswg.org/css-box/#propdef-padding-right + types: [ + ] + }, + 'padding-top': { + // https://drafts.csswg.org/css-box/#propdef-padding-top + types: [ + ] + }, + 'page-break-after': { + // https://drafts.csswg.org/css-break-3/#propdef-break-after + types: [ + { type: 'discrete', options: [ [ 'always', 'auto' ] ] } + ] + }, + 'page-break-before': { + // https://drafts.csswg.org/css-break-3/#propdef-break-before + types: [ + { type: 'discrete', options: [ [ 'always', 'auto' ] ] } + ] + }, + 'page-break-inside': { + // https://drafts.csswg.org/css-break-3/#propdef-break-inside + types: [ + { type: 'discrete', options: [ [ 'auto', 'avoid' ] ] } + ] + }, + 'paint-order': { + // https://svgwg.org/svg2-draft/painting.html#PaintOrderProperty + types: [ + { type: 'discrete', options: [ [ 'fill', 'stroke' ] ] } + ] + }, + 'perspective': { + // https://drafts.csswg.org/css-transforms-1/#propdef-perspective + types: [ 'length' ] + }, + 'perspective-origin': { + // https://drafts.csswg.org/css-transforms-1/#propdef-perspective-origin + types: [ 'position' ] + }, + 'pointer-events': { + // https://svgwg.org/svg2-draft/interact.html#PointerEventsProperty + types: [ + { type: 'discrete', options: [ [ 'fill', 'none' ] ] } + ] + }, + 'position': { + // https://drafts.csswg.org/css-position/#propdef-position + types: [ + { type: 'discrete', options: [ [ 'absolute', 'fixed' ] ] } + ] + }, + 'quotes': { + // https://drafts.csswg.org/css-content-3/#propdef-quotes + types: [ + { type: 'discrete', options: [ [ '"“" "”" "‘" "’"', '"‘" "’" "“" "”"' ] ] } + ] + }, + 'resize': { + // https://drafts.csswg.org/css-ui/#propdef-resize + types: [ + { type: 'discrete', options: [ [ 'both', 'horizontal' ] ] } + ] + }, + 'right': { + // https://drafts.csswg.org/css-position/#propdef-right + types: [ + ] + }, + 'ruby-align': { + // https://drafts.csswg.org/css-ruby-1/#propdef-ruby-align + types: [ + { type: 'discrete', options: [ [ 'start', 'center' ] ] } + ] + }, + 'ruby-position': { + // https://drafts.csswg.org/css-ruby-1/#propdef-ruby-position + types: [ + { type: 'discrete', options: [ [ 'under', 'over' ] ] } + ], + setup: t => { + return createElement(t, 'ruby'); + } + }, + 'scroll-behavior': { + // https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior + types: [ + { type: 'discrete', options: [ [ 'auto', 'smooth' ] ] } + ] + }, + 'scrollbar-color': { + // https://drafts.csswg.org/css-scrollbars/#propdef-scrollbar-color + types: [ 'colorPair' ] + }, + 'scrollbar-gutter': { + // https://drafts.csswg.org/css-overflow/#propdef-scrollbar-gutter + types: [ + { type: 'discrete', options: [ [ 'auto', 'stable' ], [ 'auto', 'stable both-edges' ], [ 'stable', 'stable both-edges' ] ] } + ] + }, + 'scrollbar-width': { + // https://drafts.csswg.org/css-scrollbars/#propdef-scrollbar-width + types: [ + { type: 'discrete', options: [ [ 'auto', 'thin' ], [ 'auto', 'none' ], [ 'thin', 'none' ] ] } + ] + }, + 'shape-outside': { + // http://dev.w3.org/csswg/css-shapes/#propdef-shape-outside + types: [ + { type: 'discrete', + options: [ [ 'url("http://localhost/test-1")', + 'url("http://localhost/test-2")' ] ] } + ] + }, + 'shape-rendering': { + // https://svgwg.org/svg2-draft/painting.html#ShapeRenderingProperty + types: [ + { type: 'discrete', options: [ [ 'optimizeSpeed', 'crispEdges' ] ] } + ] + }, + 'stop-color': { + // https://svgwg.org/svg2-draft/pservers.html#StopColorProperty + types: [ 'color' ] + }, + 'stop-opacity': { + // https://svgwg.org/svg2-draft/pservers.html#StopOpacityProperty + types: [ 'opacity' ] + }, + 'stroke': { + // https://svgwg.org/svg2-draft/painting.html#StrokeProperty + types: [ + ] + }, + 'stroke-dasharray': { + // https://svgwg.org/svg2-draft/painting.html#StrokeDasharrayProperty + types: [ + 'dasharray', + { type: 'discrete', options: [ [ 'none', '10px, 20px' ] ] } + ] + }, + 'stroke-dashoffset': { + // https://svgwg.org/svg2-draft/painting.html#StrokeDashoffsetProperty + types: [ + ] + }, + 'stroke-linecap': { + // https://svgwg.org/svg2-draft/painting.html#StrokeLinecapProperty + types: [ + { type: 'discrete', options: [ [ 'round', 'square' ] ] } + ] + }, + 'stroke-linejoin': { + // https://svgwg.org/svg2-draft/painting.html#StrokeLinejoinProperty + types: [ + { type: 'discrete', options: [ [ 'round', 'miter' ] ] } + ], + setup: t => { + return createElement(t, 'rect'); + } + }, + 'stroke-miterlimit': { + // https://svgwg.org/svg2-draft/painting.html#StrokeMiterlimitProperty + types: [ 'positiveNumber' ] + }, + 'stroke-opacity': { + // https://svgwg.org/svg2-draft/painting.html#StrokeOpacityProperty + types: [ 'opacity' ] + }, + 'stroke-width': { + // https://svgwg.org/svg2-draft/painting.html#StrokeWidthProperty + types: [ + ] + }, + 'table-layout': { + // https://drafts.csswg.org/css-tables/#propdef-table-layout + types: [ + { type: 'discrete', options: [ [ 'auto', 'fixed' ] ] } + ] + }, + 'text-align': { + // https://drafts.csswg.org/css-text-3/#propdef-text-align + types: [ + { type: 'discrete', options: [ [ 'start', 'end' ] ] } + ] + }, + 'text-align-last': { + // https://drafts.csswg.org/css-text-3/#propdef-text-align-last + types: [ + { type: 'discrete', options: [ [ 'start', 'end' ] ] } + ] + }, + 'text-anchor': { + // https://svgwg.org/svg2-draft/text.html#TextAnchorProperty + types: [ + { type: 'discrete', options: [ [ 'middle', 'end' ] ] } + ] + }, + 'text-autospace': { + // https://drafts.csswg.org/css-text-4/#text-autospace-property + types: [ + { type: 'discrete', options: [ [ 'normal', 'no-autospace' ] ] } + ] + }, + 'text-decoration-color': { + // https://drafts.csswg.org/css-text-decor-3/#propdef-text-decoration-color + types: [ 'color' ] + }, + 'text-decoration-line': { + // https://drafts.csswg.org/css-text-decor-3/#propdef-text-decoration-line + types: [ + { type: 'discrete', options: [ [ 'underline', 'overline' ] ] } + ] + }, + 'text-decoration-style': { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-decoration-style + types: [ + { type: 'discrete', options: [ [ 'solid', 'dotted' ] ] } + ] + }, + 'text-emphasis-color': { + // https://drafts.csswg.org/css-text-decor-3/#propdef-text-emphasis-color + types: [ 'color' ] + }, + 'text-emphasis-position': { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-position + types: [ + { type: 'discrete', options: [ [ 'over', 'under left' ] ] } + ] + }, + 'text-emphasis-style': { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-style + types: [ + { type: 'discrete', options: [ [ 'circle', 'open dot' ] ] } + ] + }, + 'text-group-align': { + // https://drafts.csswg.org/css-text-4/#propdef-text-group-align + types: [ + { type: 'discrete', options: [ [ 'none', 'center' ] ] } + ] + }, + 'text-indent': { + // https://drafts.csswg.org/css-text-3/#propdef-text-indent + types: [ + ] + }, + 'text-overflow': { + // https://drafts.csswg.org/css-ui/#propdef-text-overflow + types: [ + { type: 'discrete', options: [ [ 'clip', 'ellipsis' ] ] } + ] + }, + 'text-rendering': { + // https://svgwg.org/svg2-draft/painting.html#TextRenderingProperty + types: [ + { type: 'discrete', options: [ [ 'optimizeSpeed', 'optimizeLegibility' ] ] } + ] + }, + 'text-shadow': { + // https://drafts.csswg.org/css-text-decor-3/#propdef-text-shadow + types: [ 'textShadowList' ], + setup: t => { + const element = createElement(t); + element.style.color = 'green'; + return element; + } + }, + 'text-spacing-trim': { + // https://drafts.csswg.org/css-text-4/#text-spacing-trim-property + types: [ + { type: 'discrete', options: [ [ 'normal', 'space-all' ] ] } + ] + }, + 'text-transform': { + // https://drafts.csswg.org/css-text-3/#propdef-text-transform + types: [ + { type: 'discrete', options: [ [ 'capitalize', 'uppercase' ] ] } + ] + }, + 'text-wrap': { + // https://drafts.csswg.org/css-text-4/#propdef-text-wrap + types: [ + { type: 'discrete', options: [ [ 'wrap', 'nowrap' ] ] } + ] + }, + 'touch-action': { + // https://w3c.github.io/pointerevents/#the-touch-action-css-property + types: [ + { type: 'discrete', options: [ [ 'auto', 'none' ] ] } + ] + }, + 'top': { + // https://drafts.csswg.org/css-position/#propdef-top + types: [ + ] + }, + 'transform': { + // https://drafts.csswg.org/css-transforms/#propdef-transform + types: [ 'transformList' ] + }, + 'transform-box': { + // https://drafts.csswg.org/css-transforms/#propdef-transform-box + types: [ + { type: 'discrete', options: [ [ 'fill-box', 'border-box' ] ] } + ] + }, + 'transform-origin': { + // https://drafts.csswg.org/css-transforms/#propdef-transform-origin + types: [ + ] + }, + 'transform-style': { + // https://drafts.csswg.org/css-transforms/#propdef-transform-style + types: [ + { type: 'discrete', options: [ [ 'flat', 'preserve-3d' ] ] } + ] + }, + 'rotate': { + // https://drafts.csswg.org/css-transforms-2/#individual-transforms + types: [ 'rotateList' ] + }, + 'translate': { + // https://drafts.csswg.org/css-transforms-2/#individual-transforms + types: [ 'translateList' ], + setup: t => { + // We need to set a width/height for resolving percentages against. + const element = createElement(t); + element.style.width = '100px'; + element.style.height = '100px'; + return element; + } + }, + 'scale': { + // https://drafts.csswg.org/css-transforms-2/#individual-transforms + types: [ 'scaleList' ] + }, + 'vector-effect': { + // https://svgwg.org/svg2-draft/coords.html#VectorEffectProperty + types: [ + { type: 'discrete', options: [ [ 'none', 'non-scaling-stroke' ] ] }, + ] + }, + 'vertical-align': { + // https://drafts.csswg.org/css21/visudet.html#propdef-vertical-align + types: [ + ] + }, + 'view-transition-name': { + // https://drafts.csswg.org/css-view-transitions/#propdef-view-transition-name + types: [ + { type: 'discrete', options: [ [ 'none', 'header' ] ] }, + ] + }, + 'visibility': { + // https://drafts.csswg.org/css2/visufx.html#propdef-visibility + types: [ 'visibility' ] + }, + 'white-space': { + // https://drafts.csswg.org/css-text-4/#propdef-white-space + types: [ + { type: 'discrete', options: [ [ 'pre', 'nowrap' ] ] } + ] + }, + 'white-space-collapse': { + // https://drafts.csswg.org/css-text-4/#propdef-white-space-collapse + types: [ + { type: 'discrete', options: [ [ 'collapse', 'preserve' ] ] } + ] + }, + 'width': { + // https://drafts.csswg.org/css21/visudet.html#propdef-width + types: [ + ] + }, + 'word-break': { + // https://drafts.csswg.org/css-text-3/#propdef-word-break + types: [ + { type: 'discrete', options: [ [ 'keep-all', 'break-all' ] ] } + ] + }, + 'word-spacing': { + // https://drafts.csswg.org/css-text-3/#propdef-word-spacing + types: [ 'lengthPercentageOrCalc' ] + }, + 'z-index': { + // https://drafts.csswg.org/css-position/#propdef-z-index + types: [ + ] + }, +}; + +function testAnimationSamples(animation, idlName, testSamples) { + const pseudoType = animation.effect.pseudoElement; + const target = animation.effect.target; + for (const testSample of testSamples) { + animation.currentTime = testSample.time; + assert_equals(getComputedStyle(target, pseudoType)[idlName].toLowerCase(), + testSample.expected, + `The value should be ${testSample.expected}` + + ` at ${testSample.time}ms`); + } +} + +function toOrderedArray(string) { + return string.split(/\s*,\s/).sort(); +} + +// This test is for some list-based CSS properties such as font-variant-settings +// don't specify an order for serializing computed values. +// This test is for such the property. +function testAnimationSamplesWithAnyOrder(animation, idlName, testSamples) { + const type = animation.effect.pseudoElement; + const target = animation.effect.target; + for (const testSample of testSamples) { + animation.currentTime = testSample.time; + + // Convert to array and sort the expected and actual value lists first + // before comparing them. + const computedValues = + toOrderedArray(getComputedStyle(target, type)[idlName]); + const expectedValues = toOrderedArray(testSample.expected); + + assert_array_equals(computedValues, expectedValues, + `The computed values should be ${expectedValues}` + + ` at ${testSample.time}ms`); + } +} + +function RoundMatrix(style) { + var matrixMatch = style.match(/^(matrix(3d)?)\(.+\)$/); + if (!!matrixMatch) { + var matrixType = matrixMatch[1]; + var matrixArgs = style.substr(matrixType.length); + var extractmatrix = function(matrixStr) { + var list = []; + var regex = /[+\-]?[0-9]+[.]?[0-9]*(e[+/-][0-9]+)?/g; + var match = undefined; + do { + match = regex.exec(matrixStr); + if (match) { + list.push(parseFloat(parseFloat(match[0]).toFixed(6))); + } + } while (match); + return list; + } + return matrixType + '(' + extractmatrix(matrixArgs).join(', ') + ')'; + } + return style; +} + +function testAnimationSampleMatrices(animation, idlName, testSamples) { + const target = animation.effect.target; + for (const testSample of testSamples) { + animation.currentTime = testSample.time; + const actual = RoundMatrix(getComputedStyle(target)[idlName]); + const expected = RoundMatrix(createMatrixFromArray(testSample.expected)); + assert_matrix_equals(actual, expected, + `The value should be ${expected} at` + + ` ${testSample.time}ms but got ${actual}`); + } +} + +function testAnimationSampleRotate3d(animation, idlName, testSamples) { + const target = animation.effect.target; + for (const testSample of testSamples) { + animation.currentTime = testSample.time; + const actual = getComputedStyle(target)[idlName]; + const expected = testSample.expected; + assert_rotate3d_equals(actual, expected, + `The value should be ${expected} at` + + ` ${testSample.time}ms but got ${actual}`); + } +} + +function createTestElement(t, setup) { + return setup ? setup(t) : createElement(t); +} + +function isSupported(property) { + const testKeyframe = new TestKeyframe(propertyToIDL(property)); + assert_not_equals(window.KeyframeEffect, undefined, 'window.KeyframeEffect'); + try { + // Since TestKeyframe returns 'undefined' for |property|, + // the KeyframeEffect constructor will throw + // if the string 'undefined' is not a valid value for the property. + new KeyframeEffect(null, testKeyframe); + } catch(e) {} + return testKeyframe.propAccessCount !== 0; +} + +function TestKeyframe(testProp) { + let _propAccessCount = 0; + + Object.defineProperty(this, testProp, { + get: function() { _propAccessCount++; }, + enumerable: true + }); + + Object.defineProperty(this, 'propAccessCount', { + get: function() { return _propAccessCount; } + }); +} + +function propertyToIDL(property) { + // https://drafts.csswg.org/web-animations/#animation-property-name-to-idl-attribute-name + if (property === 'float') { + return 'cssFloat'; + } + return property.replace(/-[a-z]/gi, + function (str) { + return str.substr(1).toUpperCase(); }); +} +function calcFromPercentage(idlName, percentageValue) { + const examElem = document.createElement('div'); + document.body.appendChild(examElem); + examElem.style[idlName] = percentageValue; + + const calcValue = getComputedStyle(examElem)[idlName]; + document.body.removeChild(examElem); + + return calcValue; +} diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js new file mode 100644 index 0000000000..4d693561ce --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js @@ -0,0 +1,2936 @@ +'use strict'; + +const expected = values => { + // Some properties, such as line-height, report computed values which differ + // from the keyframe values. To support this, we allow optional values to specify + // explicit "from" and "to" values as additional keyframe values. + const [ from, to ] = values; + return [ values[2] ?? from, values[3] ?? to ]; +}; + +const discreteType = { + testInterpolation: (property, setup, options) => { + for (const keyframes of options) { + const [ from, to ] = keyframes; + const [ expectedFrom, expectedTo ] = expected(keyframes); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [from, to] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: expectedFrom.toLowerCase() }, + { time: 499, expected: expectedFrom.toLowerCase() }, + { time: 500, expected: expectedTo.toLowerCase() }, + { time: 1000, expected: expectedTo.toLowerCase() }]); + }, `${property} uses discrete animation when animating between` + + ` "${from}" and "${to}" with linear easing`); + + test(t => { + // Easing: http://cubic-bezier.com/#.68,0,1,.01 + // With this curve, we don't reach the 50% point until about 95% of + // the time has expired. + const idlName = propertyToIDL(property); + const keyframes = {}; + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: [from, to] }, + { + duration: 1000, + fill: 'both', + easing: 'cubic-bezier(0.68,0,1,0.01)', + } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: expectedFrom.toLowerCase() }, + { time: 940, expected: expectedFrom.toLowerCase() }, + { time: 960, expected: expectedTo.toLowerCase() }]); + }, `${property} uses discrete animation when animating between` + + ` "${from}" and "${to}" with effect easing`); + + test(t => { + // Easing: http://cubic-bezier.com/#.68,0,1,.01 + // With this curve, we don't reach the 50% point until about 95% of + // the time has expired. + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [from, to], + easing: 'cubic-bezier(0.68,0,1,0.01)', + }, + { duration: 1000, fill: 'both' } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: expectedFrom.toLowerCase() }, + { time: 940, expected: expectedFrom.toLowerCase() }, + { time: 960, expected: expectedTo.toLowerCase() }]); + }, `${property} uses discrete animation when animating between` + + ` "${from}" and "${to}" with keyframe easing`); + } + }, + + testAdditionOrAccumulation: (property, setup, options, composite) => { + for (const keyframes of options) { + const [ from, to ] = keyframes; + const [ expectedFrom, expectedTo ] = expected(keyframes); + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.animate({ [idlName]: [from, from] }, 1000); + const animation = target.animate( + { [idlName]: [to, to] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: expectedTo.toLowerCase() }]); + }, `${property}: "${to}" onto "${from}"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.animate({ [idlName]: [to, to] }, 1000); + const animation = target.animate( + { [idlName]: [from, from] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: expectedFrom.toLowerCase() }]); + }, `${property}: "${from}" onto "${to}"`); + } + }, + + testAddition: function(property, setup, options) { + this.testAdditionOrAccumulation(property, setup, options, 'add'); + }, + + testAccumulation: function(property, setup, options) { + this.testAdditionOrAccumulation(property, setup, options, 'accumulate'); + }, +}; + +const lengthType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10px', '50px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '30px' }]); + }, `${property} supports animating as a length`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['1rem', '5rem'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '30px' }]); + }, `${property} supports animating as a length of rem`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '10px'; + const animation = target.animate( + { [idlName]: ['10px', '50px'] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px' }]); + }, `${property}: length`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '1rem'; + const animation = target.animate( + { [idlName]: ['1rem', '5rem'] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px' }]); + }, `${property}: length of rem`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const lengthPairType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['10px 10px', '50px 50px'] }, + { duration: 1000, fill: 'both' } + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '30px 30px' }]); + }, `${property} supports animating as a length pair`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['1rem 1rem', '5rem 5rem'] }, + { duration: 1000, fill: 'both' } + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '30px 30px' }]); + }, `${property} supports animating as a length pair of rem`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '10px 10px'; + const animation = target.animate( + { [idlName]: ['10px 10px', '50px 50px'] }, + { duration: 1000, composite } + ); + testAnimationSamples( + animation, + idlName, + [{ time: 0, expected: '20px 20px' }] + ); + }, `${property}: length pair`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '1rem 1rem'; + const animation = target.animate( + { [idlName]: ['1rem 1rem', '5rem 5rem'] }, + { duration: 1000, composite } + ); + testAnimationSamples( + animation, + idlName, + [{ time: 0, expected: '20px 20px' }] + ); + }, `${property}: length pair of rem`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const percentageType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10%', '50%'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '30%' }]); + }, `${property} supports animating as a percentage`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '60%'; + const animation = target.animate( + { [idlName]: ['70%', '100%'] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '130%' }]); + }, `${property}: percentage`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const integerType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [-2, 2] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '0' }]); + }, `${property} supports animating as an integer`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = -1; + const animation = target.animate( + { [idlName]: [-2, 2] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-3' }]); + }, `${property}: integer`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const positiveIntegerType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [1, 3] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [ { time: 500, expected: '2' } ]); + }, `${property} supports animating as a positive integer`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 1; + const animation = target.animate( + { [idlName]: [2, 5] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '3' }]); + }, `${property}: positive integer`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const lengthPercentageOrCalcType = { + testInterpolation: (property, setup) => { + lengthType.testInterpolation(property, setup); + percentageType.testInterpolation(property, setup); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10px', '20%'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'calc(10% + 5px)' }]); + }, `${property} supports animating as combination units "px" and "%"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10%', '2em'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'calc(5% + 10px)' }]); + }, `${property} supports animating as combination units "%" and "em"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['1em', '2rem'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '15px' }]); + }, `${property} supports animating as combination units "em" and "rem"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['10px', 'calc(1em + 20%)'] }, + { duration: 1000, fill: 'both' } + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'calc(10% + 10px)' }]); + }, `${property} supports animating as combination units "px" and "calc"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['calc(10px + 10%)', 'calc(1em + 1rem + 20%)'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, + expected: 'calc(15% + 15px)' }]); + }, `${property} supports animating as a calc`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + lengthType.testAddition(property, setup); + percentageType.testAddition(property, setup); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '10px'; + const animation = target.animate({ [idlName]: ['10%', '50%'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'calc(10% + 10px)' }]); + }, `${property}: units "%" onto "px"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '10%'; + const animation = target.animate({ [idlName]: ['10px', '50px'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'calc(10% + 10px)' }]); + }, `${property}: units "px" onto "%"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '10%'; + const animation = target.animate({ [idlName]: ['2rem', '5rem'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'calc(10% + 20px)' }]); + }, `${property}: units "rem" onto "%"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2rem'; + const animation = target.animate({ [idlName]: ['10%', '50%'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'calc(10% + 20px)' }]); + }, `${property}: units "%" onto "rem"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2em'; + const animation = target.animate({ [idlName]: ['2rem', '5rem'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '40px' }]); + }, `${property}: units "rem" onto "em"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2rem'; + const animation = target.animate({ [idlName]: ['2em', '5em'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '40px' }]); + }, `${property}: units "em" onto "rem"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '10px'; + const animation = target.animate({ [idlName]: ['calc(2em + 20%)', + 'calc(5rem + 50%)'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'calc(20% + 30px)' }]); + }, `${property}: units "calc" onto "px"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'calc(10px + 10%)'; + const animation = target.animate({ [idlName]: ['calc(20px + 20%)', + 'calc(2em + 3rem + 40%)'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'calc(30% + 30px)' }]); + }, `${property}: calc`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const positiveNumberType = { + testInterpolation: (property, setup, expectedUnit='') => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [1.1, 1.5] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '1.3' + expectedUnit }]); + }, `${property} supports animating as a positive number`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 1.1; + const animation = target.animate({ [idlName]: [1.1, 1.5] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '2.2' }]); + }, `${property}: positive number`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +// Test using float values in the range [0, 1] +const opacityType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: [0.3, 0.8] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '0.55' }]); + }, `${property} supports animating as a [0, 1] number`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 0.3; + const animation = target.animate({ [idlName]: [0.3, 0.8] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '0.6' }]); + }, `${property}: [0, 1] number`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 0.8; + const animation = target.animate({ [idlName]: [0.3, 0.8] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, [{ time: 0, expected: '1' }]); + }, `${property}: [0, 1] number (clamped)`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const visibilityType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['visible', 'hidden'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'visible' }, + { time: 999, expected: 'visible' }, + { time: 1000, expected: 'hidden' }]); + }, `${property} uses visibility animation when animating` + + ' from "visible" to "hidden"'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hidden', 'visible'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'hidden' }, + { time: 1, expected: 'visible' }, + { time: 1000, expected: 'visible' }]); + }, `${property} uses visibility animation when animating` + + ' from "hidden" to "visible"'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hidden', 'collapse'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'hidden' }, + { time: 499, expected: 'hidden' }, + { time: 500, expected: 'collapse' }, + { time: 1000, expected: 'collapse' }]); + }, `${property} uses visibility animation when animating` + + ' from "hidden" to "collapse"'); + + test(t => { + // Easing: http://cubic-bezier.com/#.68,-.55,.26,1.55 + // With this curve, the value is less than 0 till about 34% + // also more than 1 since about 63% + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['visible', 'hidden'] }, + { duration: 1000, fill: 'both', + easing: 'cubic-bezier(0.68, -0.55, 0.26, 1.55)' }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'visible' }, + { time: 1, expected: 'visible' }, + { time: 330, expected: 'visible' }, + { time: 340, expected: 'visible' }, + { time: 620, expected: 'visible' }, + { time: 630, expected: 'hidden' }, + { time: 1000, expected: 'hidden' }]); + }, `${property} uses visibility animation when animating` + + ' from "visible" to "hidden" with easeInOutBack easing'); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'visible'; + const animation = target.animate({ [idlName]: ['visible', 'hidden'] }, + { duration: 1000, fill: 'both', + composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'visible' }, + { time: 1000, expected: 'hidden' }]); + }, `${property}: onto "visible"`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'hidden'; + const animation = target.animate({ [idlName]: ['hidden', 'visible'] }, + { duration: 1000, fill: 'both', + composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'hidden' }, + { time: 1000, expected: 'visible' }]); + }, `${property}: onto "hidden"`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const colorType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['rgb(255, 0, 0)', + 'rgb(0, 0, 255)'] }, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(128, 0, 128)' }]); + }, `${property} supports animating as color of rgb()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] }, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(128, 0, 128)' }]); + }, `${property} supports animating as color of #RGB`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)', + 'hsl(240, 100%, 50%)'] }, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(128, 0, 128)' }]); + }, `${property} supports animating as color of hsl()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['#ff000066', '#0000ffcc'] }, + 1000 + ); + // R: 255 * (0.4 * 0.5) / 0.6 = 85 + // B: 255 * (0.8 * 0.5) / 0.6 = 170 + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]); + }, `${property} supports animating as color of #RGBa`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['rgba(255, 0, 0, 0.4)', 'rgba(0, 0, 255, 0.8)'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]); + }, `${property} supports animating as color of rgba()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8)'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]); + }, `${property} supports animating as color of hsla()`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128)'; + const animation = target.animate( + { + [idlName]: ['rgb(255, 0, 0)', 'rgb(0, 0, 255)'], + }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(255, 128, 128)' }, + // The value at 50% is interpolated + // from 'rgb(128+255, 128, 128)' + // to 'rgb(128, 128, 128+255)'. + { time: 500, expected: 'rgb(255, 128, 255)' }]); + }, `${property} supports animating as color of rgb() with overflowed ` + + ' from and to values'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128)'; + const animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(255, 128, 128)' }]); + }, `${property} supports animating as color of #RGB`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128)'; + const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)', + 'hsl(240, 100%, 50%)'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(255, 128, 128)' }]); + }, `${property} supports animating as color of hsl()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128)'; + const animation = target.animate( + { [idlName]: ['#ff000066', '#0000ffcc'] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(230, 128, 128)' }]); + }, `${property} supports animating as color of #RGBa`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128)'; + const animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)', + 'rgba(0, 0, 255, 0.8)'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 0, expected: 'rgb(230, 128, 128)' }]); + }, `${property} supports animating as color of rgba()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128)'; + const animation = target.animate( + { + [idlName]: ['hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8)'], + }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 0, expected: 'rgb(230, 128, 128)' }]); + }, `${property} supports animating as color of hsla()`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const colorPairType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['rgb(255, 0, 0) rgb(0, 0, 255)', + 'rgb(0, 0, 255) rgb(0, 255, 0)'] }, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(128, 0, 128) rgb(0, 128, 128)' }]); + }, `${property} supports animating as color pair of rgb()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['#ff0000 #00ff00', '#0000ff #ff0000'] }, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(128, 0, 128) rgb(128, 128, 0)' }]); + }, `${property} supports animating as color pair of #RGB`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%) hsl(0, 100%, 50%)', + 'hsl(240, 100%, 50%) hsl(360, 100%, 50%)'] }, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(128, 0, 128) rgb(255, 0, 0)' }]); + }, `${property} supports animating as color pair of hsl()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: ['#ff000066 #ff000066', '#0000ffcc #00ff00cc'] }, + 1000 + ); + // R: 255 * (0.4 * 0.5) / 0.6 = 85 + // B: 255 * (0.8 * 0.5) / 0.6 = 170 + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgba(85, 0, 170, 0.6) rgba(85, 170, 0, 0.6)' }]); + }, `${property} supports animating as color pair of #RGBa`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['rgba(255, 0, 0, 0.4) rgba(255, 0, 0, 0.4)', 'rgba(0, 0, 255, 0.8) rgba(0, 255, 0, 0.8)'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 500, expected: 'rgba(85, 0, 170, 0.6) rgba(85, 170, 0, 0.6)' }]); + }, `${property} supports animating as color pair of rgba()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['hsla(0, 100%, 50%, 0.4) hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8) hsla(360, 100%, 50%, 0.8)'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 500, expected: 'rgba(85, 0, 170, 0.6) rgba(255, 0, 0, 0.6)' }]); + }, `${property} supports animating as color pair of hsla()`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128) rgb(0, 0, 0)'; + const animation = target.animate( + { + [idlName]: ['rgb(255, 0, 0) rgb(0, 0, 255)', 'rgb(0, 0, 255) rgb(255, 0, 0)'] + }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(255, 128, 128) rgb(0, 0, 255)' }, + { time: 500, expected: 'rgb(255, 128, 255) rgb(128, 0, 128)' }]); + }, `${property} supports animating as color pair of rgb() with overflowed ` + + ' from and to values'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128) rgb(0, 0, 0)'; + const animation = target.animate({ [idlName]: ['#ff0000 #0000ff', '#0000ff #ff0000'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(255, 128, 128) rgb(0, 0, 255)' }]); + }, `${property} supports animating as color pair of #RGB`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128) rgb(0, 0, 0)'; + const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%) hsl(0, 100%, 50%)', + 'hsl(240, 100%, 50%) hsl(360, 100%, 50%)'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(255, 128, 128) rgb(255, 0, 0)' }]); + }, `${property} supports animating as color pair of hsl()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128) rgb(0, 0, 0)'; + const animation = target.animate( + { [idlName]: ['#ff000066 #ff000066', '#0000ffcc #00ff00cc'] }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'rgb(230, 128, 128) rgb(102, 0, 0)' }]); + }, `${property} supports animating as color pair of #RGBa`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128) rgb(0, 0, 0)'; + const animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4) rgba(0, 255, 0, 0.4)', + 'rgba(0, 0, 255, 0.8) rgba(255, 0, 0, 0.8)'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 0, expected: 'rgb(230, 128, 128) rgb(0, 102, 0)' }]); + }, `${property} supports animating as color pair of rgba()`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(128, 128, 128) rgb(0, 0, 0)'; + const animation = target.animate( + { + [idlName]: ['hsla(0, 100%, 50%, 0.4) hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8) hsla(360, 100%, 50%, 0.8)'], + }, + { duration: 1000, composite } + ); + testAnimationSamples(animation, idlName, // Same as above. + [{ time: 0, expected: 'rgb(230, 128, 128) rgb(102, 0, 0)' }]); + }, `${property} supports animating as color pair of hsla()`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const transformListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['translate(200px, -200px)', 'translate(400px, 400px)'], + }, + 1000 + ); + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ 1, 0, 0, 1, 300, 100 ] }]); + }, `${property}: translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['rotate(45deg)', 'rotate(135deg)'], + }, + 1000 + ); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 0, 0] }]); + }, `${property}: rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['scale(3)', 'scale(5)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ 4, 0, 0, 4, 0, 0 ] }]); + }, `${property}: scale`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['skew(30deg, 60deg)', + 'skew(60deg, 30deg)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ 1, Math.tan(Math.PI / 4), + Math.tan(Math.PI / 4), 1, + 0, 0] }]); + }, `${property}: skew`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['translateX(100px) rotate(45deg)', + 'translateX(200px) rotate(135deg)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 150, 0 ] }]); + }, `${property}: rotate and translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['rotate(45deg) translateX(100px)', + 'rotate(135deg) translateX(200px)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 150 * Math.cos(Math.PI / 2), + 150 * Math.sin(Math.PI / 2) ] }]); + }, `${property}: translate and rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['rotate(0deg)', + 'rotate(1080deg) translateX(100px)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ -1, 0, 0, -1, -50, 0 ] }]); + }, `${property}: extend shorter list (from)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['rotate(0deg) translateX(100px)', + 'rotate(1080deg)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ -1, 0, 0, -1, -50, 0 ] }]); + }, `${property}: extend shorter list (to)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = // matrix(0, 1, -1, 0, 0, 100) + target.animate({ [idlName]: ['rotate(90deg) translateX(100px)', + // matrix(-1, 0, 0, -1, 200, 0) + 'translateX(200px) rotate(180deg)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ Math.cos(Math.PI * 3 / 4), + Math.sin(Math.PI * 3 / 4), + -Math.sin(Math.PI * 3 / 4), + Math.cos(Math.PI * 3 / 4), + 100, 50 ] }]); + }, `${property}: mismatch order of translate and rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = // Same matrices as above. + target.animate({ [idlName]: [ 'matrix(0, 1, -1, 0, 0, 100)', + 'matrix(-1, 0, 0, -1, 200, 0)' ] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ Math.cos(Math.PI * 3 / 4), + Math.sin(Math.PI * 3 / 4), + -Math.sin(Math.PI * 3 / 4), + Math.cos(Math.PI * 3 / 4), + 100, 50 ] }]); + }, `${property}: matrix`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, 0deg)', + 'rotate3d(1, 1, 0, 90deg)'] }, + 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI / 4) }]); + }, `${property}: rotate3d`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // To calculate expected matrices easily, generate input matrices from + // rotate3d. + const from = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); + const to = rotate3dToMatrix3d(1, 1, 0, Math.PI * 3 / 4); + const animation = target.animate({ [idlName]: [ from, to ] }, 1000); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI * 2 / 4) }]); + }, `${property}: matrix3d`); + + // This test aims for forcing the two mismatched transforms to be + // decomposed into matrix3d before interpolation. Therefore, we not only + // test the interpolation, but also test the 3D matrix decomposition. + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [ + 'scale(0.3)', + // scale(0.5) translateZ(1px) + 'matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)', + ], + }, + 1000 + ); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ 0.4, 0, 0, 0, + 0, 0.4, 0, 0, + 0, 0, 1, 0, + 0, 0, 0.5, 1] }]); + }, `${property}: mismatched 3D transforms`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['rotateY(60deg)', 'none' ] }, 1000); + + testAnimationSampleMatrices(animation, idlName, + // rotateY(30deg) == rotate3D(0, 1, 0, 30deg) + [{ time: 500, expected: rotate3dToMatrix(0, 1, 0, Math.PI / 6) }]); + }, `${property}: rotateY`); + + // Following tests aim for test the fallback discrete interpolation behavior + // for non-invertible matrices. The non-invertible matrix that we use is the + // singular matrix, matrix(1, 1, 0, 0, 0, 100). + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', + 'matrix( 1, 1, 0, 0, 0, 100)'] }, + { duration: 1000, fill: 'both' }); + + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ -1, 0, 0, -1, 200, 0 ] }, + { time: 499, expected: [ -1, 0, 0, -1, 200, 0 ] }, + { time: 500, expected: [ 1, 1, 0, 0, 0, 100 ] }, + { time: 1000, expected: [ 1, 1, 0, 0, 0, 100 ] }]); + }, `${property}: non-invertible matrices`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [ + // matrix(0, -1, 1, 0, 250, 0) + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + // matrix(-1, -1, 0, 0, 100, 100) + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', + ], + }, + { duration: 1000, fill: 'both' } + ); + + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] }, + { time: 499, expected: [ 0, -1, 1, 0, 250, 0 ] }, + { time: 500, expected: [ -1, -1, 0, 0, 100, 100 ] }, + { time: 1000, expected: [ -1, -1, 0, 0, 100, 100 ] }]); + }, `${property}: non-invertible matrices in matched transform lists`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: [ + // matrix(-2, 0, 0, -2, 250, 0) + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + // matrix(1, 1, 1, 1, 100, 100) + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) skew(45deg)', + ], + }, + { duration: 1000, fill: 'both' } + ); + + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] }, + { time: 499, expected: [ -2, 0, 0, -2, 250, 0 ] }, + { time: 500, expected: [ 1, 1, 1, 1, 100, 100 ] }, + { time: 1000, expected: [ 1, 1, 1, 1, 100, 100 ] }]); + }, `${property}: non-invertible matrices in mismatched transform lists`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + // perspective(0) is treated as perspective(1px) + [idlName]: ['perspective(0)', 'perspective(10px)'], + }, + 1000 + ); + testAnimationSampleMatrices(animation, idlName, + [{ time: 500, expected: [ 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, -0.55, + 0, 0, 0, 1 ] }]); + }, `${property}: perspective`); + + }, + + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'translateX(100px)'; + const animation = target.animate({ [idlName]: ['translateX(-200px)', + 'translateX(500px)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ 1, 0, 0, 1, -100, 0 ] }, + { time: 1000, expected: [ 1, 0, 0, 1, 600, 0 ] }]); + }, `${property}: translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate(45deg)'; + const animation = target.animate({ [idlName]: ['rotate(-90deg)', + 'rotate(90deg)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ Math.cos(-Math.PI / 4), + Math.sin(-Math.PI / 4), + -Math.sin(-Math.PI / 4), + Math.cos(-Math.PI / 4), + 0, 0] }, + { time: 1000, expected: [ Math.cos(Math.PI * 3 / 4), + Math.sin(Math.PI * 3 / 4), + -Math.sin(Math.PI * 3 / 4), + Math.cos(Math.PI * 3 / 4), + 0, 0] }]); + }, `${property}: rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'scale(2)'; + const animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ -6, 0, 0, -6, 0, 0 ] }, // scale(-3) scale(2) + { time: 1000, expected: [ 10, 0, 0, 10, 0, 0 ] }]); // scale(5) scale(2) + }, `${property}: scale`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(1, tan(10deg), tan(10deg), 1) + target.style[idlName] = 'skew(10deg, 10deg)'; + const animation = // matrix(1, tan(20deg), tan(-30deg), 1) + target.animate({ [idlName]: ['skew(-30deg, 20deg)', + // matrix(1, tan(-30deg), tan(20deg), 1) + 'skew(20deg, -30deg)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + // matrix at 0%. + // [ 1 tan(10deg) ] [ 1 tan(-30deg) ] + // [ tan(10deg) 1 ] [ tan(20deg) 1 ] = + // + // [ 1 + tan(10deg) * tan(20deg) tan(-30deg) + tan(10deg) ] + // [ tan(10deg) + tan(20deg) tan(10deg) * tan(-30deg) + 1 ] + + // matrix at 100%. + // [ 1 tan(10deg) ] [ 1 tan(20deg) ] + // [ tan(10deg) 1 ] [ tan(-30deg) 1 ] = + // + // [ 1 + tan(10deg) * tan(-30deg) tan(20deg) + tan(10deg) ] + // [ tan(10deg) + tan(-30deg) tan(10deg) * tan(20deg) + 1 ] + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 1 + Math.tan(Math.PI/18) * Math.tan(Math.PI/9), + Math.tan(Math.PI/18) + Math.tan(Math.PI/9), + Math.tan(-Math.PI/6) + Math.tan(Math.PI/18), + 1 + Math.tan(Math.PI/18) * Math.tan(-Math.PI/6), + 0, 0] }, + { time: 1000, expected: [ 1 + Math.tan(Math.PI/18) * Math.tan(-Math.PI/6), + Math.tan(Math.PI/18) + Math.tan(-Math.PI/6), + Math.tan(Math.PI/9) + Math.tan(Math.PI/18), + 1 + Math.tan(Math.PI/18) * Math.tan(Math.PI/9), + 0, 0] }]); + }, `${property}: skew`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(1, 0, 0, 1, 100, 0) + target.style[idlName] = 'translateX(100px)'; + const animation = // matrix(0, 1, -1, 0, 0, 0) + target.animate({ [idlName]: ['rotate(90deg)', + // matrix(-1, 0, 0, -1, 0, 0) + 'rotate(180deg)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, + { time: 1000, expected: [ -1, 0, 0, -1, 100, 0 ] }]); + }, `${property}: rotate on translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(0, 1, -1, 0, 0, 0) + target.style[idlName] = 'rotate(90deg)'; + const animation = // matrix(1, 0, 0, 1, 100, 0) + target.animate({ [idlName]: ['translateX(100px)', + // matrix(1, 0, 0, 1, 200, 0) + 'translateX(200px)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 0, 1, -1, 0, 0, 100 ] }, + { time: 1000, expected: [ 0, 1, -1, 0, 0, 200 ] }]); + }, `${property}: translate on rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate(45deg) translateX(100px)'; + const animation = target.animate({ [idlName]: ['rotate(-90deg)', + 'rotate(90deg)'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ Math.cos(-Math.PI / 4), + Math.sin(-Math.PI / 4), + -Math.sin(-Math.PI / 4), + Math.cos(-Math.PI / 4), + 100 * Math.cos(Math.PI / 4), + 100 * Math.sin(Math.PI / 4) ] }, + { time: 1000, expected: [ Math.cos(Math.PI * 3 / 4), + Math.sin(Math.PI * 3 / 4), + -Math.sin(Math.PI * 3 / 4), + Math.cos(Math.PI * 3 / 4), + 100 * Math.cos(Math.PI / 4), + 100 * Math.sin(Math.PI / 4) ] }]); + }, `${property}: rotate on rotate and translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'matrix(0, 1, -1, 0, 0, 0)'; + const animation = // Same matrices as above. + target.animate({ [idlName]: [ 'matrix(1, 0, 0, 1, 100, 0)', + 'matrix(1, 0, 0, 1, 200, 0)' ] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 0, 1, -1, 0, 0, 100 ] }, + { time: 1000, expected: [ 0, 1, -1, 0, 0, 200 ] }]); + }, `${property}: matrix`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate3d(1, 1, 0, 45deg)'; + const animation = + target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, -90deg)', + 'rotate3d(1, 1, 0, 90deg)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, + { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); + }, `${property}: rotate3d`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // To calculate expected matrices easily, generate input matrices from + // rotate3d. + target.style[idlName] = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); + const from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2); + const to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2); + const animation = + target.animate({ [idlName]: [ from, to ] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, + { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); + }, `${property}: matrix3d`); + + // Following tests aim for test the addition behavior for non-invertible + // matrices. Note that the addition for non-invertible matrices should be + // the same, just like addition for invertible matrices. With these tests, + // we can assure that addition never behaves as discrete. The non-invertible + // matrix that we use is the singular matrix, matrix(1, 1, 0, 0, 0, 100). + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'translateX(50px)'; + const animation = + target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', + 'matrix( 1, 1, 0, 0, 0, 100)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ -1, 0, 0, -1, 250, 0 ] }, + { time: 1000, expected: [ 1, 1, 0, 0, 50, 100 ] }]); + }, `${property}: non-invertible matrices`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'translateX(50px)'; + const animation = // matrix(0, -1, 1, 0, 200, 0) + target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + // matrix(-1, -1, 0, 0, 0, 100) + 'matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] }, + { time: 1000, expected: [ -1, -1, 0, 0, 50, 100 ] }]); + }, `${property}: non-invertible matrices in matched transform lists`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'translateX(50px)'; + const animation = // matrix(-2, 0, 0, -2, 200, 0) + target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0) scale(2)', + // matrix(1, 1, 1, 1, 0, 100) + 'matrix( 1, 1, 0, 0, 0, 100) skew(45deg)'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] }, + { time: 1000, expected: [ 1, 1, 1, 1, 50, 100 ] }]); + }, `${property}: non-invertible matrices in mismatched transform lists`); + }, + + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'translateX(100px)'; + const animation = target.animate({ [idlName]: ['translateX(-200px)', + 'translateX(500px)'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + testAnimationSampleMatrices(animation, idlName, + [ { time: 0, expected: [ 1, 0, 0, 1, -100, 0 ] }, + { time: 1000, expected: [ 1, 0, 0, 1, 600, 0 ] }]); + }, `${property}: translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate(45deg)'; + const animation = target.animate({ [idlName]: ['rotate(-90deg)', + 'rotate(90deg)'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ Math.cos(-Math.PI / 4), + Math.sin(-Math.PI / 4), + -Math.sin(-Math.PI / 4), + Math.cos(-Math.PI / 4), + 0, 0] }, + { time: 1000, expected: [ Math.cos(Math.PI * 3 / 4), + Math.sin(Math.PI * 3 / 4), + -Math.sin(Math.PI * 3 / 4), + Math.cos(Math.PI * 3 / 4), + 0, 0] }]); + }, `${property}: rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'scale(2)'; + const animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + // scale((2 - 1) + (-3 - 1) + 1) + [{ time: 0, expected: [ -2, 0, 0, -2, 0, 0 ] }, + // scale((2 - 1) + (5 - 1) + 1) + { time: 1000, expected: [ 6, 0, 0, 6, 0, 0 ] }]); + }, `${property}: scale`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(1, tan(10deg), tan(10deg), 1) + target.style[idlName] = 'skew(10deg, 10deg)'; + const animation = // matrix(1, tan(20deg), tan(-30deg), 1) + target.animate({ [idlName]: ['skew(-30deg, 20deg)', + // matrix(1, tan(-30deg), tan(20deg), 1) + 'skew(20deg, -30deg)'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 1, Math.tan(Math.PI/6), + Math.tan(-Math.PI/9), 1, + 0, 0] }, + { time: 1000, expected: [ 1, Math.tan(-Math.PI/9), + Math.tan(Math.PI/6), 1, + 0, 0] }]); + }, `${property}: skew`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(1, 0, 0, 1, 100, 0) + target.style[idlName] = 'translateX(100px)'; + const animation = // matrix(0, 1, -1, 0, 0, 0) + target.animate({ [idlName]: ['rotate(90deg)', + // matrix(-1, 0, 0, -1, 0, 0) + 'rotate(180deg)'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, + { time: 1000, expected: [ -1, 0, 0, -1, 100, 0 ] }]); + }, `${property}: rotate on translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(0, 1, -1, 0, 0, 0) + target.style[idlName] = 'rotate(90deg)'; + const animation = // matrix(1, 0, 0, 1, 100, 0) + target.animate({ [idlName]: ['translateX(100px)', + // matrix(1, 0, 0, 1, 200, 0) + 'translateX(200px)'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, + { time: 1000, expected: [ 0, 1, -1, 0, 200, 0 ] }]); + }, `${property}: translate on rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate(45deg)'; + const animation = + target.animate({ [idlName]: ['rotate(45deg) translateX(0px)', + 'rotate(45deg) translateX(100px)'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 0 * Math.cos(Math.PI / 2), + 0 * Math.sin(Math.PI / 2) ] }, + { time: 1000, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 100 * Math.cos(Math.PI / 2), + 100 * Math.sin(Math.PI / 2) ] }]); + }, `${property}: rotate and translate on rotate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate(45deg) translateX(100px)'; + const animation = + target.animate({ [idlName]: ['rotate(45deg)', 'rotate(45deg)'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 100 * Math.cos(Math.PI / 2), + 100 * Math.sin(Math.PI / 2) ] }, + { time: 1000, expected: [ Math.cos(Math.PI / 2), + Math.sin(Math.PI / 2), + -Math.sin(Math.PI / 2), + Math.cos(Math.PI / 2), + 100 * Math.cos(Math.PI / 2), + 100 * Math.sin(Math.PI / 2) ] }]); + }, `${property}: rotate on rotate and translate`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'matrix(0, 1, -1, 0, 0, 0)'; + const animation = // Same matrices as above. + target.animate({ [idlName]: [ 'matrix(1, 0, 0, 1, 100, 0)', + 'matrix(1, 0, 0, 1, 200, 0)' ] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] }, + { time: 1000, expected: [ 0, 1, -1, 0, 200, 0 ] }]); + }, `${property}: matrix`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rotate3d(1, 1, 0, 45deg)'; + const animation = + target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, -90deg)', + 'rotate3d(1, 1, 0, 90deg)'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, + { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); + }, `${property}: rotate3d`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // To calculate expected matrices easily, generate input matrices from + // rotate3d. + target.style[idlName] = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4); + const from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2); + const to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2); + const animation = + target.animate({ [idlName]: [ from, to ] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) }, + { time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]); + }, `${property}: matrix3d`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const matrixArray = [ 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 1, 1 ]; + + target.style[idlName] = createMatrixFromArray(matrixArray); + const animation = + target.animate({ [idlName]: [ 'none', 'none' ] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleMatrices(animation, idlName, + [{ time: 0, expected: matrixArray }, + { time: 1000, expected: matrixArray }]); + }, `${property}: none`); + + // Following tests aim for test the fallback discrete accumulation behavior + // for non-invertible matrices. The non-invertible matrix that we use is the + // singular matrix, matrix(1, 1, 0, 0, 0, 100). + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)', + 'matrix(-1, 0, 0, -1, 200, 0)'] }, 1000); + const animation = target.animate( + { + [idlName]: [ + 'matrix( 1, 1, 0, 0, 0, 100)', + 'matrix( 1, 1, 0, 0, 0, 100)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [1, 1, 0, 0, 0, 100] }, + ]); + }, `${property}: non-invertible matrices (non-invertible onto invertible)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.animate({ [idlName]: ['matrix( 1, 1, 0, 0, 0, 100)', + 'matrix( 1, 1, 0, 0, 0, 100)'] }, 1000); + const animation = target.animate( + { + [idlName]: [ + 'matrix(-1, 0, 0, -1, 200, 0)', + 'matrix(-1, 0, 0, -1, 200, 0)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [-1, 0, 0, -1, 200, 0] }, + ]); + }, `${property}: non-invertible matrices (invertible onto non-invertible)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(0, -1, 1, 0, 250, 0) + target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + ], + }, + 1000 + ); + // matrix(-1, -1, 0, 0, 100, 100) + const animation = target.animate( + { + [idlName]: [ + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', + 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [-1, -1, 0, 0, 100, 100] }, + ]); + }, `${property}: non-invertible matrices in matched transform lists (non-invertible onto invertible)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(-1, -1, 0, 0, 100, 100) + target.animate( + { + [idlName]: [ + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)', + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)', + ], + }, + 1000 + ); + // matrix(0, -1, 1, 0, 250, 0) + const animation = target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [0, -1, 1, 0, 250, 0] }, + ]); + }, `${property}: non-invertible matrices in matched transform lists (invertible onto non-invertible)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(-2, 0, 0, -2, 250, 0) + target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + ], + }, + 1000 + ); + // matrix(1, 1, 1, 1, 100, 100) + const animation = target.animate( + { + [idlName]: [ + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [1, 1, 1, 1, 100, 100] }, + ]); + }, `${property}: non-invertible matrices in mismatched transform lists` + + ' (non-invertible onto invertible)'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // matrix(1, 1, 1, 1, 100, 100) + target.animate( + { + [idlName]: [ + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)', + ], + }, + 1000 + ); + // matrix(-2, 0, 0, -2, 250, 0) + const animation = target.animate( + { + [idlName]: [ + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + testAnimationSampleMatrices(animation, idlName, [ + { time: 0, expected: [-2, 0, 0, -2, 250, 0] }, + ]); + }, `${property}: non-invertible matrices in mismatched transform lists` + + ' (invertible onto non-invertible)'); + }, +}; + +const rotateListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['45deg', '135deg'], + }, + 1000 + ); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '90deg' }]); + }, `${property} without rotation axes`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ '0 1 0 0deg', + '0 1 0 90deg'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'y 45deg' }]); + }, `${property} with rotation axes`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + + const animation = + target.animate({ [idlName]: [ '0 1 0 0deg', + '0 1 0 720deg'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 250, expected: 'y 180deg' }]); + }, `${property} with rotation axes and range over 360 degrees`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ '0 1 0 0deg', + '0 1 1 90deg'] }, + 1000); + + testAnimationSampleRotate3d(animation, idlName, + [{ time: 500, expected: '0 0.707107 0.707107 45deg' }]); + }, `${property} with different rotation axes`); + }, + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '45deg'; + const animation = target.animate({ [idlName]: ['-90deg', '90deg'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-45deg' }, + { time: 1000, expected: '135deg' }]); + }, `${property} without rotation axes`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + // Rotation specified in transform property should not affect the computed + // value of |property|. + target.style.transform = 'rotate(20deg)'; + target.style[idlName] = 'y -45deg'; + const animation = + target.animate({ [idlName]: ['0 1 0 90deg', + '0 1 0 180deg'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'y 45deg' }, + { time: 1000, expected: 'y 135deg' }]); + }, `${property} with underlying transform`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ '0 1 0 0deg', + '1 1 1 270deg'] }, + { duration: 1000, fill: 'both', composite: 'add' }); + + testAnimationSampleRotate3d(animation, idlName, + [{ time: 500, expected: '0.57735 0.57735 0.57735 135deg' }]); + }, `${property} with different rotation axes`); + }, + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '45deg'; + const animation = target.animate({ [idlName]: ['-90deg', '90deg'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-45deg' }, + { time: 1000, expected: '135deg' }]); + }, `${property} without rotation axes`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style.transform = 'translateX(100px)'; + target.style[idlName] = '1 0 0 -45deg'; + const animation = + target.animate({ [idlName]: ['1 0 0 90deg', + '1 0 0 180deg'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: 'x 45deg' }, + { time: 1000, expected: 'x 135deg' }]); + }, `${property} with underlying transform`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ '0 1 0 0deg', + '1 0 1 180deg'] }, + { duration: 1000, fill: 'both', composite: 'accumulate' }); + + testAnimationSampleRotate3d(animation, idlName, + [{ time: 500, expected: '0.707107 0 0.707107 90deg' }]); + }, `${property} with different rotation axes`); + }, +}; + +const translateListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['200px', '400px'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '300px' }]); + }, `${property} with two unspecified values`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['200px -200px', '400px 400px'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '300px 100px' }]); + }, `${property} with one unspecified value`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['200px -200px 600px', '400px 400px -200px'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '300px 100px 200px' }]); + }, `${property} with all three values specified`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { + [idlName]: ['0% -101px 600px', '400px 50% -200px'], + }, + 1000 + ); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'calc(0% + 200px) calc(25% - 50.5px) 200px' }]); + }, `${property} with combination of percentages and lengths`); + }, + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '100px'; + const animation = target.animate({ [idlName]: ['-200px', '500px'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: '-100px' }, + { time: 1000, expected: '600px' }]); + + }, `${property}`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.transform = 'translateY(100px)'; + target.style[idlName] = '100px'; + const animation = target.animate({ [idlName]: ['-200px', '500px'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: '-100px' }, + { time: 1000, expected: '600px' }]); + + }, `${property} with underlying transform`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '50%'; + const animation = target.animate({ [idlName]: ['-200px', '500px'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'calc(50% - 200px)' }, + { time: 1000, expected: 'calc(50% + 500px)' }]); + + }, `${property} with underlying percentage value`); + }, + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '100px'; + const animation = target.animate({ [idlName]: ['-200px', '500px'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: '-100px' }, + { time: 1000, expected: '600px' }]); + }, `${property}`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.transform = 'translateY(100px)'; + target.style[idlName] = '100px'; + const animation = target.animate({ [idlName]: ['-200px', '500px'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: '-100px' }, + { time: 1000, expected: '600px' }]); + }, `${property} with transform`); + }, +}; + +const scaleListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['3', '5'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '4' }]); + }, `${property} with two unspecified values`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['3 3', '5 5'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '4' }]); + }, `${property} with one unspecified value`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['3 3 3', '5 5 5'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: '4 4 4' }]); + }, `${property}`); + }, + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2'; + const animation = target.animate({ [idlName]: ['-3', '5'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-6' }, + { time: 1000, expected: '10' }]); + }, `${property} with two unspecified values`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2 2'; + const animation = target.animate({ [idlName]: ['-3 -3', '5 5'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-6' }, + { time: 1000, expected: '10' }]); + }, `${property} with one unspecified value`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2 2 2'; + const animation = target.animate({ [idlName]: ['-1 -2 -3', '4 5 6'] }, + { duration: 1000, fill: 'both', + composite: 'add' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-2 -4 -6' }, + { time: 1000, expected: '8 10 12' }]); + }, `${property}`); + }, + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2'; + const animation = target.animate({ [idlName]: ['-3', '5'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-2' }, + { time: 1000, expected: '6' }]); + }, `${property} with two unspecified values`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2 2'; + const animation = target.animate({ [idlName]: ['-3 -3', '5 5'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '-2' }, + { time: 1000, expected: '6' }]); + }, `${property} with one unspecified value`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '2 2 2'; + const animation = target.animate({ [idlName]: ['-1 -2 -3', '4 5 6'] }, + { duration: 1000, fill: 'both', + composite: 'accumulate' }); + + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '0 -1 -2' }, + { time: 1000, expected: '5 6 7' }]); + }, `${property}`); + }, +}; + +const filterListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['blur(10px)', 'blur(50px)'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'blur(30px)' }]); + }, `${property}: blur function`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hue-rotate(0deg)', + 'hue-rotate(100deg)'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'hue-rotate(50deg)' }]); + }, `${property}: hue-rotate function with same unit(deg)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['hue-rotate(10deg)', + 'hue-rotate(100rad)'] }, + 1000); + + // 10deg = 0.1745rad. + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'hue-rotate(2869.79deg)' }]); + }, `${property}: hue-rotate function with different unit(deg -> rad)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + ['drop-shadow(10px 10px 10px rgba(255, 0, 0, 0.4))', + 'drop-shadow(50px 50px 50px rgba(0, 0, 255, 0.8))'] }, + 1000); + + testAnimationSamples( + animation, idlName, + [{ time: 500, + expected: 'drop-shadow(rgba(85, 0, 170, 0.6) 30px 30px 30px)' }]); + }, `${property}: drop-shadow function`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + ['brightness(0.1) contrast(0.1) grayscale(0.1) invert(0.1) ' + + 'opacity(0.1) saturate(0.1) sepia(0.1)', + 'brightness(0.5) contrast(0.5) grayscale(0.5) invert(0.5) ' + + 'opacity(0.5) saturate(0.5) sepia(0.5)'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, + expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' + + 'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]); + }, `${property}: percentage or numeric-specifiable functions` + + ' (number value)'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + ['brightness(10%) contrast(10%) grayscale(10%) invert(10%) ' + + 'opacity(10%) saturate(10%) sepia(10%)', + 'brightness(50%) contrast(50%) grayscale(50%) invert(50%) ' + + 'opacity(50%) saturate(50%) sepia(50%)'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, + expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' + + 'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]); + }, `${property}: percentage or numeric-specifiable functions` + + ' (percentage value)'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + // To make missing filter-function-lists, specified the grayscale. + ['grayscale(0)', + 'grayscale(1) brightness(0) contrast(0) opacity(0) saturate(0)' ]}, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, + expected: 'grayscale(0.5) brightness(0.5) contrast(0.5) ' + + 'opacity(0.5) saturate(0.5)' }]); + }, `${property}: interpolate different length of filter-function-list` + + ' with function which lacuna value is 1'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + // To make missing filter-function-lists, specified the opacity. + ['opacity(1)', + 'opacity(0) grayscale(1) invert(1) sepia(1) blur(10px)'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, + expected: + 'opacity(0.5) grayscale(0.5) invert(0.5) sepia(0.5) blur(5px)' }]); + }, `${property}: interpolate different length of filter-function-list` + + ' with function which lacuna value is 0'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + ['blur(0px)', + 'blur(10px) drop-shadow(10px 10px 10px rgba(0, 0, 255, 0.8))'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, + // Per the spec: The initial value for interpolation is all length values + // set to 0 and the used color set to transparent. + expected: 'blur(5px) drop-shadow(rgba(0, 0, 255, 0.4) 5px 5px 5px)' }]); + }, `${property}: interpolate different length of filter-function-list` + + ' with drop-shadow function'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['none', 'blur(10px)'] }, + 1000); + + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'blur(5px)' }]); + }, `${property}: interpolate from none`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate( + { [idlName]: + ['blur(0px) url(\"#f1\")', + 'blur(10px) url(\"#f2\")']}, + 1000); + testAnimationSamples(animation, idlName, + [{ time: 499, expected: 'blur(0px) url(\"#f1\")' }, + { time: 500, expected: 'blur(10px) url(\"#f2\")' }]); + }, `${property}: url function (interpoalte as discrete)`); + }, + + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'blur(10px)'; + const animation = target.animate({ [idlName]: ['blur(20px)', + 'blur(50px)'] }, + { duration: 1000, composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'blur(10px) blur(20px)' }]); + }, `${property}: blur on blur`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'blur(10px)'; + const animation = target.animate({ [idlName]: ['brightness(80%)', + 'brightness(40%)'] }, + { duration: 1000, composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'blur(10px) brightness(0.8)' }]); + }, `${property}: different filter functions`); + }, + + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'blur(10px) brightness(0.3)'; + const animation = target.animate( + { + [idlName]: [ + 'blur(20px) brightness(0.1)', + 'blur(20px) brightness(0.1)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + // brightness(0.1) onto brightness(0.3) means + // brightness((0.1 - 1.0) + (0.3 - 1.0) + 1.0). The result of this formula + // is brightness(-0.6) that means brightness(0.0). + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'blur(30px) brightness(0)' }]); + }, `${property}: same ordered filter functions`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'blur(10px) brightness(1.3)'; + const animation = target.animate( + { + [idlName]: [ + 'brightness(1.2) blur(20px)', + 'brightness(1.2) blur(20px)', + ], + }, + { duration: 1000, composite: 'accumulate' } + ); + // Mismatched ordered functions can't be accumulated. + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'brightness(1.2) blur(20px)' }]); + }, `${property}: mismatched ordered filter functions`); + }, +}; + +const textShadowListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'none', + 'rgb(100, 100, 100) 10px 10px 10px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + // Premultiplied + [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); + }, `${property}: from none to other`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px', + 'none' ] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + // Premultiplied + [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); + }, `${property}: from other to none`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px', + 'rgb(100, 100, 100) 10px 10px 10px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px' }]); + }, `${property}: single shadow`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px, ' + + 'rgb(200, 200, 200) 20px 20px 20px', + 'rgb(100, 100, 100) 10px 10px 10px, ' + + 'rgb(100, 100, 100) 10px 10px 10px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px, ' + + 'rgb(150, 150, 150) 15px 15px 15px' }]); + }, `${property}: shadow list`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(200, 200, 200) 20px 20px 20px', + 'rgb(100, 100, 100) 10px 10px 10px, ' + + 'rgb(100, 100, 100) 10px 10px 10px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, ' + + 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); + }, `${property}: mismatched list length (from longer to shorter)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px, ' + + 'rgb(100, 100, 100) 10px 10px 10px', + 'rgb(200, 200, 200) 20px 20px 20px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, ' + + 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]); + }, `${property}: mismatched list length (from shorter to longer)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style.color = 'rgb(0, 255, 0)'; + const animation = + target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px', + 'currentcolor 10px 10px 10px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px' }]); + }, `${property}: with currentcolor`); + }, + + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(0, 0, 0) 0px 0px 0px'; + const animation = + target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px', + 'rgb(120, 120, 120) 10px 10px 10px'] }, + { duration: 1000, composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'rgb(0, 0, 0) 0px 0px 0px, ' + + 'rgb(120, 120, 120) 10px 10px 10px' }]); + }, `${property}: shadow`); + }, + + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(120, 120, 120) 10px 10px 10px'; + const animation = + target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px', + 'rgb(120, 120, 120) 10px 10px 10px'] }, + { duration: 1000, composite: 'accumulate' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'rgb(240, 240, 240) 20px 20px 20px' }]); + }, `${property}: shadow`); + }, +}; + + +const boxShadowListType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'none', + 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + // Premultiplied + [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); + }, `${property}: from none to other`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px 0px', + 'none' ] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + // Premultiplied + [{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); + }, `${property}: from other to none`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px 0px', + 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px 0px' }]); + }, `${property}: single shadow`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px 0px, ' + + 'rgb(200, 200, 200) 20px 20px 20px 20px', + 'rgb(100, 100, 100) 10px 10px 10px 0px, ' + + 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px 0px, ' + + 'rgb(150, 150, 150) 15px 15px 15px 10px' }]); + }, `${property}: shadow list`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(200, 200, 200) 20px 20px 20px 20px', + 'rgb(100, 100, 100) 10px 10px 10px 0px, ' + + 'rgb(100, 100, 100) 10px 10px 10px 0px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, ' + + 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); + }, `${property}: mismatched list length (from shorter to longer)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px 0px, ' + + 'rgb(100, 100, 100) 10px 10px 10px 0px', + 'rgb(200, 200, 200) 20px 20px 20px 20px']}, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, ' + + 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]); + }, `${property}: mismatched list length (from longer to shorter)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style.color = 'rgb(0, 255, 0)'; + const animation = + target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px 0px', + 'currentcolor 10px 10px 10px 10px'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px 5px' }]); + }, `${property}: with currentcolor`); + }, + + testAddition: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(0, 0, 0) 0px 0px 0px 0px'; + const animation = + target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px 0px', + 'rgb(120, 120, 120) 10px 10px 10px 0px'] }, + { duration: 1000, composite: 'add' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'rgb(0, 0, 0) 0px 0px 0px 0px, ' + + 'rgb(120, 120, 120) 10px 10px 10px 0px' }]); + }, `${property}: shadow`); + }, + + testAccumulation: function(property, setup) { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rgb(120, 120, 120) 10px 10px 10px 10px'; + const animation = + target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px 10px', + 'rgb(120, 120, 120) 10px 10px 10px 10px'] }, + { duration: 1000, composite: 'accumulate' }); + testAnimationSamples(animation, idlName, + [ { time: 0, expected: 'rgb(240, 240, 240) 20px 20px 20px 20px' }]); + }, `${property}: shadow`); + }, +}; + +const positionType = { + testInterpolation: (property, setup) => { + lengthPairType.testInterpolation(property, setup); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: ['10% 10%', '50% 50%'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples( + animation, idlName, + [{ time: 500, expected: calcFromPercentage(idlName, '30% 30%') }]); + }, `${property} supports animating as a position of percent`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + lengthPairType.testAddition(property, setup); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '60% 60%'; + const animation = target.animate({ [idlName]: ['70% 70%', '100% 100%'] }, + { duration: 1000, composite }); + testAnimationSamples( + animation, idlName, + [{ time: 0, expected: calcFromPercentage(idlName, '130% 130%') }]); + }, `${property}: position of percentage`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +}; + +const rectType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['rect(10px, 10px, 10px, 10px)', + 'rect(50px, 50px, 50px, 50px)'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples( + animation, idlName, + [{ time: 500, expected: 'rect(30px, 30px, 30px, 30px)' }]); + }, `${property} supports animating as a rect`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = 'rect(100px, 100px, 100px, 100px)'; + const animation = target.animate({ [idlName]: + ['rect(10px, 10px, 10px, 10px)', + 'rect(10px, 10px, 10px, 10px)'] }, + { duration: 1000, composite }); + testAnimationSamples( + animation, idlName, + [{ time: 0, expected: 'rect(110px, 110px, 110px, 110px)' }]); + }, `${property}: rect`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +} + +// stroke-dasharray: none | [ | | ]* +const dasharrayType = { + testInterpolation: (property, setup) => { + percentageType.testInterpolation(property, setup); + positiveNumberType.testInterpolation(property, setup, 'px'); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['8, 16, 4', + '4, 8, 12, 16'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples( + animation, idlName, + [{ time: 500, expected: '6px, 12px, 8px, 12px, 10px, 6px, 10px, 16px, 4px, 8px, 14px, 10px' }]); + }, `${property} supports animating as a dasharray (mismatched length)`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = target.animate({ [idlName]: + ['2, 50%, 6, 10', + '6, 30%, 2, 2'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples( + animation, idlName, + [{ time: 500, expected: '4px, 40%, 4px, 6px' }]); + }, `${property} supports animating as a dasharray (mixed lengths and percentages)`); + + }, + + // Note that stroke-dasharray is neither additive nor cumulative, so we should + // write this additive test case that animating value replaces underlying + // values. + // See https://www.w3.org/TR/SVG2/painting.html#StrokeDashing. + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '6, 30%, 2px'; + const animation = target.animate({ [idlName]: + ['1, 2, 3, 4, 5', + '6, 7, 8, 9, 10'] }, + { duration: 1000, composite }); + testAnimationSamples( + animation, idlName, + [{ time: 0, expected: '1px, 2px, 3px, 4px, 5px' }]); + }, `${property}: dasharray`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +} + +const fontVariationSettingsType = { + testInterpolation: (property, setup) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['"wght" 1.1', '"wght" 1.5'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamples(animation, idlName, + [{ time: 0, expected: '"wght" 1.1' }, + { time: 250, expected: '"wght" 1.2' }, + { time: 750, expected: '"wght" 1.4' } ]); + }, `${property} supports animation as float`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['"wdth" 1, "wght" 1.1', + '"wght" 1.5, "wdth" 5'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamplesWithAnyOrder( + animation, idlName, + [{ time: 0, expected: '"wdth" 1, "wght" 1.1' }, + { time: 250, expected: '"wdth" 2, "wght" 1.2' }, + { time: 750, expected: '"wdth" 4, "wght" 1.4' } ]); + }, `${property} supports animation as float with multiple tags`); + + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + const animation = + target.animate({ [idlName]: ['"wdth" 1, "wght" 1.1', + '"wght" 10, "wdth" 5, "wght" 1.5'] }, + { duration: 1000, fill: 'both' }); + testAnimationSamplesWithAnyOrder( + animation, idlName, + [{ time: 250, expected: '"wdth" 2, "wght" 1.2' }, + { time: 750, expected: '"wdth" 4, "wght" 1.4' } ]); + }, `${property} supports animation as float with multiple duplicate tags`); + }, + + testAdditionOrAccumulation: (property, setup, composite) => { + test(t => { + const idlName = propertyToIDL(property); + const target = createTestElement(t, setup); + target.style[idlName] = '"wght" 1'; + const animation = + target.animate({ [idlName]: ['"wght" 1.1', '"wght" 1.5'] }, + { duration: 1000, composite }); + testAnimationSamples(animation, idlName, + [{ time: 250, expected: '"wght" 2.2' }, + { time: 750, expected: '"wght" 2.4' } ]); + }, `${property} with composite type ${composite}`); + }, + + testAddition: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'add'); + }, + + testAccumulation: function(property, setup) { + this.testAdditionOrAccumulation(property, setup, 'accumulate'); + }, +} + +const types = { + color: colorType, + colorPair: colorPairType, + discrete: discreteType, + filterList: filterListType, + integer: integerType, + positiveInteger: positiveIntegerType, + length: lengthType, + percentage: percentageType, + lengthPercentageOrCalc: lengthPercentageOrCalcType, + lengthPair: lengthPairType, + positiveNumber: positiveNumberType, + opacity: opacityType, + transformList: transformListType, + rotateList: rotateListType, + translateList: translateListType, + scaleList: scaleListType, + visibility: visibilityType, + boxShadowList: boxShadowListType, + textShadowList: textShadowListType, + rect: rectType, + position: positionType, + dasharray: dasharrayType, + fontVariationSettings: fontVariationSettingsType, +}; diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/property-utils.js b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-utils.js new file mode 100644 index 0000000000..d3a7b12a61 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-utils.js @@ -0,0 +1,38 @@ +'use strict'; + +function runAnimationTypeTest(gCSSProperties, testType) { + for (const property in gCSSProperties) { + if (!isSupported(property)) { + continue; + } + + const setupFunction = gCSSProperties[property].setup; + for (const animationType of gCSSProperties[property].types) { + let typeObject; + let animationTypeString; + if (typeof animationType === 'string') { + typeObject = types[animationType]; + animationTypeString = animationType; + } else if (typeof animationType === 'object' && + animationType.type && typeof animationType.type === 'string') { + typeObject = types[animationType.type]; + animationTypeString = animationType.type; + } + + // First, test that the animation type object has 'testAccumulation', or + // 'testAddition', or 'testInterpolation'. + // We use test() function here so that we can continue the remainder tests + // even if this test fails. + test(t => { + assert_own_property(typeObject, testType, animationTypeString + + ` should have ${testType} property`); + assert_equals(typeof typeObject[testType], 'function', + `${testType} method should be a function`); + }, `${property} (type: ${animationTypeString}) has ${testType} function`); + + if (typeObject[testType] && typeof typeObject[testType] === 'function') { + typeObject[testType](property, setupFunction, animationType.options); + } + } + } +} diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html new file mode 100644 index 0000000000..bc02dd00b9 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/scrollbar-interpolation.html @@ -0,0 +1,91 @@ + + + + + + +Scrollbar interpolation + + + + + + +
+
+
+ + + + diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/visibility.html b/testing/web-platform/tests/web-animations/animation-model/animation-types/visibility.html new file mode 100644 index 0000000000..f5a60b4e2c --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/visibility.html @@ -0,0 +1,57 @@ + + +Animation type for the 'visibility' property + + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-interpolated-transform.html b/testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-interpolated-transform.html new file mode 100644 index 0000000000..c101b5f0cf --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-interpolated-transform.html @@ -0,0 +1,87 @@ + + + apply interpolated transform on multiple keyframes + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-the-composited-result.html b/testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-the-composited-result.html new file mode 100644 index 0000000000..336115e577 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/combining-effects/applying-the-composited-result.html @@ -0,0 +1,29 @@ + + +Applying the composited result + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/combining-effects/effect-composition.html b/testing/web-platform/tests/web-animations/animation-model/combining-effects/effect-composition.html new file mode 100644 index 0000000000..70a8cdd92c --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/combining-effects/effect-composition.html @@ -0,0 +1,154 @@ + + +Effect composition + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/computed-keyframes-shorthands.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/computed-keyframes-shorthands.html new file mode 100644 index 0000000000..ff62a23bce --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/computed-keyframes-shorthands.html @@ -0,0 +1,30 @@ + + +Calculating computed keyframes: Shorthand properties + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-in-removed-iframe-crash.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-in-removed-iframe-crash.html new file mode 100644 index 0000000000..209ede786f --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-in-removed-iframe-crash.html @@ -0,0 +1,22 @@ + + + + + + Querying keyframes for an effect in a removed iframe should not crash + + + + +
+ + + + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html new file mode 100644 index 0000000000..2948d6b66e --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-on-marquee-parent-crash.html @@ -0,0 +1,21 @@ + +Animating marquee's parent inside display:none + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html new file mode 100644 index 0000000000..fcb7f13126 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html @@ -0,0 +1,377 @@ + + +The effect value of a keyframe effect: Forwards-filling animations whose + values depend on their context (target element) + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html new file mode 100644 index 0000000000..3730a02098 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-context.html @@ -0,0 +1,105 @@ + + +The effect value of a keyframe effect: Property values that depend on + their context (target element) + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html new file mode 100644 index 0000000000..6bf5d8cd46 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html @@ -0,0 +1,36 @@ + + +The effect value of a keyframe effect: Calculating the interval + distance between keyframes + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html new file mode 100644 index 0000000000..abfda86f4d --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html @@ -0,0 +1,824 @@ + + +The effect value of a keyframe effect: Applying the iteration composite + operation + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root-ref.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root-ref.html new file mode 100644 index 0000000000..792ca214cf --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root-ref.html @@ -0,0 +1,9 @@ + + +
diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root.html new file mode 100644 index 0000000000..43e229856b --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-in-shadow-root.html @@ -0,0 +1,26 @@ + + + + +The effect value of consecutive animations targeting 'opacity' in a shadow root + + + + + + + + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-ref.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-ref.html new file mode 100644 index 0000000000..792ca214cf --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect-ref.html @@ -0,0 +1,9 @@ + + +
diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect.html new file mode 100644 index 0000000000..bef3bd3e8d --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-opacity-replaced-effect.html @@ -0,0 +1,32 @@ + + + + +The effect value of consecutive animations targeting 'opacity' + + + + + +
+ + + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html new file mode 100644 index 0000000000..a2a0683921 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html @@ -0,0 +1,77 @@ + + +The effect value of a keyframe effect: Overlapping keyframes + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-replaced-animations.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-replaced-animations.html new file mode 100644 index 0000000000..d40a01fdd2 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-replaced-animations.html @@ -0,0 +1,161 @@ + + +The effect value of a keyframe effect: Overlapping keyframes + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html new file mode 100644 index 0000000000..a33d6d4f24 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html @@ -0,0 +1,84 @@ + + +The effect value of a keyframe effect: Calculating the transformed + distance between keyframes + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/keyframe-exceptions.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/keyframe-exceptions.html new file mode 100644 index 0000000000..4cb4be76a8 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/keyframe-exceptions.html @@ -0,0 +1,39 @@ + + + + + + + + +Keyframes with invalid offsets + + diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001-ref.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001-ref.html new file mode 100644 index 0000000000..1e7f250c48 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001-ref.html @@ -0,0 +1,14 @@ + + +CSS Test (Animations): Element.animate() animating both transform and opacity on an inline + + + + + +x diff --git a/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001.html b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001.html new file mode 100644 index 0000000000..f76b53cd4c --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001.html @@ -0,0 +1,27 @@ + + +CSS Test (Animations): Element.animate() animating both transform and opacity on an inline + + + + + + + +x diff --git a/testing/web-platform/tests/web-animations/animation-model/resources/side-effects-common.js b/testing/web-platform/tests/web-animations/animation-model/resources/side-effects-common.js new file mode 100644 index 0000000000..2f6531d4fc --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/resources/side-effects-common.js @@ -0,0 +1,81 @@ +'use strict'; + +const PROPERTY_OPACITY = 0; +const PROPERTY_TRANSFORM = 1; +const PROPERTY_BGCOLOR = 2; + +const PHASE_BEFORE = 10; +const PHASE_ACTIVE = 11; +const PHASE_AFTER = 12; + +const STATE_CURRENT = 100; +const STATE_IN_EFFECT = 101; +const STATE_NONE = 102; + +// Creates an animation in the given state/page used to test side-effects. See: +// https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states +// +// testcase - A query string for the test case root. Must have a descendant +// with the 'target' class that will be animated. +// state - One of the STATE_ constants above. Configures the animation to be +// either "current", "in effect" or neither. +// property - One of the PROPERTY_ constants above, the property the animation +// will target. +// phase - One of the PHASE_ constants above. Configures the animation to be in +// the before/active/after phase. +function setupAnimation(testcase, state, property, phase) { + const root = document.querySelector(testcase); + const effect_target = root.querySelector('.target'); + + let keyframe; + if (property == PROPERTY_OPACITY) + keyframe = { opacity: 1}; + else if (property == PROPERTY_TRANSFORM) + keyframe = { transform: 'translateX(0px)' }; + else if (property == PROPERTY_BGCOLOR) + keyframe = { backgroundColor: 'red' }; + else + throw new Error('Unexpected property'); + + const kPhaseDuration = 1000000; + const kBeforePhaseTime = kPhaseDuration / 2; + const kActivePhaseTime = kPhaseDuration + kPhaseDuration / 2; + const kAfterPhaseTime = 2 * kPhaseDuration + kPhaseDuration / 2; + + const options = { + duration: kPhaseDuration, + delay: kPhaseDuration, + endDelay: kPhaseDuration, + + easing: 'steps(1, jump-both)', + + fill: (state == STATE_IN_EFFECT ? 'both' : 'none'), + }; + + const animation = effect_target.animate( + [ keyframe, keyframe ], options); + + switch(phase) { + case PHASE_BEFORE: + animation.currentTime = kBeforePhaseTime; + if (state == STATE_IN_EFFECT || state == STATE_NONE) + animation.playbackRate = -1; + break; + + case PHASE_ACTIVE: + if (state == STATE_NONE) + throw new Error("Cannot have state[NONE] in the active phase"); + + animation.currentTime = kActivePhaseTime; + break; + + case PHASE_AFTER: + animation.currentTime = kAfterPhaseTime; + if (state == STATE_CURRENT) + animation.playbackRate = -1; + break; + + default: + throw new Error('Unexpected phase'); + } +} diff --git a/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current-ref.html b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current-ref.html new file mode 100644 index 0000000000..acc0465b07 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current-ref.html @@ -0,0 +1,109 @@ + + + Current animations should effectively apply will-change (i.e. force a + stacking context) (ref) + + + + + + + + +
+
Opacity - before phase
+
+
+
+
+ + +
+
Opacity - active phase
+
+
+
+
+ + +
+
Opacity - after phase
+
+
+
+
+ + + + +
+
Transform - before phase
+
+
+
+
+ + +
+
Transform - active phase
+
+
+
+
+ + +
+
Transform - after phase
+
+
+
+
+ + +
+
Background-color - before phase
+
+
+
+
+ + +
+
Background-color - active phase
+
+
+
+
+ + +
+
Background-color - after phase
+
+
+
+
diff --git a/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current.html b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current.html new file mode 100644 index 0000000000..18b13be9fa --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-current.html @@ -0,0 +1,174 @@ + + + + Current animations should effectively apply will-change (i.e. force a + stacking context) + + + + + + + + + + + + + + +
+
Opacity - before phase
+
+
+
+
+
+ + + +
+
Opacity - active phase
+
+
+
+
+
+ + + +
+
Opacity - after phase
+
+
+
+
+
+ + + + + +
+
Transform - before phase
+
+
+
+
+
+ + + +
+
Transform - active phase
+
+
+
+
+
+ + + +
+
Transform - after phase
+
+
+
+
+
+ + + + + + +
+
Background-color - before phase
+
+
+
+
+
+ + + +
+
Background-color - active phase
+
+
+
+
+
+ + + +
+
Background-color - after phase
+
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect-ref.html b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect-ref.html new file mode 100644 index 0000000000..24160cb267 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect-ref.html @@ -0,0 +1,109 @@ + + + In effect animations should effectively apply will-change (i.e. force a + stacking context) (ref) + + + + + + + + +
+
Opacity - before phase
+
+
+
+
+ + +
+
Opacity - active phase
+
+
+
+
+ + +
+
Opacity - after phase
+
+
+
+
+ + + + +
+
Transform - before phase
+
+
+
+
+ + +
+
Transform - active phase
+
+
+
+
+ + +
+
Transform - after phase
+
+
+
+
+ + +
+
Background-color - before phase
+
+
+
+
+ + +
+
Background-color - active phase
+
+
+
+
+ + +
+
Background-color - after phase
+
+
+
+
diff --git a/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect.html b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect.html new file mode 100644 index 0000000000..90ee055082 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-in-effect.html @@ -0,0 +1,174 @@ + + + + In effect animations should effectively apply will-change (i.e. force a + stacking context) + + + + + + + + + + + + + + +
+
Opacity - before phase
+
+
+
+
+
+ + + +
+
Opacity - active phase
+
+
+
+
+
+ + + +
+
Opacity - after phase
+
+
+
+
+
+ + + + + +
+
Transform - before phase
+
+
+
+
+
+ + + +
+
Transform - active phase
+
+
+
+
+
+ + + +
+
Transform - after phase
+
+
+
+
+
+ + + + + + +
+
Background-color - before phase
+
+
+
+
+
+ + + +
+
Background-color - active phase
+
+
+
+
+
+ + + +
+
Background-color - after phase
+
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none-ref.html b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none-ref.html new file mode 100644 index 0000000000..4d1ea997f4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none-ref.html @@ -0,0 +1,48 @@ + + + Animations not in effect nor current shouldn't have side-effects (ref). + + + + + + +
+
Before phase
+
+
+
+
+ + +
+
After phase
+
+
+
+
diff --git a/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none.html b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none.html new file mode 100644 index 0000000000..d200409e64 --- /dev/null +++ b/testing/web-platform/tests/web-animations/animation-model/side-effects-of-animations-none.html @@ -0,0 +1,79 @@ + + + + Animations not in effect nor current shouldn't have side-effects. + + + + + + + + + + + + +
+
Before phase
+
+
+
+
+
+ + + +
+
After phase
+
+
+
+
+
+ + + diff --git a/testing/web-platform/tests/web-animations/crashtests/color-mix-crashtest.html b/testing/web-platform/tests/web-animations/crashtests/color-mix-crashtest.html new file mode 100644 index 0000000000..91d29464f5 --- /dev/null +++ b/testing/web-platform/tests/web-animations/crashtests/color-mix-crashtest.html @@ -0,0 +1,35 @@ + + +Interpolation of a color-mix function with currentcolor should not crash + + + +
Hello world
+ + + + diff --git a/testing/web-platform/tests/web-animations/crashtests/get-computed-timing-crash.html b/testing/web-platform/tests/web-animations/crashtests/get-computed-timing-crash.html new file mode 100644 index 0000000000..b666eea91f --- /dev/null +++ b/testing/web-platform/tests/web-animations/crashtests/get-computed-timing-crash.html @@ -0,0 +1,20 @@ + + +GetComputedTiming on an animation without an execution context, +timeline or playback rate + + + + +
+ + + + diff --git a/testing/web-platform/tests/web-animations/crashtests/infinite-active-duration.html b/testing/web-platform/tests/web-animations/crashtests/infinite-active-duration.html new file mode 100644 index 0000000000..f92cd13942 --- /dev/null +++ b/testing/web-platform/tests/web-animations/crashtests/infinite-active-duration.html @@ -0,0 +1,68 @@ + +Various test cases producing infinite active duration + + diff --git a/testing/web-platform/tests/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html b/testing/web-platform/tests/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html new file mode 100644 index 0000000000..b943514f42 --- /dev/null +++ b/testing/web-platform/tests/web-animations/crashtests/partially-overlapping-animations-one-not-current-001.html @@ -0,0 +1,17 @@ + + +CSS Test (Animations): Reparenting an element with a web animation on the compositor + + + + + + +
X
diff --git a/testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-001.html b/testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-001.html new file mode 100644 index 0000000000..49ee9c433c --- /dev/null +++ b/testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-001.html @@ -0,0 +1,40 @@ + + +CSS Test (Animations): Reparenting an element with a web animation on the compositor + + + + + + +
+
+ diff --git a/testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-002.html b/testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-002.html new file mode 100644 index 0000000000..0d3549fc33 --- /dev/null +++ b/testing/web-platform/tests/web-animations/crashtests/reparent-animating-element-002.html @@ -0,0 +1,44 @@ + + +CSS Test (Animations): Reparenting an element with a web animation on the compositor + + + + + + + +X +
+ diff --git a/testing/web-platform/tests/web-animations/idlharness.window.js b/testing/web-platform/tests/web-animations/idlharness.window.js new file mode 100644 index 0000000000..aaf6f58e7b --- /dev/null +++ b/testing/web-platform/tests/web-animations/idlharness.window.js @@ -0,0 +1,21 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +'use strict'; + +idl_test( + ['web-animations', 'web-animations-2'], + ['dom', 'html', 'scroll-animations'], + idl_array => { + idl_array.add_objects({ + Animation: ['new Animation()'], + AnimationPlaybackEvent: ['new AnimationPlaybackEvent("cancel")'], + Document: ['document'], + DocumentTimeline: ['document.timeline'], + KeyframeEffect: ['new KeyframeEffect(null, null)'], + ShadowRoot: ['shadowRoot'], + }); + self.shadowRoot = document.createElement("div").attachShadow({mode: "open"}); + } +); diff --git a/testing/web-platform/tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html b/testing/web-platform/tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html new file mode 100644 index 0000000000..61a7502a98 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html @@ -0,0 +1,107 @@ + + +Animatable.animate in combination with elements in documents + without a browsing context + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animatable/animate.html b/testing/web-platform/tests/web-animations/interfaces/Animatable/animate.html new file mode 100644 index 0000000000..28e803d690 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animatable/animate.html @@ -0,0 +1,363 @@ + + +Animatable.animate + + + + + + + + + + + +
+ + + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations-iframe.html b/testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations-iframe.html new file mode 100644 index 0000000000..1851878c41 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations-iframe.html @@ -0,0 +1,51 @@ + +getAnimations in dirty iframe + + + + + + + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations.html b/testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations.html new file mode 100644 index 0000000000..fd8719299d --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animatable/getAnimations.html @@ -0,0 +1,355 @@ + + +Animatable.getAnimations + + + + + + + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html b/testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html new file mode 100644 index 0000000000..a7da9755dd --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/cancel.html @@ -0,0 +1,133 @@ + + +Animation.cancel + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-crash.html b/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-crash.html new file mode 100644 index 0000000000..063fe5a4eb --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-crash.html @@ -0,0 +1,26 @@ + + + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-svg-crash.html b/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-svg-crash.html new file mode 100644 index 0000000000..7fc1fef9ce --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles-svg-crash.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles.html b/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles.html new file mode 100644 index 0000000000..9a7dbea8b8 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/commitStyles.html @@ -0,0 +1,577 @@ + + +Animation.commitStyles + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html b/testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html new file mode 100644 index 0000000000..e964c10ee4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/constructor.html @@ -0,0 +1,124 @@ + + +Animation constructor + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html b/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html new file mode 100644 index 0000000000..cb8bc09c36 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/effect.html @@ -0,0 +1,42 @@ + + +Animation.effect + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/finished.html b/testing/web-platform/tests/web-animations/interfaces/Animation/finished.html new file mode 100644 index 0000000000..bee4fd8fb7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/finished.html @@ -0,0 +1,416 @@ + + +Animation.finished + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/id.html b/testing/web-platform/tests/web-animations/interfaces/Animation/id.html new file mode 100644 index 0000000000..5b9586bfaf --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/id.html @@ -0,0 +1,28 @@ + + +Animation.id + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html b/testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html new file mode 100644 index 0000000000..d539119609 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/oncancel.html @@ -0,0 +1,33 @@ + + +Animation.oncancel + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html b/testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html new file mode 100644 index 0000000000..b58fea0362 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/onfinish.html @@ -0,0 +1,119 @@ + + +Animation.onfinish + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/onremove.html b/testing/web-platform/tests/web-animations/interfaces/Animation/onremove.html new file mode 100644 index 0000000000..1a41a3d21c --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/onremove.html @@ -0,0 +1,58 @@ + + +Animation.onremove + + + + + +
+ + + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/pause.html b/testing/web-platform/tests/web-animations/interfaces/Animation/pause.html new file mode 100644 index 0000000000..1d1bd5fd89 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/pause.html @@ -0,0 +1,98 @@ + + +Animation.pause + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/pending.html b/testing/web-platform/tests/web-animations/interfaces/Animation/pending.html new file mode 100644 index 0000000000..c200f9e977 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/pending.html @@ -0,0 +1,55 @@ + + +Animation.pending + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/persist.html b/testing/web-platform/tests/web-animations/interfaces/Animation/persist.html new file mode 100644 index 0000000000..c18993cbc4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/persist.html @@ -0,0 +1,40 @@ + + +Animation.persist + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/play.html b/testing/web-platform/tests/web-animations/interfaces/Animation/play.html new file mode 100644 index 0000000000..6c5d604b1e --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/play.html @@ -0,0 +1,34 @@ + + +Animation.play + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/ready.html b/testing/web-platform/tests/web-animations/interfaces/Animation/ready.html new file mode 100644 index 0000000000..462e2a0484 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/ready.html @@ -0,0 +1,78 @@ + + +Animation.ready + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html b/testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html new file mode 100644 index 0000000000..61f76955a3 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/startTime.html @@ -0,0 +1,55 @@ + + +Animation.startTime + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/Animation/style-change-events.html b/testing/web-platform/tests/web-animations/interfaces/Animation/style-change-events.html new file mode 100644 index 0000000000..0ec21657e3 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Animation/style-change-events.html @@ -0,0 +1,376 @@ + + +Animation interface: style change events + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/AnimationEffect/getComputedTiming.html b/testing/web-platform/tests/web-animations/interfaces/AnimationEffect/getComputedTiming.html new file mode 100644 index 0000000000..10bd193361 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/AnimationEffect/getComputedTiming.html @@ -0,0 +1,214 @@ + + +AnimationEffect.getComputedTiming + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/AnimationEffect/updateTiming.html b/testing/web-platform/tests/web-animations/interfaces/AnimationEffect/updateTiming.html new file mode 100644 index 0000000000..6a340c0bf4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/AnimationEffect/updateTiming.html @@ -0,0 +1,475 @@ + + +AnimationEffect.updateTiming + + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html b/testing/web-platform/tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html new file mode 100644 index 0000000000..1c40a3fb21 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html @@ -0,0 +1,30 @@ + + +AnimationPlaybackEvent constructor + + + +
+ diff --git a/testing/web-platform/tests/web-animations/interfaces/Document/timeline.html b/testing/web-platform/tests/web-animations/interfaces/Document/timeline.html new file mode 100644 index 0000000000..b8b4d74d5e --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/Document/timeline.html @@ -0,0 +1,23 @@ + + +Document.timeline + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/DocumentOrShadowRoot/getAnimations.html b/testing/web-platform/tests/web-animations/interfaces/DocumentOrShadowRoot/getAnimations.html new file mode 100644 index 0000000000..9bcc042a8f --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/DocumentOrShadowRoot/getAnimations.html @@ -0,0 +1,234 @@ + + +DocumentOrShadowRoot.getAnimations + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/constructor.html b/testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/constructor.html new file mode 100644 index 0000000000..ca0997ac8f --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/constructor.html @@ -0,0 +1,43 @@ + + +DocumentTimeline constructor tests + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/style-change-events.html b/testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/style-change-events.html new file mode 100644 index 0000000000..c1607e6fb9 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/DocumentTimeline/style-change-events.html @@ -0,0 +1,92 @@ + + +DocumentTimeline interface: style change events + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/composite.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/composite.html new file mode 100644 index 0000000000..bcca2cad24 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/composite.html @@ -0,0 +1,47 @@ + + +KeyframeEffect.composite + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/constructor.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/constructor.html new file mode 100644 index 0000000000..f9d552e63e --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/constructor.html @@ -0,0 +1,195 @@ + + +KeyframeEffect constructor + + + + + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html new file mode 100644 index 0000000000..e3bc0db00a --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html @@ -0,0 +1,93 @@ + + +KeyframeEffect copy constructor + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/getKeyframes.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/getKeyframes.html new file mode 100644 index 0000000000..1f8d267e4a --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/getKeyframes.html @@ -0,0 +1,25 @@ + + +KeyframeEffect getKeyframes() + + + + + + +
+
+ \ No newline at end of file diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html new file mode 100644 index 0000000000..bbb8ee2a32 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html @@ -0,0 +1,36 @@ + + +KeyframeEffect.iterationComposite + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html new file mode 100644 index 0000000000..271a47b301 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html @@ -0,0 +1,602 @@ + + +Processing a keyframes argument (property access) + + + + + + +
+
+ diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html new file mode 100644 index 0000000000..8620f883f9 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html @@ -0,0 +1,125 @@ + + +Processing a keyframes argument (easing) + + + + + + +
+
+ diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html new file mode 100644 index 0000000000..a5c81a29bd --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html @@ -0,0 +1,55 @@ + + +KeyframeEffect.setKeyframes + + + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/style-change-events.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/style-change-events.html new file mode 100644 index 0000000000..eecf170cd9 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/style-change-events.html @@ -0,0 +1,242 @@ + + +KeyframeEffect interface: style change events + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html new file mode 100644 index 0000000000..58d17b98d5 --- /dev/null +++ b/testing/web-platform/tests/web-animations/interfaces/KeyframeEffect/target.html @@ -0,0 +1,271 @@ + + +KeyframeEffect.target and .pseudoElement + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/resources/easing-tests.js b/testing/web-platform/tests/web-animations/resources/easing-tests.js new file mode 100644 index 0000000000..a05264b0f5 --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/easing-tests.js @@ -0,0 +1,121 @@ +'use strict'; + +const gEasingTests = [ + { + desc: 'step-start function', + easing: 'step-start', + easingFunction: stepStart(1), + serialization: 'steps(1, start)' + }, + { + desc: 'steps(1, start) function', + easing: 'steps(1, start)', + easingFunction: stepStart(1) + }, + { + desc: 'steps(2, start) function', + easing: 'steps(2, start)', + easingFunction: stepStart(2) + }, + { + desc: 'step-end function', + easing: 'step-end', + easingFunction: stepEnd(1), + serialization: 'steps(1)' + }, + { + desc: 'steps(1) function', + easing: 'steps(1)', + easingFunction: stepEnd(1) + }, + { + desc: 'steps(1, end) function', + easing: 'steps(1, end)', + easingFunction: stepEnd(1), + serialization: 'steps(1)' + }, + { + desc: 'steps(2, end) function', + easing: 'steps(2, end)', + easingFunction: stepEnd(2), + serialization: 'steps(2)' + }, + { + desc: 'linear function', + easing: 'linear', // cubic-bezier(0, 0, 1.0, 1.0) + easingFunction: cubicBezier(0, 0, 1.0, 1.0) + }, + { + desc: 'ease function', + easing: 'ease', // cubic-bezier(0.25, 0.1, 0.25, 1.0) + easingFunction: cubicBezier(0.25, 0.1, 0.25, 1.0) + }, + { + desc: 'ease-in function', + easing: 'ease-in', // cubic-bezier(0.42, 0, 1.0, 1.0) + easingFunction: cubicBezier(0.42, 0, 1.0, 1.0) + }, + { + desc: 'ease-in-out function', + easing: 'ease-in-out', // cubic-bezier(0.42, 0, 0.58, 1.0) + easingFunction: cubicBezier(0.42, 0, 0.58, 1.0) + }, + { + desc: 'ease-out function', + easing: 'ease-out', // cubic-bezier(0, 0, 0.58, 1.0) + easingFunction: cubicBezier(0, 0, 0.58, 1.0) + }, + { + desc: 'easing function which produces values greater than 1', + easing: 'cubic-bezier(0, 1.5, 1, 1.5)', + easingFunction: cubicBezier(0, 1.5, 1, 1.5) + }, + { + desc: 'easing function which produces values less than 1', + easing: 'cubic-bezier(0, -0.5, 1, -0.5)', + easingFunction: cubicBezier(0, -0.5, 1, -0.5) + } +]; + +const gEasingParsingTests = [ + ['linear', 'linear'], + ['ease-in-out', 'ease-in-out'], + ['Ease\\2d in-out', 'ease-in-out'], + ['ease /**/', 'ease'], +]; + +const gInvalidEasings = [ + '', + '7', + 'test', + 'initial', + 'inherit', + 'unset', + 'unrecognized', + 'var(--x)', + 'ease-in-out, ease-out', + 'cubic-bezier(1.1, 0, 1, 1)', + 'cubic-bezier(0, 0, 1.1, 1)', + 'cubic-bezier(-0.1, 0, 1, 1)', + 'cubic-bezier(0, 0, -0.1, 1)', + 'cubic-bezier(0.1, 0, 4, 0.4)', + 'steps(-1, start)', + 'steps(0.1, start)', + 'steps(3, nowhere)', + 'steps(-3, end)', + 'function (a){return a}', + 'function (x){return x}', + 'function(x, y){return 0.3}', +]; + +// Easings that should serialize to the same string +const gRoundtripEasings = [ + 'ease', + 'linear', + 'ease-in', + 'ease-out', + 'ease-in-out', + 'cubic-bezier(0.1, 5, 0.23, 0)', + 'steps(3, start)', + 'steps(3)', +]; diff --git a/testing/web-platform/tests/web-animations/resources/effect-tests.js b/testing/web-platform/tests/web-animations/resources/effect-tests.js new file mode 100644 index 0000000000..8a18ab13c6 --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/effect-tests.js @@ -0,0 +1,75 @@ +'use strict'; + +// Common utility methods for testing animation effects + +// Tests the |property| member of |animation's| target effect's computed timing +// at the various points indicated by |values|. +// +// |values| has the format: +// +// { +// before, // value to test during before phase +// activeBoundary, // value to test at the very beginning of the active +// // phase when playing forwards, or the very end of +// // the active phase when playing backwards. +// // This should be undefined if the active duration of +// // the effect is zero. +// after, // value to test during the after phase or undefined if the +// // active duration is infinite +// } +// +function assert_computed_timing_for_each_phase(animation, property, values) { + // Some computed timing properties (e.g. 'progress') require floating-point + // comparison, whilst exact equality suffices for others. + const assert_property_equals = + (property === 'progress') ? assert_times_equal : assert_equals; + + const effect = animation.effect; + const timing = effect.getComputedTiming(); + + // The following calculations are based on the definitions here: + // https://drafts.csswg.org/web-animations/#animation-effect-phases-and-states + const beforeActive = Math.max(Math.min(timing.delay, timing.endTime), 0); + const activeAfter = + Math.max(Math.min(timing.delay + timing.activeDuration, timing.endTime), 0); + const direction = animation.playbackRate < 0 ? 'backwards' : 'forwards'; + + // Before phase + if (direction === 'forwards') { + animation.currentTime = beforeActive - 1; + } else { + animation.currentTime = beforeActive; + } + assert_property_equals(effect.getComputedTiming()[property], values.before, + `Value of ${property} in the before phase`); + + // Active phase + if (effect.getComputedTiming().activeDuration > 0) { + if (direction === 'forwards') { + animation.currentTime = beforeActive; + } else { + animation.currentTime = activeAfter; + } + assert_property_equals(effect.getComputedTiming()[property], values.activeBoundary, + `Value of ${property} at the boundary of the active phase`); + } else { + assert_equals(values.activeBoundary, undefined, + 'Test specifies a value to check during the active phase but' + + ' the animation has a zero duration'); + } + + // After phase + if (effect.getComputedTiming().activeDuration !== Infinity) { + if (direction === 'forwards') { + animation.currentTime = activeAfter; + } else { + animation.currentTime = activeAfter + 1; + } + assert_property_equals(effect.getComputedTiming()[property], values.after, + `Value of ${property} in the after phase`); + } else { + assert_equals(values.after, undefined, + 'Test specifies a value to check during the after phase but' + + ' the animation has an infinite duration'); + } +} diff --git a/testing/web-platform/tests/web-animations/resources/keyframe-tests.js b/testing/web-platform/tests/web-animations/resources/keyframe-tests.js new file mode 100644 index 0000000000..43e0d7575f --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/keyframe-tests.js @@ -0,0 +1,827 @@ +'use strict'; + +// ============================== +// +// Common keyframe test data +// +// ============================== + + +// ------------------------------ +// Composite values +// ------------------------------ + +const gGoodKeyframeCompositeValueTests = [ + 'replace', 'add', 'accumulate', 'auto' +]; + +const gBadKeyframeCompositeValueTests = [ + 'unrecognised', 'replace ', 'Replace', null +]; + +const gGoodOptionsCompositeValueTests = [ + 'replace', 'add', 'accumulate' +]; + +const gBadOptionsCompositeValueTests = [ + 'unrecognised', 'replace ', 'Replace', null +]; + +// ------------------------------ +// Keyframes +// ------------------------------ + +const gEmptyKeyframeListTests = [ + [], + null, + undefined, +]; + +// Helper methods to make defining computed keyframes more readable. + +const offset = offset => ({ + offset, + computedOffset: offset, +}); + +const computedOffset = computedOffset => ({ + offset: null, + computedOffset, +}); + +const keyframe = (offset, props, easing='linear', composite) => { + // The object spread operator is not yet available in all browsers so we use + // Object.assign instead. + const result = {}; + Object.assign(result, offset, props, { easing }); + result.composite = composite || 'auto'; + return result; +}; + +const gKeyframesTests = [ + + // ----------- Property-indexed keyframes: property handling ----------- + + { + desc: 'a one property two value property-indexed keyframes specification', + input: { left: ['10px', '20px'] }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(1), { left: '20px' })], + }, + { + desc: 'a one shorthand property two value property-indexed keyframes' + + ' specification', + input: { margin: ['10px', '10px 20px 30px 40px'] }, + output: [keyframe(computedOffset(0), { margin: '10px' }), + keyframe(computedOffset(1), { margin: '10px 20px 30px 40px' })], + }, + { + desc: 'a two property (one shorthand and one of its longhand components)' + + ' two value property-indexed keyframes specification', + input: { marginTop: ['50px', '60px'], + margin: ['10px', '10px 20px 30px 40px'] }, + output: [keyframe(computedOffset(0), + { marginTop: '50px', margin: '10px' }), + keyframe(computedOffset(1), + { marginTop: '60px', margin: '10px 20px 30px 40px' })], + }, + { + desc: 'a two property (one shorthand and one of its shorthand components)' + + ' two value property-indexed keyframes specification', + input: { border: ['pink', '2px'], + borderColor: ['green', 'blue'] }, + output: [keyframe(computedOffset(0), + { border: 'pink', borderColor: 'green' }), + keyframe(computedOffset(1), + { border: '2px', borderColor: 'blue' })], + }, + { + desc: 'a two property two value property-indexed keyframes specification', + input: { left: ['10px', '20px'], + top: ['30px', '40px'] }, + output: [keyframe(computedOffset(0), { left: '10px', top: '30px' }), + keyframe(computedOffset(1), { left: '20px', top: '40px' })], + }, + { + desc: 'a two property property-indexed keyframes specification with' + + ' different numbers of values', + input: { left: ['10px', '20px', '30px'], + top: ['40px', '50px'] }, + output: [keyframe(computedOffset(0), { left: '10px', top: '40px' }), + keyframe(computedOffset(0.5), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px', top: '50px' })], + }, + { + desc: 'a property-indexed keyframes specification with an invalid value', + input: { left: ['10px', '20px', '30px', '40px', '50px'], + top: ['15px', '25px', 'invalid', '45px', '55px'] }, + output: [keyframe(computedOffset(0), { left: '10px', top: '15px' }), + keyframe(computedOffset(0.25), { left: '20px', top: '25px' }), + keyframe(computedOffset(0.5), { left: '30px' }), + keyframe(computedOffset(0.75), { left: '40px', top: '45px' }), + keyframe(computedOffset(1), { left: '50px', top: '55px' })], + }, + { + desc: 'a one property two value property-indexed keyframes specification' + + ' that needs to stringify its values', + input: { opacity: [0, 1] }, + output: [keyframe(computedOffset(0), { opacity: '0' }), + keyframe(computedOffset(1), { opacity: '1' })], + }, + { + desc: 'a property-indexed keyframes specification with a CSS variable' + + ' reference', + input: { left: [ 'var(--dist)', 'calc(var(--dist) + 100px)' ] }, + output: [keyframe(computedOffset(0), { left: 'var(--dist)' }), + keyframe(computedOffset(1), { left: 'calc(var(--dist) + 100px)' })] + }, + { + desc: 'a property-indexed keyframes specification with a CSS variable' + + ' reference in a shorthand property', + input: { margin: [ 'var(--dist)', 'calc(var(--dist) + 100px)' ] }, + output: [keyframe(computedOffset(0), + { margin: 'var(--dist)' }), + keyframe(computedOffset(1), + { margin: 'calc(var(--dist) + 100px)' })], + }, + { + desc: 'a one property one value property-indexed keyframes specification', + input: { left: ['10px'] }, + output: [keyframe(computedOffset(1), { left: '10px' })], + }, + { + desc: 'a one property one non-array value property-indexed keyframes' + + ' specification', + input: { left: '10px' }, + output: [keyframe(computedOffset(1), { left: '10px' })], + }, + { + desc: 'a one property two value property-indexed keyframes specification' + + ' where the first value is invalid', + input: { left: ['invalid', '10px'] }, + output: [keyframe(computedOffset(0), {}), + keyframe(computedOffset(1), { left: '10px' })] + }, + { + desc: 'a one property two value property-indexed keyframes specification' + + ' where the second value is invalid', + input: { left: ['10px', 'invalid'] }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(1), {})] + }, + { + desc: 'a property-indexed keyframes specification with a CSS variable as' + + ' the property', + input: { '--custom': ['1', '2'] }, + output: [keyframe(computedOffset(0), { '--custom': '1' }), + keyframe(computedOffset(1), { '--custom': '2' })] + }, + + // ----------- Property-indexed keyframes: offset handling ----------- + + { + desc: 'a property-indexed keyframe with a single offset', + input: { left: ['10px', '20px', '30px'], offset: 0.5 }, + output: [keyframe(offset(0.5), { left: '10px' }), + keyframe(computedOffset(0.75), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets', + input: { left: ['10px', '20px', '30px'], offset: [ 0.1, 0.25, 0.8 ] }, + output: [keyframe(offset(0.1), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(offset(0.8), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets that is too' + + ' short', + input: { left: ['10px', '20px', '30px'], offset: [ 0, 0.25 ] }, + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets that is too' + + ' long', + input: { left: ['10px', '20px', '30px'], + offset: [ 0, 0.25, 0.5, 0.75, 1 ] }, + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(offset(0.5), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an empty array of offsets', + input: { left: ['10px', '20px', '30px'], offset: [] }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(0.5), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets with an' + + ' embedded null value', + input: { left: ['10px', '20px', '30px'], + offset: [ 0, null, 0.5 ] }, + output: [keyframe(offset(0), { left: '10px' }), + keyframe(computedOffset(0.25), { left: '20px' }), + keyframe(offset(0.5), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets with a' + + ' trailing null value', + input: { left: ['10px', '20px', '30px'], + offset: [ 0, 0.25, null ] }, + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets with leading' + + ' and trailing null values', + input: { left: ['10px', '20px', '30px'], + offset: [ null, 0.25, null ] }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets with' + + ' adjacent null values', + input: { left: ['10px', '20px', '30px'], + offset: [ null, null, 0.5 ] }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(0.25), { left: '20px' }), + keyframe(offset(0.5), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets with' + + ' all null values (and too many at that)', + input: { left: ['10px', '20px', '30px'], + offset: [ null, null, null, null, null ] }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(0.5), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with a single null offset', + input: { left: ['10px', '20px', '30px'], offset: null }, + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(0.5), { left: '20px' }), + keyframe(computedOffset(1), { left: '30px' })], + }, + { + desc: 'a property-indexed keyframe with an array of offsets that is not' + + ' strictly ascending in the unused part of the array', + input: { left: ['10px', '20px', '30px'], + offset: [ 0, 0.2, 0.8, 0.6 ] }, + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.2), { left: '20px' }), + keyframe(offset(0.8), { left: '30px' })], + }, + + // ----------- Property-indexed keyframes: easing handling ----------- + + { + desc: 'a property-indexed keyframe without any specified easing', + input: { left: ['10px', '20px', '30px'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'linear'), + keyframe(computedOffset(0.5), { left: '20px' }, 'linear'), + keyframe(computedOffset(1), { left: '30px' }, 'linear')], + }, + { + desc: 'a property-indexed keyframe with a single easing', + input: { left: ['10px', '20px', '30px'], easing: 'ease-in' }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'ease-in'), + keyframe(computedOffset(0.5), { left: '20px' }, 'ease-in'), + keyframe(computedOffset(1), { left: '30px' }, 'ease-in')], + }, + { + desc: 'a property-indexed keyframe with an array of easings', + input: { left: ['10px', '20px', '30px'], + easing: ['ease-in', 'ease-out', 'ease-in-out'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'ease-in'), + keyframe(computedOffset(0.5), { left: '20px' }, 'ease-out'), + keyframe(computedOffset(1), { left: '30px' }, 'ease-in-out')], + }, + { + desc: 'a property-indexed keyframe with an array of easings that is too' + + ' short', + input: { left: ['10px', '20px', '30px'], + easing: ['ease-in', 'ease-out'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'ease-in'), + keyframe(computedOffset(0.5), { left: '20px' }, 'ease-out'), + keyframe(computedOffset(1), { left: '30px' }, 'ease-in')], + }, + { + desc: 'a property-indexed keyframe with a single-element array of' + + ' easings', + input: { left: ['10px', '20px', '30px'], easing: ['ease-in'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'ease-in'), + keyframe(computedOffset(0.5), { left: '20px' }, 'ease-in'), + keyframe(computedOffset(1), { left: '30px' }, 'ease-in')], + }, + { + desc: 'a property-indexed keyframe with an empty array of easings', + input: { left: ['10px', '20px', '30px'], easing: [] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'linear'), + keyframe(computedOffset(0.5), { left: '20px' }, 'linear'), + keyframe(computedOffset(1), { left: '30px' }, 'linear')], + }, + { + desc: 'a property-indexed keyframe with an array of easings that is too' + + ' long', + input: { left: ['10px', '20px', '30px'], + easing: ['steps(1)', 'steps(2)', 'steps(3)', 'steps(4)'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'steps(1)'), + keyframe(computedOffset(0.5), { left: '20px' }, 'steps(2)'), + keyframe(computedOffset(1), { left: '30px' }, 'steps(3)')], + }, + + // ----------- Property-indexed keyframes: composite handling ----------- + + { + desc: 'a property-indexed keyframe with a single composite operation', + input: { left: ['10px', '20px', '30px'], composite: 'add' }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'linear', 'add'), + keyframe(computedOffset(0.5), { left: '20px' }, 'linear', 'add'), + keyframe(computedOffset(1), { left: '30px' }, 'linear', 'add')], + }, + { + desc: 'a property-indexed keyframe with a composite array', + input: { left: ['10px', '20px', '30px'], + composite: ['add', 'replace', 'accumulate'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, + 'linear', 'add'), + keyframe(computedOffset(0.5), { left: '20px' }, + 'linear', 'replace'), + keyframe(computedOffset(1), { left: '30px' }, + 'linear', 'accumulate')], + }, + { + desc: 'a property-indexed keyframe with a composite array that is too' + + ' short', + input: { left: ['10px', '20px', '30px', '40px', '50px'], + composite: ['add', 'replace'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, + 'linear', 'add'), + keyframe(computedOffset(0.25), { left: '20px' }, + 'linear', 'replace'), + keyframe(computedOffset(0.5), { left: '30px' }, + 'linear', 'add'), + keyframe(computedOffset(0.75), { left: '40px' }, + 'linear', 'replace'), + keyframe(computedOffset(1), { left: '50px' }, + 'linear', 'add')], + }, + { + desc: 'a property-indexed keyframe with a composite array that is too' + + ' long', + input: { left: ['10px', '20px'], + composite: ['add', 'replace', 'accumulate'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, + 'linear', 'add'), + keyframe(computedOffset(1), { left: '20px' }, + 'linear', 'replace')], + }, + { + desc: 'a property-indexed keyframe with a single-element composite array', + input: { left: ['10px', '20px', '30px'], + composite: ['add'] }, + output: [keyframe(computedOffset(0), { left: '10px' }, 'linear', 'add'), + keyframe(computedOffset(0.5), { left: '20px' }, 'linear', 'add'), + keyframe(computedOffset(1), { left: '30px' }, 'linear', 'add')], + }, + + // ----------- Keyframe sequence: property handling ----------- + + { + desc: 'a one property one keyframe sequence', + input: [{ offset: 1, left: '10px' }], + output: [keyframe(offset(1), { left: '10px' })], + }, + { + desc: 'a one property two keyframe sequence', + input: [{ offset: 0, left: '10px' }, + { offset: 1, left: '20px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(1), { left: '20px' })], + }, + { + desc: 'a two property two keyframe sequence', + input: [{ offset: 0, left: '10px', top: '30px' }, + { offset: 1, left: '20px', top: '40px' }], + output: [keyframe(offset(0), { left: '10px', top: '30px' }), + keyframe(offset(1), { left: '20px', top: '40px' })], + }, + { + desc: 'a one shorthand property two keyframe sequence', + input: [{ offset: 0, margin: '10px' }, + { offset: 1, margin: '20px 30px 40px 50px' }], + output: [keyframe(offset(0), { margin: '10px' }), + keyframe(offset(1), { margin: '20px 30px 40px 50px' })], + }, + { + desc: 'a two property (a shorthand and one of its component longhands)' + + ' two keyframe sequence', + input: [{ offset: 0, margin: '10px', marginTop: '20px' }, + { offset: 1, marginTop: '70px', margin: '30px 40px 50px 60px' }], + output: [keyframe(offset(0), { margin: '10px', marginTop: '20px' }), + keyframe(offset(1), { marginTop: '70px', + margin: '30px 40px 50px 60px' })], + }, + { + desc: 'a two property keyframe sequence where one property is missing' + + ' from the first keyframe', + input: [{ offset: 0, left: '10px' }, + { offset: 1, left: '20px', top: '30px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(1), { left: '20px', top: '30px' })], + }, + { + desc: 'a two property keyframe sequence where one property is missing' + + ' from the last keyframe', + input: [{ offset: 0, left: '10px', top: '20px' }, + { offset: 1, left: '30px' }], + output: [keyframe(offset(0), { left: '10px', top: '20px' }), + keyframe(offset(1), { left: '30px' })], + }, + { + desc: 'a one property two keyframe sequence that needs to stringify' + + ' its values', + input: [{ offset: 0, opacity: 0 }, + { offset: 1, opacity: 1 }], + output: [keyframe(offset(0), { opacity: '0' }), + keyframe(offset(1), { opacity: '1' })], + }, + { + desc: 'a keyframe sequence with a CSS variable reference', + input: [{ left: 'var(--dist)' }, + { left: 'calc(var(--dist) + 100px)' }], + output: [keyframe(computedOffset(0), { left: 'var(--dist)' }), + keyframe(computedOffset(1), { left: 'calc(var(--dist) + 100px)' })] + }, + { + desc: 'a keyframe sequence with a CSS variable reference in a shorthand' + + ' property', + input: [{ margin: 'var(--dist)' }, + { margin: 'calc(var(--dist) + 100px)' }], + output: [keyframe(computedOffset(0), + { margin: 'var(--dist)' }), + keyframe(computedOffset(1), + { margin: 'calc(var(--dist) + 100px)' })], + }, + { + desc: 'a keyframe sequence with a CSS variable as its property', + input: [{ '--custom': 'a' }, + { '--custom': 'b' }], + output: [keyframe(computedOffset(0), { '--custom': 'a' }), + keyframe(computedOffset(1), { '--custom': 'b' })] + }, + + // ----------- Keyframe sequence: offset handling ----------- + + { + desc: 'a keyframe sequence with duplicate values for a given interior' + + ' offset', + input: [{ offset: 0.0, left: '10px' }, + { offset: 0.5, left: '20px' }, + { offset: 0.5, left: '30px' }, + { offset: 0.5, left: '40px' }, + { offset: 1.0, left: '50px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.5), { left: '20px' }), + keyframe(offset(0.5), { left: '30px' }), + keyframe(offset(0.5), { left: '40px' }), + keyframe(offset(1), { left: '50px' })], + }, + { + desc: 'a keyframe sequence with duplicate values for offsets 0 and 1', + input: [{ offset: 0, left: '10px' }, + { offset: 0, left: '20px' }, + { offset: 0, left: '30px' }, + { offset: 1, left: '40px' }, + { offset: 1, left: '50px' }, + { offset: 1, left: '60px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0), { left: '20px' }), + keyframe(offset(0), { left: '30px' }), + keyframe(offset(1), { left: '40px' }), + keyframe(offset(1), { left: '50px' }), + keyframe(offset(1), { left: '60px' })], + }, + { + desc: 'a two property four keyframe sequence', + input: [{ offset: 0, left: '10px' }, + { offset: 0, top: '20px' }, + { offset: 1, top: '30px' }, + { offset: 1, left: '40px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0), { top: '20px' }), + keyframe(offset(1), { top: '30px' }), + keyframe(offset(1), { left: '40px' })], + }, + { + desc: 'a single keyframe sequence with omitted offset', + input: [{ left: '10px' }], + output: [keyframe(computedOffset(1), { left: '10px' })], + }, + { + desc: 'a single keyframe sequence with null offset', + input: [{ offset: null, left: '10px' }], + output: [keyframe(computedOffset(1), { left: '10px' })], + }, + { + desc: 'a single keyframe sequence with string offset', + input: [{ offset: '0.5', left: '10px' }], + output: [keyframe(offset(0.5), { left: '10px' })], + }, + { + desc: 'a one property keyframe sequence with some omitted offsets', + input: [{ offset: 0.00, left: '10px' }, + { offset: 0.25, left: '20px' }, + { left: '30px' }, + { left: '40px' }, + { offset: 1.00, left: '50px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(computedOffset(0.5), { left: '30px' }), + keyframe(computedOffset(0.75), { left: '40px' }), + keyframe(offset(1), { left: '50px' })], + }, + { + desc: 'a one property keyframe sequence with some null offsets', + input: [{ offset: 0.00, left: '10px' }, + { offset: 0.25, left: '20px' }, + { offset: null, left: '30px' }, + { offset: null, left: '40px' }, + { offset: 1.00, left: '50px' }], + output: [keyframe(offset(0), { left: '10px' }), + keyframe(offset(0.25), { left: '20px' }), + keyframe(computedOffset(0.5), { left: '30px' }), + keyframe(computedOffset(0.75), { left: '40px' }), + keyframe(offset(1), { left: '50px' })], + }, + { + desc: 'a two property keyframe sequence with some omitted offsets', + input: [{ offset: 0.00, left: '10px', top: '20px' }, + { offset: 0.25, left: '30px' }, + { left: '40px' }, + { left: '50px', top: '60px' }, + { offset: 1.00, left: '70px', top: '80px' }], + output: [keyframe(offset(0), { left: '10px', top: '20px' }), + keyframe(offset(0.25), { left: '30px' }), + keyframe(computedOffset(0.5), { left: '40px' }), + keyframe(computedOffset(0.75), { left: '50px', top: '60px' }), + keyframe(offset(1), { left: '70px', top: '80px' })], + }, + { + desc: 'a one property keyframe sequence with all omitted offsets', + input: [{ left: '10px' }, + { left: '20px' }, + { left: '30px' }, + { left: '40px' }, + { left: '50px' }], + output: [keyframe(computedOffset(0), { left: '10px' }), + keyframe(computedOffset(0.25), { left: '20px' }), + keyframe(computedOffset(0.5), { left: '30px' }), + keyframe(computedOffset(0.75), { left: '40px' }), + keyframe(computedOffset(1), { left: '50px' })], + }, + + // ----------- Keyframe sequence: easing handling ----------- + + { + desc: 'a keyframe sequence with different easing values, but the same' + + ' easing value for a given offset', + input: [{ offset: 0.0, easing: 'ease', left: '10px'}, + { offset: 0.0, easing: 'ease', top: '20px'}, + { offset: 0.5, easing: 'linear', left: '30px' }, + { offset: 0.5, easing: 'linear', top: '40px' }, + { offset: 1.0, easing: 'step-end', left: '50px' }, + { offset: 1.0, easing: 'step-end', top: '60px' }], + output: [keyframe(offset(0), { left: '10px' }, 'ease'), + keyframe(offset(0), { top: '20px' }, 'ease'), + keyframe(offset(0.5), { left: '30px' }, 'linear'), + keyframe(offset(0.5), { top: '40px' }, 'linear'), + keyframe(offset(1), { left: '50px' }, 'steps(1)'), + keyframe(offset(1), { top: '60px' }, 'steps(1)')], + }, + + // ----------- Keyframe sequence: composite handling ----------- + + { + desc: 'a keyframe sequence with different composite values, but the' + + ' same composite value for a given offset', + input: [{ offset: 0.0, composite: 'replace', left: '10px' }, + { offset: 0.0, composite: 'replace', top: '20px' }, + { offset: 0.5, composite: 'add', left: '30px' }, + { offset: 0.5, composite: 'add', top: '40px' }, + { offset: 1.0, composite: 'replace', left: '50px' }, + { offset: 1.0, composite: 'replace', top: '60px' }], + output: [keyframe(offset(0), { left: '10px' }, 'linear', 'replace'), + keyframe(offset(0), { top: '20px' }, 'linear', 'replace'), + keyframe(offset(0.5), { left: '30px' }, 'linear', 'add'), + keyframe(offset(0.5), { top: '40px' }, 'linear', 'add'), + keyframe(offset(1), { left: '50px' }, 'linear', 'replace'), + keyframe(offset(1), { top: '60px' }, 'linear', 'replace')], + }, +]; + +const gInvalidKeyframesTests = [ + { + desc: 'keyframes with an out-of-bounded positive offset', + input: [ { opacity: 0 }, + { opacity: 0.5, offset: 2 }, + { opacity: 1 } ], + }, + { + desc: 'keyframes with an out-of-bounded negative offset', + input: [ { opacity: 0 }, + { opacity: 0.5, offset: -1 }, + { opacity: 1 } ], + }, + { + desc: 'property-indexed keyframes not loosely sorted by offset', + input: { opacity: [ 0, 1 ], offset: [ 1, 0 ] }, + }, + { + desc: 'property-indexed keyframes not loosely sorted by offset even' + + ' though not all offsets are specified', + input: { opacity: [ 0, 0.5, 1 ], offset: [ 0.5, 0 ] }, + }, + { + desc: 'property-indexed keyframes with offsets out of range', + input: { opacity: [ 0, 0.5, 1 ], offset: [ 0, 1.1 ] }, + }, + { + desc: 'keyframes not loosely sorted by offset', + input: [ { opacity: 0, offset: 1 }, + { opacity: 1, offset: 0 } ], + }, + { + desc: 'property-indexed keyframes with an invalid easing value', + input: { opacity: [ 0, 0.5, 1 ], + easing: 'inherit' }, + }, + { + desc: 'property-indexed keyframes with an invalid easing value as one of' + + ' the array values', + input: { opacity: [ 0, 0.5, 1 ], + easing: [ 'ease-in', 'inherit' ] }, + }, + { + desc: 'property-indexed keyframe with an invalid easing in the unused' + + ' part of the array of easings', + input: { left: ['10px', '20px', '30px'], + easing: ['steps(1)', 'steps(2)', 'steps(3)', 'invalid'] }, + }, + { + desc: 'empty property-indexed keyframe with an invalid easing', + input: { easing: 'invalid' }, + }, + { + desc: 'empty property-indexed keyframe with an invalid easings array', + input: { easing: ['invalid'] }, + }, + { + desc: 'a keyframe sequence with an invalid easing value', + input: [ { opacity: 0, easing: 'jumpy' }, + { opacity: 1 } ], + }, + { + desc: 'property-indexed keyframes with an invalid composite value', + input: { opacity: [ 0, 0.5, 1 ], + composite: 'alternate' }, + }, + { + desc: 'property-indexed keyframes with an invalid composite value as one' + + ' of the array values', + input: { opacity: [ 0, 0.5, 1 ], + composite: [ 'add', 'alternate' ] }, + }, + { + desc: 'keyframes with an invalid composite value', + input: [ { opacity: 0, composite: 'alternate' }, + { opacity: 1 } ], + }, +]; + + +const gKeyframeSerializationTests = [ + { + desc: 'a on keyframe sequence which requires value serilaization of its' + + ' values', + input: [{offset: 0, backgroundColor: 'rgb(1,2,3)' }], + output: [keyframe(offset(0), { backgroundColor: 'rgb(1, 2, 3)' })], + }, +]; + + + +// ------------------------------ +// KeyframeEffectOptions +// ------------------------------ + +const gKeyframeEffectOptionTests = [ + { + desc: 'an empty KeyframeEffectOptions object', + input: { }, + expected: { }, + }, + { + desc: 'a normal KeyframeEffectOptions object', + input: { delay: 1000, + fill: 'auto', + iterations: 5.5, + duration: 'auto', + direction: 'alternate' }, + expected: { delay: 1000, + fill: 'auto', + iterations: 5.5, + duration: 'auto', + direction: 'alternate' }, + }, + { + desc: 'a double value', + input: 3000, + expected: { duration: 3000 }, + }, + { + desc: '+Infinity', + input: Infinity, + expected: { duration: Infinity }, + }, + { + desc: 'an Infinity duration', + input: { duration: Infinity }, + expected: { duration: Infinity }, + }, + { + desc: 'an auto duration', + input: { duration: 'auto' }, + expected: { duration: 'auto' }, + }, + { + desc: 'an Infinity iterations', + input: { iterations: Infinity }, + expected: { iterations: Infinity }, + }, + { + desc: 'an auto fill', + input: { fill: 'auto' }, + expected: { fill: 'auto' }, + }, + { + desc: 'a forwards fill', + input: { fill: 'forwards' }, + expected: { fill: 'forwards' }, + } +]; + +const gInvalidKeyframeEffectOptionTests = [ + { desc: '-Infinity', input: -Infinity }, + { desc: 'NaN', input: NaN }, + { desc: 'a negative value', input: -1 }, + { desc: 'a negative Infinity duration', input: { duration: -Infinity } }, + { desc: 'a NaN duration', input: { duration: NaN } }, + { desc: 'a negative duration', input: { duration: -1 } }, + { desc: 'a string duration', input: { duration: 'merrychristmas' } }, + { desc: 'a negative Infinity iterations', input: { iterations: -Infinity} }, + { desc: 'a NaN iterations', input: { iterations: NaN } }, + { desc: 'a negative iterations', input: { iterations: -1 } }, + { desc: 'a blank easing', input: { easing: '' } }, + { desc: 'an unrecognized easing', input: { easing: 'unrecognised' } }, + { desc: 'an \'initial\' easing', input: { easing: 'initial' } }, + { desc: 'an \'inherit\' easing', input: { easing: 'inherit' } }, + { desc: 'a variable easing', input: { easing: 'var(--x)' } }, + { desc: 'a multi-value easing', input: { easing: 'ease-in-out, ease-out' } }, +]; + +// There is currently only ScrollTimeline that can be constructed and used here +// beyond document timeline. Given that ScrollTimeline is not stable as of yet +// it's tested in scroll-animations/animation-with-animatable-interface.html. +const gAnimationTimelineTests = [ + { + expectedTimeline: document.timeline, + expectedTimelineDescription: 'document.timeline', + description: 'with no timeline parameter' + }, + { + timeline: undefined, + expectedTimeline: document.timeline, + expectedTimelineDescription: 'document.timeline', + description: 'with undefined timeline' + }, + { + timeline: null, + expectedTimeline: null, + expectedTimelineDescription: 'null', + description: 'with null timeline' + }, + { + timeline: document.timeline, + expectedTimeline: document.timeline, + expectedTimelineDescription: 'document.timeline', + description: 'with DocumentTimeline' + }, +]; \ No newline at end of file diff --git a/testing/web-platform/tests/web-animations/resources/keyframe-utils.js b/testing/web-platform/tests/web-animations/resources/keyframe-utils.js new file mode 100644 index 0000000000..60fb9781a0 --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/keyframe-utils.js @@ -0,0 +1,51 @@ +'use strict'; + +// ======================================= +// +// Utility functions for testing keyframes +// +// ======================================= + + +// ------------------------------ +// Helper functions +// ------------------------------ + +/** + * Test equality between two lists of computed keyframes + * @param {Array.} a - actual computed keyframes + * @param {Array.} b - expected computed keyframes + */ +function assert_frame_lists_equal(a, b, message) { + assert_equals(a.length, b.length, `number of frames: ${(message || '')}`); + for (let i = 0; i < Math.min(a.length, b.length); i++) { + assert_frames_equal(a[i], b[i], + `ComputedKeyframe #${i}: ${(message || '')}`); + } +} + +/** Helper for assert_frame_lists_equal */ +function assert_frames_equal(a, b, name) { + assert_equals(Object.keys(a).sort().toString(), + Object.keys(b).sort().toString(), + `properties on ${name} should match`); + // Iterates sorted keys to ensure stable failures. + for (const p of Object.keys(a).sort()) { + if (typeof b[p] == 'number') + assert_approx_equals(a[p], b[p], 1e-6, `value for '${p}' on ${name}`); + else if (typeof b[p] == 'object') { + for (const key in b[p]) { + if (typeof b[p][key] == 'number') { + assert_approx_equals(a[p][key], b[p][key], 1e-6, + `value for '${p}.${key}' on ${name}`); + } else { + assert_equals((a[p][key] || 'undefined').toString(), + b[p][key].toString(), + `value for '${p}.${key}' on ${name}`); + } + } + } + else + assert_equals(a[p], b[p], `value for '${p}' on ${name}`); + } +} diff --git a/testing/web-platform/tests/web-animations/resources/timing-override.js b/testing/web-platform/tests/web-animations/resources/timing-override.js new file mode 100644 index 0000000000..a1d65030f0 --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/timing-override.js @@ -0,0 +1,18 @@ +// Firefox implements unconditional clamping of 20 usec; and for certain web-animation tests, +// we hit some test failures because the Time Precision is too small. We override these functions +// on a per-test basis for Firefox only. +if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1){ + window.assert_times_equal = (actual, expected, description) => { + let TIME_PRECISION = 0.02; + assert_approx_equals(actual, expected, TIME_PRECISION * 2, description); + }; + + window.assert_time_equals_literal = (actual, expected, description) => { + let TIME_PRECISION = 0.02; + if (Math.abs(expected) === Infinity) { + assert_equals(actual, expected, description); + } else { + assert_approx_equals(actual, expected, TIME_PRECISION, description); + } + } +} diff --git a/testing/web-platform/tests/web-animations/resources/timing-tests.js b/testing/web-platform/tests/web-animations/resources/timing-tests.js new file mode 100644 index 0000000000..4b0f021f74 --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/timing-tests.js @@ -0,0 +1,46 @@ +'use strict'; + +// ================================= +// +// Common timing parameter test data +// +// ================================= + + +// ------------------------------ +// Delay values +// ------------------------------ + +const gBadDelayValues = [ + NaN, Infinity, -Infinity +]; + +// ------------------------------ +// Duration values +// ------------------------------ + +const gGoodDurationValues = [ + { specified: 123.45, computed: 123.45 }, + { specified: 'auto', computed: 0 }, + { specified: Infinity, computed: Infinity }, +]; + +const gBadDurationValues = [ + -1, NaN, -Infinity, 'abc', '100' +]; + +// ------------------------------ +// iterationStart values +// ------------------------------ + +const gBadIterationStartValues = [ + -1, NaN, Infinity, -Infinity +]; + +// ------------------------------ +// iterations values +// ------------------------------ + +const gBadIterationsValues = [ + -1, -Infinity, NaN +]; diff --git a/testing/web-platform/tests/web-animations/resources/timing-utils.js b/testing/web-platform/tests/web-animations/resources/timing-utils.js new file mode 100644 index 0000000000..fba62a1f6d --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/timing-utils.js @@ -0,0 +1,52 @@ +'use strict'; + +// ======================================= +// +// Utility functions for testing timing +// +// ======================================= + + +// ------------------------------ +// Helper functions +// ------------------------------ + +// Utility function to check that a subset of timing properties have their +// default values. +function assert_default_timing_except(effect, propertiesToSkip) { + const defaults = { + delay: 0, + endDelay: 0, + fill: 'auto', + iterationStart: 0, + iterations: 1, + duration: 'auto', + direction: 'normal', + easing: 'linear', + }; + + for (const prop of Object.keys(defaults)) { + if (propertiesToSkip.includes(prop)) { + continue; + } + + assert_equals( + effect.getTiming()[prop], + defaults[prop], + `${prop} parameter has default value:` + ); + } +} + +function waitForAnimationTime(animation, time) { + return new Promise((resolve) => { + function raf() { + if (animation.currentTime < time) { + requestAnimationFrame(raf); + } else { + resolve(); + } + } + requestAnimationFrame(raf); + }); +} diff --git a/testing/web-platform/tests/web-animations/resources/xhr-doc.py b/testing/web-platform/tests/web-animations/resources/xhr-doc.py new file mode 100644 index 0000000000..0023a44e22 --- /dev/null +++ b/testing/web-platform/tests/web-animations/resources/xhr-doc.py @@ -0,0 +1,5 @@ +def main(request, response): + headers = [(b"Content-type", b"text/html;charset=utf-8")] + content = u"
" + + return headers, content diff --git a/testing/web-platform/tests/web-animations/responsive/assorted-lengths.html b/testing/web-platform/tests/web-animations/responsive/assorted-lengths.html new file mode 100644 index 0000000000..50e01f766c --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/assorted-lengths.html @@ -0,0 +1,102 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/backgroundPosition.html b/testing/web-platform/tests/web-animations/responsive/backgroundPosition.html new file mode 100644 index 0000000000..cd6c6991a3 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/backgroundPosition.html @@ -0,0 +1,25 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/backgroundSize.html b/testing/web-platform/tests/web-animations/responsive/backgroundSize.html new file mode 100644 index 0000000000..1e9ccf96a1 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/backgroundSize.html @@ -0,0 +1,22 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/baselineShift.html b/testing/web-platform/tests/web-animations/responsive/baselineShift.html new file mode 100644 index 0000000000..4ccaaf33ac --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/baselineShift.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/web-animations/responsive/borderImageWidth.html b/testing/web-platform/tests/web-animations/responsive/borderImageWidth.html new file mode 100644 index 0000000000..4b832889bd --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/borderImageWidth.html @@ -0,0 +1,22 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/borderRadius.html b/testing/web-platform/tests/web-animations/responsive/borderRadius.html new file mode 100644 index 0000000000..c59696ec90 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/borderRadius.html @@ -0,0 +1,39 @@ + + + +
+ diff --git a/testing/web-platform/tests/web-animations/responsive/borderWidth.html b/testing/web-platform/tests/web-animations/responsive/borderWidth.html new file mode 100644 index 0000000000..090d9a185a --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/borderWidth.html @@ -0,0 +1,33 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/boxShadow.html b/testing/web-platform/tests/web-animations/responsive/boxShadow.html new file mode 100644 index 0000000000..bd1911132d --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/boxShadow.html @@ -0,0 +1,30 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/clip.html b/testing/web-platform/tests/web-animations/responsive/clip.html new file mode 100644 index 0000000000..316e977576 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/clip.html @@ -0,0 +1,45 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/columnCount.html b/testing/web-platform/tests/web-animations/responsive/columnCount.html new file mode 100644 index 0000000000..c92d5cbf8f --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/columnCount.html @@ -0,0 +1,32 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/columnGap.html b/testing/web-platform/tests/web-animations/responsive/columnGap.html new file mode 100644 index 0000000000..43d44152cb --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/columnGap.html @@ -0,0 +1,49 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/d.html b/testing/web-platform/tests/web-animations/responsive/d.html new file mode 100644 index 0000000000..55c6c23a0e --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/d.html @@ -0,0 +1,27 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/font-size-adjust.html b/testing/web-platform/tests/web-animations/responsive/font-size-adjust.html new file mode 100644 index 0000000000..282ec7fede --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/font-size-adjust.html @@ -0,0 +1,32 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/fontSize.html b/testing/web-platform/tests/web-animations/responsive/fontSize.html new file mode 100644 index 0000000000..d65aeacd46 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/fontSize.html @@ -0,0 +1,72 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/fontWeight.html b/testing/web-platform/tests/web-animations/responsive/fontWeight.html new file mode 100644 index 0000000000..e8fbbae0e7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/fontWeight.html @@ -0,0 +1,42 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/lineHeight.html b/testing/web-platform/tests/web-animations/responsive/lineHeight.html new file mode 100644 index 0000000000..03d45e54c1 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/lineHeight.html @@ -0,0 +1,80 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/minHeight.html b/testing/web-platform/tests/web-animations/responsive/minHeight.html new file mode 100644 index 0000000000..07474bc3f4 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/minHeight.html @@ -0,0 +1,35 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/offset-path.html b/testing/web-platform/tests/web-animations/responsive/offset-path.html new file mode 100644 index 0000000000..eff8ede60f --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/offset-path.html @@ -0,0 +1,27 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/offsetDistance.html b/testing/web-platform/tests/web-animations/responsive/offsetDistance.html new file mode 100644 index 0000000000..d56da9c767 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/offsetDistance.html @@ -0,0 +1,57 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/offsetRotate.html b/testing/web-platform/tests/web-animations/responsive/offsetRotate.html new file mode 100644 index 0000000000..f0957e15c5 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/offsetRotate.html @@ -0,0 +1,43 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/opacity.html b/testing/web-platform/tests/web-animations/responsive/opacity.html new file mode 100644 index 0000000000..0bedfc879a --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/opacity.html @@ -0,0 +1,48 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/perspective.html b/testing/web-platform/tests/web-animations/responsive/perspective.html new file mode 100644 index 0000000000..f32b4dbad3 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/perspective.html @@ -0,0 +1,49 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/resources/block.html b/testing/web-platform/tests/web-animations/responsive/resources/block.html new file mode 100644 index 0000000000..8284055969 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/resources/block.html @@ -0,0 +1,10 @@ + + +
\ No newline at end of file diff --git a/testing/web-platform/tests/web-animations/responsive/rotate.html b/testing/web-platform/tests/web-animations/responsive/rotate.html new file mode 100644 index 0000000000..b0e4213200 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/rotate.html @@ -0,0 +1,22 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/rowGap.html b/testing/web-platform/tests/web-animations/responsive/rowGap.html new file mode 100644 index 0000000000..b7dae62f23 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/rowGap.html @@ -0,0 +1,49 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/shapeMargin.html b/testing/web-platform/tests/web-animations/responsive/shapeMargin.html new file mode 100644 index 0000000000..02d6151ad0 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/shapeMargin.html @@ -0,0 +1,24 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/shapeOutside.html b/testing/web-platform/tests/web-animations/responsive/shapeOutside.html new file mode 100644 index 0000000000..2a54576a33 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/shapeOutside.html @@ -0,0 +1,59 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/strokeDasharray.html b/testing/web-platform/tests/web-animations/responsive/strokeDasharray.html new file mode 100644 index 0000000000..a1ccb30e90 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/strokeDasharray.html @@ -0,0 +1,28 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/text-size-adjust.html b/testing/web-platform/tests/web-animations/responsive/text-size-adjust.html new file mode 100644 index 0000000000..203b067a77 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/text-size-adjust.html @@ -0,0 +1,29 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/textIndent.html b/testing/web-platform/tests/web-animations/responsive/textIndent.html new file mode 100644 index 0000000000..430417d28b --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/textIndent.html @@ -0,0 +1,59 @@ + + + +
+
+
+ diff --git a/testing/web-platform/tests/web-animations/responsive/to-color-change.html b/testing/web-platform/tests/web-animations/responsive/to-color-change.html new file mode 100644 index 0000000000..6c3fcccf62 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/to-color-change.html @@ -0,0 +1,253 @@ + + + + + +
+
+
+
+ + + + +
Unvisited
+
Visited
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/to-inherited-change.html b/testing/web-platform/tests/web-animations/responsive/to-inherited-change.html new file mode 100644 index 0000000000..96ef5d24e1 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/to-inherited-change.html @@ -0,0 +1,56 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/to-style-change.html b/testing/web-platform/tests/web-animations/responsive/to-style-change.html new file mode 100644 index 0000000000..8f4bf4c8b5 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/to-style-change.html @@ -0,0 +1,44 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility-ref.html b/testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility-ref.html new file mode 100644 index 0000000000..dab5bed7c8 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility-ref.html @@ -0,0 +1,10 @@ + + +
+ +
\ No newline at end of file diff --git a/testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility.html b/testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility.html new file mode 100644 index 0000000000..f50ffaad34 --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/toggle-animated-iframe-visibility.html @@ -0,0 +1,55 @@ + + + +CSS Test (Animations): Unhiding iframe visibility should restart animation. + + + + +
+ +
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/transform.html b/testing/web-platform/tests/web-animations/responsive/transform.html new file mode 100644 index 0000000000..d57f8b136a --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/transform.html @@ -0,0 +1,22 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/translate.html b/testing/web-platform/tests/web-animations/responsive/translate.html new file mode 100644 index 0000000000..8df4d8577d --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/translate.html @@ -0,0 +1,22 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/responsive/verticalAlign.html b/testing/web-platform/tests/web-animations/responsive/verticalAlign.html new file mode 100644 index 0000000000..af81fa481b --- /dev/null +++ b/testing/web-platform/tests/web-animations/responsive/verticalAlign.html @@ -0,0 +1,22 @@ + + + + +
+
+
+ + diff --git a/testing/web-platform/tests/web-animations/testcommon.js b/testing/web-platform/tests/web-animations/testcommon.js new file mode 100644 index 0000000000..5b22c658d5 --- /dev/null +++ b/testing/web-platform/tests/web-animations/testcommon.js @@ -0,0 +1,342 @@ +'use strict'; + +const MS_PER_SEC = 1000; + +// The recommended minimum precision to use for time values[1]. +// +// [1] https://drafts.csswg.org/web-animations/#precision-of-time-values +const TIME_PRECISION = 0.0005; // ms + +// Allow implementations to substitute an alternative method for comparing +// times based on their precision requirements. +if (!window.assert_times_equal) { + window.assert_times_equal = (actual, expected, description) => { + assert_approx_equals(actual, expected, TIME_PRECISION * 2, description); + }; +} + +// Allow implementations to substitute an alternative method for comparing +// times based on their precision requirements. +if (!window.assert_time_greater_than_equal) { + window.assert_time_greater_than_equal = (actual, expected, description) => { + assert_greater_than_equal(actual, expected - 2 * TIME_PRECISION, + description); + }; +} + +// Allow implementations to substitute an alternative method for comparing +// a time value based on its precision requirements with a fixed value. +if (!window.assert_time_equals_literal) { + window.assert_time_equals_literal = (actual, expected, description) => { + if (Math.abs(expected) === Infinity) { + assert_equals(actual, expected, description); + } else { + assert_approx_equals(actual, expected, TIME_PRECISION, description); + } + } +} + +// creates div element, appends it to the document body and +// removes the created element during test cleanup +function createDiv(test, doc) { + return createElement(test, 'div', doc); +} + +// creates element of given tagName, appends it to the document body and +// removes the created element during test cleanup +// if tagName is null or undefined, returns div element +function createElement(test, tagName, doc) { + if (!doc) { + doc = document; + } + const element = doc.createElement(tagName || 'div'); + doc.body.appendChild(element); + test.add_cleanup(() => { + element.remove(); + }); + return element; +} + +// Creates a style element with the specified rules, appends it to the document +// head and removes the created element during test cleanup. +// |rules| is an object. For example: +// { '@keyframes anim': '' , +// '.className': 'animation: anim 100s;' }; +// or +// { '.className1::before': 'content: ""; width: 0px; transition: all 10s;', +// '.className2::before': 'width: 100px;' }; +// The object property name could be a keyframes name, or a selector. +// The object property value is declarations which are property:value pairs +// split by a space. +function createStyle(test, rules, doc) { + if (!doc) { + doc = document; + } + const extraStyle = doc.createElement('style'); + doc.head.appendChild(extraStyle); + if (rules) { + const sheet = extraStyle.sheet; + for (const selector in rules) { + sheet.insertRule(`${selector}{${rules[selector]}}`, + sheet.cssRules.length); + } + } + test.add_cleanup(() => { + extraStyle.remove(); + }); +} + +// Cubic bezier with control points (0, 0), (x1, y1), (x2, y2), and (1, 1). +function cubicBezier(x1, y1, x2, y2) { + const xForT = t => { + const omt = 1-t; + return 3 * omt * omt * t * x1 + 3 * omt * t * t * x2 + t * t * t; + }; + + const yForT = t => { + const omt = 1-t; + return 3 * omt * omt * t * y1 + 3 * omt * t * t * y2 + t * t * t; + }; + + const tForX = x => { + // Binary subdivision. + let mint = 0, maxt = 1; + for (let i = 0; i < 30; ++i) { + const guesst = (mint + maxt) / 2; + const guessx = xForT(guesst); + if (x < guessx) { + maxt = guesst; + } else { + mint = guesst; + } + } + return (mint + maxt) / 2; + }; + + return x => { + if (x == 0) { + return 0; + } + if (x == 1) { + return 1; + } + return yForT(tForX(x)); + }; +} + +function stepEnd(nsteps) { + return x => Math.floor(x * nsteps) / nsteps; +} + +function stepStart(nsteps) { + return x => { + const result = Math.floor(x * nsteps + 1.0) / nsteps; + return (result > 1.0) ? 1.0 : result; + }; +} + +function waitForAnimationFrames(frameCount) { + return new Promise(resolve => { + function handleFrame() { + if (--frameCount <= 0) { + resolve(); + } else { + window.requestAnimationFrame(handleFrame); // wait another frame + } + } + window.requestAnimationFrame(handleFrame); + }); +} + +// Continually calls requestAnimationFrame until |minDelay| has elapsed +// as recorded using document.timeline.currentTime (i.e. frame time not +// wall-clock time). +function waitForAnimationFramesWithDelay(minDelay) { + const startTime = document.timeline.currentTime; + return new Promise(resolve => { + (function handleFrame() { + if (document.timeline.currentTime - startTime >= minDelay) { + resolve(); + } else { + window.requestAnimationFrame(handleFrame); + } + }()); + }); +} + +function runAndWaitForFrameUpdate(callback) { + return new Promise(resolve => { + window.requestAnimationFrame(() => { + callback(); + window.requestAnimationFrame(resolve); + }); + }); +} + +// Waits for a requestAnimationFrame callback in the next refresh driver tick. +function waitForNextFrame() { + const timeAtStart = document.timeline.currentTime; + return new Promise(resolve => { + (function handleFrame() { + if (timeAtStart === document.timeline.currentTime) { + window.requestAnimationFrame(handleFrame); + } else { + resolve(); + } + }()); + }); +} + +async function insertFrameAndAwaitLoad(test, iframe, doc) { + const eventWatcher = new EventWatcher(test, iframe, ['load']); + const event_promise = eventWatcher.wait_for('load'); + + doc.body.appendChild(iframe); + test.add_cleanup(() => { doc.body.removeChild(iframe); }); + + await event_promise; +} + +// Returns 'matrix()' or 'matrix3d()' function string generated from an array. +function createMatrixFromArray(array) { + return (array.length == 16 ? 'matrix3d' : 'matrix') + `(${array.join()})`; +} + +// Returns 'matrix3d()' function string equivalent to +// 'rotate3d(x, y, z, radian)'. +function rotate3dToMatrix3d(x, y, z, radian) { + return createMatrixFromArray(rotate3dToMatrix(x, y, z, radian)); +} + +// Returns an array of the 4x4 matrix equivalent to 'rotate3d(x, y, z, radian)'. +// https://drafts.csswg.org/css-transforms-2/#Rotate3dDefined +function rotate3dToMatrix(x, y, z, radian) { + const sc = Math.sin(radian / 2) * Math.cos(radian / 2); + const sq = Math.sin(radian / 2) * Math.sin(radian / 2); + + // Normalize the vector. + const length = Math.sqrt(x*x + y*y + z*z); + x /= length; + y /= length; + z /= length; + + return [ + 1 - 2 * (y*y + z*z) * sq, + 2 * (x * y * sq + z * sc), + 2 * (x * z * sq - y * sc), + 0, + 2 * (x * y * sq - z * sc), + 1 - 2 * (x*x + z*z) * sq, + 2 * (y * z * sq + x * sc), + 0, + 2 * (x * z * sq + y * sc), + 2 * (y * z * sq - x * sc), + 1 - 2 * (x*x + y*y) * sq, + 0, + 0, + 0, + 0, + 1 + ]; +} + +// Compare matrix string like 'matrix(1, 0, 0, 1, 100, 0)' with tolerances. +function assert_matrix_equals(actual, expected, description) { + const matrixRegExp = /^matrix(?:3d)*\((.+)\)/; + assert_regexp_match(actual, matrixRegExp, + 'Actual value is not a matrix') + assert_regexp_match(expected, matrixRegExp, + 'Expected value is not a matrix'); + + const actualMatrixArray = + actual.match(matrixRegExp)[1].split(',').map(Number); + const expectedMatrixArray = + expected.match(matrixRegExp)[1].split(',').map(Number); + + assert_equals(actualMatrixArray.length, expectedMatrixArray.length, + `dimension of the matrix: ${description}`); + for (let i = 0; i < actualMatrixArray.length; i++) { + assert_approx_equals(actualMatrixArray[i], expectedMatrixArray[i], 0.0001, + `expected ${expected} but got ${actual}: ${description}`); + } +} + +// Compare rotate3d vector like '0 1 0 45deg' with tolerances. +function assert_rotate3d_equals(actual, expected, description) { + const rotationRegExp =/^((([+-]?\d+(\.+\d+)?\s){3})?\d+(\.+\d+)?)deg/; + + assert_regexp_match(actual, rotationRegExp, + 'Actual value is not a rotate3d vector') + assert_regexp_match(expected, rotationRegExp, + 'Expected value is not a rotate3d vector'); + + const actualRotationVector = + actual.match(rotationRegExp)[1].split(' ').map(Number); + const expectedRotationVector = + expected.match(rotationRegExp)[1].split(' ').map(Number); + + assert_equals(actualRotationVector.length, expectedRotationVector.length, + `dimension of the matrix: ${description}`); + for (let i = 0; i < actualRotationVector.length; i++) { + assert_approx_equals( + actualRotationVector[i], + expectedRotationVector[i], + 0.0001, + `expected ${expected} but got ${actual}: ${description}`); + } +} + +function assert_phase_at_time(animation, phase, currentTime) { + animation.currentTime = currentTime; + assert_phase(animation, phase); +} + +function assert_phase(animation, phase) { + const fillMode = animation.effect.getTiming().fill; + const currentTime = animation.currentTime; + + if (phase === 'active') { + // If the fill mode is 'none', then progress will only be non-null if we + // are in the active phase. + animation.effect.updateTiming({ fill: 'none' }); + assert_not_equals(animation.effect.getComputedTiming().progress, null, + 'Animation effect is in active phase when current time ' + + `is ${currentTime}.`); + } else { + // The easiest way to distinguish between the 'before' phase and the 'after' + // phase is to toggle the fill mode. For example, if the progress is null + // when the fill mode is 'none' but non-null when the fill mode is + // 'backwards' then we are in the before phase. + animation.effect.updateTiming({ fill: 'none' }); + assert_equals(animation.effect.getComputedTiming().progress, null, + `Animation effect is in ${phase} phase when current time ` + + `is ${currentTime} (progress is null with 'none' fill mode)`); + + animation.effect.updateTiming({ + fill: phase === 'before' ? 'backwards' : 'forwards', + }); + assert_not_equals(animation.effect.getComputedTiming().progress, null, + `Animation effect is in ${phase} phase when current ` + + `time is ${currentTime} (progress is non-null with ` + + `appropriate fill mode)`); + } + + // Reset fill mode to avoid side-effects. + animation.effect.updateTiming({ fill: fillMode }); +} + + +// Use with reftest-wait to wait until compositor commits are no longer deferred +// before taking the screenshot. +// crbug.com/1378671 +async function waitForCompositorReady() { + const animation = + document.body.animate({ opacity: [ 1, 1 ] }, {duration: 1 }); + return animation.finished; +} + +async function takeScreenshotOnAnimationsReady() { + await Promise.all(document.getAnimations().map(a => a.ready)); + requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)); +} + diff --git a/testing/web-platform/tests/web-animations/timing-model/animation-effects/active-time.html b/testing/web-platform/tests/web-animations/timing-model/animation-effects/active-time.html new file mode 100644 index 0000000000..a2feb2323c --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animation-effects/active-time.html @@ -0,0 +1,141 @@ + + +Active time + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animation-effects/current-iteration.html b/testing/web-platform/tests/web-animations/timing-model/animation-effects/current-iteration.html new file mode 100644 index 0000000000..24464ce05f --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animation-effects/current-iteration.html @@ -0,0 +1,620 @@ + + +Current iteration + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animation-effects/local-time.html b/testing/web-platform/tests/web-animations/timing-model/animation-effects/local-time.html new file mode 100644 index 0000000000..79437d9f54 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animation-effects/local-time.html @@ -0,0 +1,29 @@ + + +Local time + + + + + + + diff --git a/testing/web-platform/tests/web-animations/timing-model/animation-effects/phases-and-states.html b/testing/web-platform/tests/web-animations/timing-model/animation-effects/phases-and-states.html new file mode 100644 index 0000000000..a33dbf517e --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animation-effects/phases-and-states.html @@ -0,0 +1,149 @@ + + +Phases and states + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html b/testing/web-platform/tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html new file mode 100644 index 0000000000..3c42f79a71 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html @@ -0,0 +1,600 @@ + + +Simple iteration progress + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html new file mode 100644 index 0000000000..f296ac4da7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/canceling-an-animation.html @@ -0,0 +1,127 @@ + + +Canceling an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation-ref.html b/testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation-ref.html new file mode 100644 index 0000000000..d1ee52a553 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation-ref.html @@ -0,0 +1,19 @@ + +Reference for document timeline animation + + +
+

+ This test creates a document timeline animation. If any blue pixels appear + in the screenshot, the test fails. +

+ \ No newline at end of file diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation.html new file mode 100644 index 0000000000..7d4dc76849 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/document-timeline-animation.html @@ -0,0 +1,63 @@ + + + + +document timeline animation + + + + + + +
+
+

+ This test creates a document timeline animation. If any blue pixels appear + in the screenshot, the test fails. +

+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html new file mode 100644 index 0000000000..fbf6558f78 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/finishing-an-animation.html @@ -0,0 +1,330 @@ + + +Finishing an animation + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation-ref.html b/testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation-ref.html new file mode 100644 index 0000000000..6b358bd4e7 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation-ref.html @@ -0,0 +1,19 @@ + +Reference for infinite duration animation + + +

+ This test creates an infinite duration animations, which should be stuck at + a progress of 0. If any blue pixels appear in the screenshot, the test + fails. +

+ diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation.html new file mode 100644 index 0000000000..c641e5afa2 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/infinite-duration-animation.html @@ -0,0 +1,64 @@ + + + + +Infinite duration animation + + + + + + +
+
+

+ This test creates an infinite duration animations, which should be stuck at + a progress of 0. If any blue pixels appear in the screenshot, the test + fails. +

+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/invalidating-animation-before-start-time-synced.html b/testing/web-platform/tests/web-animations/timing-model/animations/invalidating-animation-before-start-time-synced.html new file mode 100644 index 0000000000..653e46906a --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/invalidating-animation-before-start-time-synced.html @@ -0,0 +1,71 @@ + + + + + + + +The blue boxes below should stay aligned in the x-axis. +
+
+
diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html new file mode 100644 index 0000000000..dd9522cb35 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/pausing-an-animation.html @@ -0,0 +1,119 @@ + + +Pausing an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html b/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html new file mode 100644 index 0000000000..ec7d8c842f --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/play-states.html @@ -0,0 +1,185 @@ + + +Play states + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html new file mode 100644 index 0000000000..01e036ae57 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/playing-an-animation.html @@ -0,0 +1,177 @@ + + +Playing an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation-ref.html b/testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation-ref.html new file mode 100644 index 0000000000..7bf5b03c1e --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation-ref.html @@ -0,0 +1,17 @@ + +Reference for reverse running animation + + +
+

+ This test animates the box color from green to red and reverses the play + direction shortly after the midpoint. If the box remains red, the test + failed. +

+ diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation.html new file mode 100644 index 0000000000..c9eb2a068e --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/reverse-running-animation.html @@ -0,0 +1,50 @@ + + + + +reverse running animation + + + + + +
+

+ This test animates the box color from green to red and reverses the play + direction shortly after the midpoint. If the box remains red, the test + failed. +

+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/reversing-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/reversing-an-animation.html new file mode 100644 index 0000000000..8d869d72aa --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/reversing-an-animation.html @@ -0,0 +1,266 @@ + + +Reversing an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html new file mode 100644 index 0000000000..dffbeabd59 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html @@ -0,0 +1,171 @@ + + +Seamlessly updating the playback rate of an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-current-time-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-current-time-of-an-animation.html new file mode 100644 index 0000000000..809877345f --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-current-time-of-an-animation.html @@ -0,0 +1,167 @@ + + +Setting the current time of an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-playback-rate-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-playback-rate-of-an-animation.html new file mode 100644 index 0000000000..a1f9e4f3ac --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-playback-rate-of-an-animation.html @@ -0,0 +1,110 @@ + + +Setting the playback rate of an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html new file mode 100644 index 0000000000..fee3f1e0de --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-start-time-of-an-animation.html @@ -0,0 +1,329 @@ + + +Setting the start time of an animation + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html new file mode 100644 index 0000000000..60ea1850fc --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html @@ -0,0 +1,129 @@ + + +Setting the target effect of an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html new file mode 100644 index 0000000000..d4f802152c --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html @@ -0,0 +1,255 @@ + + +Setting the timeline of an animation + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times-ref.html b/testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times-ref.html new file mode 100644 index 0000000000..fc843a132f --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times-ref.html @@ -0,0 +1,20 @@ + + + +Reference for sync start times + + + +

+ This test creates a pair of animations, starts the first animation and then + syncs the second animation to align with the first. The test passes if the + box associated with the first animation is completely occluded by the + second. +

+ diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times.html b/testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times.html new file mode 100644 index 0000000000..e9ef6762ea --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/sync-start-times.html @@ -0,0 +1,72 @@ + + + + +sync start times + + + + + +
+
+

+ This test creates a pair of animations, starts the first animation and then + syncs the second animation to align with the first. The test passes if the + box associated with the first animation is completely occluded by the + second. +

+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/the-current-time-of-an-animation.html b/testing/web-platform/tests/web-animations/timing-model/animations/the-current-time-of-an-animation.html new file mode 100644 index 0000000000..77a6b716d2 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/the-current-time-of-an-animation.html @@ -0,0 +1,75 @@ + + +The current time of an animation + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast-ref.html b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast-ref.html new file mode 100644 index 0000000000..e996815da8 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast-ref.html @@ -0,0 +1,17 @@ + +Reference for update playback rate zero + + +
+

+ This test creates a running animation and changes its playback rate + part way through. If the box remains red when the screenshot is captured + the test fails. +

+ diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast.html b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast.html new file mode 100644 index 0000000000..c3df1c1bf0 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-fast.html @@ -0,0 +1,52 @@ + + + + +Update playback rate zero + + + + + +
+

+ This test creates a running animation and changes its playback rate + part way through. If the box remains red when the screenshot is captured + the test fails. +

+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero-ref.html b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero-ref.html new file mode 100644 index 0000000000..399fd5ce7d --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero-ref.html @@ -0,0 +1,16 @@ + +Reference for update playback rate zero + + +
+

+ This test creates a running animation and halts its playback rate + part way through. If the box transitions to red the test fails. +

+ diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero.html b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero.html new file mode 100644 index 0000000000..db1544ee92 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/update-playback-rate-zero.html @@ -0,0 +1,46 @@ + + + + +Update playback rate zero + + + + + +
+

+ This test creates a running animation and halts its playback rate + part way through. If the box transitions to red the test fails. +

+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/animations/updating-the-finished-state.html b/testing/web-platform/tests/web-animations/timing-model/animations/updating-the-finished-state.html new file mode 100644 index 0000000000..4d3cc7950b --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/animations/updating-the-finished-state.html @@ -0,0 +1,457 @@ + + +Updating the finished state + + + + + + +
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/time-transformations/transformed-progress.html b/testing/web-platform/tests/web-animations/timing-model/time-transformations/transformed-progress.html new file mode 100644 index 0000000000..960e333c09 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/time-transformations/transformed-progress.html @@ -0,0 +1,391 @@ + + +Transformed progress + + + + + + +
+
+ + diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/document-timelines.html b/testing/web-platform/tests/web-animations/timing-model/timelines/document-timelines.html new file mode 100644 index 0000000000..c71d73331c --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/document-timelines.html @@ -0,0 +1,50 @@ + + +Document timelines + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/resources/target-frame.html b/testing/web-platform/tests/web-animations/timing-model/timelines/resources/target-frame.html new file mode 100644 index 0000000000..18ee4fd8a2 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/resources/target-frame.html @@ -0,0 +1,76 @@ + + + + + + + +
+ + + + diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/resources/timeline-frame.html b/testing/web-platform/tests/web-animations/timing-model/timelines/resources/timeline-frame.html new file mode 100644 index 0000000000..9c8cdabc9d --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/resources/timeline-frame.html @@ -0,0 +1,20 @@ + + + + + + + diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/sibling-iframe-timeline.html b/testing/web-platform/tests/web-animations/timing-model/timelines/sibling-iframe-timeline.html new file mode 100644 index 0000000000..8a611c8579 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/sibling-iframe-timeline.html @@ -0,0 +1,58 @@ + + + + + Animate using sibling iframe's timeline + + + + + + + diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/timelines.html b/testing/web-platform/tests/web-animations/timing-model/timelines/timelines.html new file mode 100644 index 0000000000..1609f85939 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/timelines.html @@ -0,0 +1,144 @@ + + +Timelines + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events-replacement.html b/testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events-replacement.html new file mode 100644 index 0000000000..d6ed734831 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events-replacement.html @@ -0,0 +1,1017 @@ + + +Update animations and send events (replacement) + + + + + +
+ diff --git a/testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events.html b/testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events.html new file mode 100644 index 0000000000..255e013f27 --- /dev/null +++ b/testing/web-platform/tests/web-animations/timing-model/timelines/update-and-send-events.html @@ -0,0 +1,257 @@ + + +Update animations and send events + + + + + +
+ -- cgit v1.2.3