summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/svg/animations
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/svg/animations')
-rw-r--r--testing/web-platform/tests/svg/animations/accumulate-values-width-animation.html110
-rw-r--r--testing/web-platform/tests/svg/animations/additive-from-to-width-animation.html61
-rw-r--r--testing/web-platform/tests/svg/animations/additive-type-by-animation.html275
-rw-r--r--testing/web-platform/tests/svg/animations/additive-values-width-animation.html83
-rw-r--r--testing/web-platform/tests/svg/animations/animVal-basics.html65
-rw-r--r--testing/web-platform/tests/svg/animations/animate-calcMode-spline-by.html70
-rw-r--r--testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-by.html71
-rw-r--r--testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-to.html71
-rw-r--r--testing/web-platform/tests/svg/animations/animate-calcMode-spline-to.html70
-rw-r--r--testing/web-platform/tests/svg/animations/animate-calcMode-spline-values.html70
-rw-r--r--testing/web-platform/tests/svg/animations/animate-color-calcMode-discrete.html63
-rw-r--r--testing/web-platform/tests/svg/animations/animate-color-fill-currentColor.html63
-rw-r--r--testing/web-platform/tests/svg/animations/animate-color-fill-from-by.html63
-rw-r--r--testing/web-platform/tests/svg/animations/animate-color-transparent.html53
-rw-r--r--testing/web-platform/tests/svg/animations/animate-css-xml-attributeType.html88
-rw-r--r--testing/web-platform/tests/svg/animations/animate-currentColor.html63
-rw-r--r--testing/web-platform/tests/svg/animations/animate-dynamic-update-attributeName.html71
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-02-t-drt.html183
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-14-t-drt.html140
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-15-t-drt.html136
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-16-t-drt.html136
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-17-t-drt.html136
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-18-t-drt.html137
-rw-r--r--testing/web-platform/tests/svg/animations/animate-elem-19-t-drt.html136
-rw-r--r--testing/web-platform/tests/svg/animations/animate-end-attribute-numeric-precision.html57
-rw-r--r--testing/web-platform/tests/svg/animations/animate-fill-freeze-with-repeatDur.html47
-rw-r--r--testing/web-platform/tests/svg/animations/animate-from-to-keyTimes.html60
-rw-r--r--testing/web-platform/tests/svg/animations/animate-gradient-transform.html103
-rw-r--r--testing/web-platform/tests/svg/animations/animate-inherit-css-property.html69
-rw-r--r--testing/web-platform/tests/svg/animations/animate-insert-begin.html59
-rw-r--r--testing/web-platform/tests/svg/animations/animate-insert-no-begin.html58
-rw-r--r--testing/web-platform/tests/svg/animations/animate-keySplines.html75
-rw-r--r--testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-angle.html104
-rw-r--r--testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-auto.html97
-rw-r--r--testing/web-platform/tests/svg/animations/animate-marker-orient-from-auto-to-auto-start-reverse.html97
-rw-r--r--testing/web-platform/tests/svg/animations/animate-marker-orient-to-angle.html94
-rw-r--r--testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete-keyTimes.html68
-rw-r--r--testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete.html63
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-Cc-Ss.tentative.html62
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-Ll-Vv-Hh.tentative.html58
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-Mm-Aa-Z.tentative.html62
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-Qq-Tt.tentative.html58
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-cC-sS-inverse.tentative.html62
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-lL-vV-hH-inverse.tentative.html58
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-mM-aA-Z-inverse.tentative.html63
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-animation-qQ-tT-inverse.tentative.html58
-rw-r--r--testing/web-platform/tests/svg/animations/animate-path-to-animation.tentative.html52
-rw-r--r--testing/web-platform/tests/svg/animations/animate-reset-freeze.html29
-rw-r--r--testing/web-platform/tests/svg/animations/animate-stop-currentcolor.html26
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-base.html53
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-circle.html56
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-display-none.html53
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-ellipse.html56
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-fill-freeze.html55
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-fill-remove.html55
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-keyPoints-001.html34
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-line.html53
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-multiple.html66
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-rect.html53
-rw-r--r--testing/web-platform/tests/svg/animations/animateMotion-still.html61
-rw-r--r--testing/web-platform/tests/svg/animations/animateTransform-pattern-transform.html99
-rw-r--r--testing/web-platform/tests/svg/animations/animated-classname-crash.svg7
-rw-r--r--testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-001.html34
-rw-r--r--testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-002.html21
-rw-r--r--testing/web-platform/tests/svg/animations/attributeTypes.html121
-rw-r--r--testing/web-platform/tests/svg/animations/begin-attribute-mutation.html29
-rw-r--r--testing/web-platform/tests/svg/animations/begin-event.svg17
-rw-r--r--testing/web-platform/tests/svg/animations/beginelement-instance-time-1.html28
-rw-r--r--testing/web-platform/tests/svg/animations/beginevents-1.html26
-rw-r--r--testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-freeze.html64
-rw-r--r--testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-remove.html64
-rw-r--r--testing/web-platform/tests/svg/animations/change-target-while-animating-SVG-property.html92
-rw-r--r--testing/web-platform/tests/svg/animations/correct-events-for-short-animations-with-syncbases.html52
-rw-r--r--testing/web-platform/tests/svg/animations/cyclic-syncbase-2.html29
-rw-r--r--testing/web-platform/tests/svg/animations/cyclic-syncbase-events.html30
-rw-r--r--testing/web-platform/tests/svg/animations/cyclic-syncbase.html50
-rw-r--r--testing/web-platform/tests/svg/animations/dependent-begin-on-syncbase.html42
-rw-r--r--testing/web-platform/tests/svg/animations/dependent-end-on-syncbase.html42
-rw-r--r--testing/web-platform/tests/svg/animations/end-attribute-change-end-time.html22
-rw-r--r--testing/web-platform/tests/svg/animations/end-event.svg19
-rw-r--r--testing/web-platform/tests/svg/animations/end-of-time-001-crash.html15
-rw-r--r--testing/web-platform/tests/svg/animations/end-of-time-002-crash.html15
-rw-r--r--testing/web-platform/tests/svg/animations/eventbase-non-svg-element.html16
-rw-r--r--testing/web-platform/tests/svg/animations/first-interval-in-the-past-contribute.html30
-rw-r--r--testing/web-platform/tests/svg/animations/first-interval-in-the-past-dont-contribute.html26
-rw-r--r--testing/web-platform/tests/svg/animations/force-use-shadow-tree-recreation-while-animating.html65
-rw-r--r--testing/web-platform/tests/svg/animations/interval-restart-events.html30
-rw-r--r--testing/web-platform/tests/svg/animations/keysplines-x-limits.html66
-rw-r--r--testing/web-platform/tests/svg/animations/keysplines-y-limits.html67
-rw-r--r--testing/web-platform/tests/svg/animations/multiple-animations-ending.html421
-rw-r--r--testing/web-platform/tests/svg/animations/multiple-animations-fill-freeze.html149
-rw-r--r--testing/web-platform/tests/svg/animations/multiple-begin-additive-animation.html136
-rw-r--r--testing/web-platform/tests/svg/animations/non-additive-type-by-animation.html72
-rw-r--r--testing/web-platform/tests/svg/animations/non-additive-type-from-by-animation.html72
-rw-r--r--testing/web-platform/tests/svg/animations/onbegin.svg18
-rw-r--r--testing/web-platform/tests/svg/animations/onend.svg20
-rw-r--r--testing/web-platform/tests/svg/animations/onrepeat.svg20
-rw-r--r--testing/web-platform/tests/svg/animations/pruning-first-interval.html28
-rw-r--r--testing/web-platform/tests/svg/animations/reinserting-svg-into-document.html37
-rw-r--r--testing/web-platform/tests/svg/animations/remove-animation-element-while-animation-is-running.html85
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-event.svg19
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-iteration-event-001.svg27
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-iteration-event-002.svg18
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-iteration-event-003.svg18
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-iteration-event-004.svg18
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-iteration-event-005.svg29
-rw-r--r--testing/web-platform/tests/svg/animations/repeat-iteration-event-006.svg48
-rw-r--r--testing/web-platform/tests/svg/animations/repeatcount-numeric-limit.tentative.svg26
-rw-r--r--testing/web-platform/tests/svg/animations/repeatn-remove-add-animation.html90
-rw-r--r--testing/web-platform/tests/svg/animations/restart-never-and-begin-click.html57
-rw-r--r--testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-exceptions.html18
-rw-r--r--testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-getStartTime.html56
-rw-r--r--testing/web-platform/tests/svg/animations/scripted/animatetransform-type-missing-value-default.html62
-rw-r--r--testing/web-platform/tests/svg/animations/scripted/end-element-on-inactive-element.svg20
-rw-r--r--testing/web-platform/tests/svg/animations/scripted/onhover-syncbases.html43
-rw-r--r--testing/web-platform/tests/svg/animations/scripted/paced-value-animation-overwrites-keyTimes.html37
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-1.html24
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-2.html28
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-3.html27
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-4.html27
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-5.html25
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-6.html25
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-7.html23
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-events-8.html23
-rw-r--r--testing/web-platform/tests/svg/animations/seeking-to-large-time.html24
-rw-r--r--testing/web-platform/tests/svg/animations/short-simple-duration-and-fractional-repeatcount.html22
-rw-r--r--testing/web-platform/tests/svg/animations/single-values-animation.html51
-rw-r--r--testing/web-platform/tests/svg/animations/slider-switch.html47
-rw-r--r--testing/web-platform/tests/svg/animations/spaces-at-end-of-path-data.html29
-rw-r--r--testing/web-platform/tests/svg/animations/support/animated-path-helpers.js76
-rw-r--r--testing/web-platform/tests/svg/animations/svg-style-animate-crash.html22
-rw-r--r--testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-grad.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-rad.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-deg.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-rad.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-deg.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-grad.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgboolean-animation-1.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-1.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-10.html81
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-11.html95
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-12.html81
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-13.html103
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-2.html83
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-3.html62
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-4.html182
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-5.html77
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-6.html89
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-7.html94
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-8.html114
-rw-r--r--testing/web-platform/tests/svg/animations/svgenum-animation-9.html83
-rw-r--r--testing/web-platform/tests/svg/animations/svginteger-animation-1.html77
-rw-r--r--testing/web-platform/tests/svg/animations/svginteger-animation-2.html82
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-1.html70
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-2.html70
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-3.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-4.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-6.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-7.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-by-8.html76
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-from-by-1.html70
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-from-by-2.html77
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-from-by-3.html77
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-additive-from-by-4.html77
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-LengthModeHeight.html69
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-LengthModeOther.html68
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-LengthModeWidth.html69
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-1.html56
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-2.html56
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-3.html56
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-number-to-number.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-cm.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-ems.html65
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-in.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-number.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-pc.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-pt.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-px-to-px.html64
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-unitType.html65
-rw-r--r--testing/web-platform/tests/svg/animations/svglength-animation-values.html75
-rw-r--r--testing/web-platform/tests/svg/animations/svglengthlist-animation-1.html89
-rw-r--r--testing/web-platform/tests/svg/animations/svglengthlist-animation-2.html89
-rw-r--r--testing/web-platform/tests/svg/animations/svglengthlist-animation-3.html78
-rw-r--r--testing/web-platform/tests/svg/animations/svglengthlist-animation-4.html89
-rw-r--r--testing/web-platform/tests/svg/animations/svglengthlist-animation-5.html90
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumber-animation-1.html62
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumber-animation-2.html62
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumber-animation-3.html54
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumber-animation-4.html82
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumberlist-animation-1.html90
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumberlist-animation-2.html90
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-1.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-2.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-3.html93
-rw-r--r--testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-4.html92
-rw-r--r--testing/web-platform/tests/svg/animations/svgpath-animation-1.tentative.html55
-rw-r--r--testing/web-platform/tests/svg/animations/svgpointlist-animation-1.html72
-rw-r--r--testing/web-platform/tests/svg/animations/svgpointlist-animation-2.html72
-rw-r--r--testing/web-platform/tests/svg/animations/svgrect-animation-1.html85
-rw-r--r--testing/web-platform/tests/svg/animations/svgrect-animation-2.html85
-rw-r--r--testing/web-platform/tests/svg/animations/svgstring-animation-1.html66
-rw-r--r--testing/web-platform/tests/svg/animations/svgstring-animation-fallback-to-discrete.html62
-rw-r--r--testing/web-platform/tests/svg/animations/svgtransform-animation-1.html117
-rw-r--r--testing/web-platform/tests/svg/animations/svgtransform-animation-discrete.html74
-rw-r--r--testing/web-platform/tests/svg/animations/switching-animated-target-to-unknown-element.html23
-rw-r--r--testing/web-platform/tests/svg/animations/syncbase-remove-add-while-running.html45
-rw-r--r--testing/web-platform/tests/svg/animations/use-animate-display-none-symbol.html16
207 files changed, 13862 insertions, 0 deletions
diff --git a/testing/web-platform/tests/svg/animations/accumulate-values-width-animation.html b/testing/web-platform/tests/svg/animations/accumulate-values-width-animation.html
new file mode 100644
index 0000000000..7813494a6a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/accumulate-values-width-animation.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests values animation and accumulate='sum'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width to 100 in 10s with a wobbling animation -->
+<rect width="20" height="100" fill="green">
+ <animate id="an1" attributeName="width" dur="2s" values="0; 30; 20" accumulate="sum" repeatCount="5" fill="freeze"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 0, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 20, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 40, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 70, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample7() {
+ assert_approx_equals(rect.width.animVal.value, 60, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample8() {
+ assert_approx_equals(rect.width.animVal.value, 90, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample9() {
+ assert_approx_equals(rect.width.animVal.value, 80, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample10() {
+ assert_approx_equals(rect.width.animVal.value, 110, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+function sample11() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 20);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.0, sample2],
+ ["an1", 1.999, sample3],
+ ["an1", 2.001, sample3],
+ ["an1", 3.0, sample4],
+ ["an1", 3.999, sample5],
+ ["an1", 4.001, sample5],
+ ["an1", 5.0, sample6],
+ ["an1", 5.999, sample7],
+ ["an1", 6.001, sample7],
+ ["an1", 7.0, sample8],
+ ["an1", 7.999, sample9],
+ ["an1", 8.001, sample9],
+ ["an1", 9.0, sample10],
+ ["an1", 9.999, sample11],
+ ["an1", 10.001, sample11],
+ ["an1", 11.0, sample11],
+ ["an1", 60.0, sample11]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/additive-from-to-width-animation.html b/testing/web-platform/tests/svg/animations/additive-from-to-width-animation.html
new file mode 100644
index 0000000000..0899f5e0b5
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/additive-from-to-width-animation.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests multiple additive='sum' animations running at the same time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 10 to 25 + additive=sum. This results in a change from 20 to 75 -->
+<!-- an3: Change width from 0 to 25 + additve=sum. This results in a final change from 20 to 100 -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" from="10" to="50" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="sum" fill="freeze" from="10" to="25" begin="0s" dur="4s"/>
+ <animate id="an3" attributeType="XML" attributeName="width" additive="sum" fill="freeze" from="0" to="25" begin="0s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 20, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 60, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 60.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/additive-type-by-animation.html b/testing/web-platform/tests/svg/animations/additive-type-by-animation.html
new file mode 100644
index 0000000000..2dc7732dd6
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/additive-type-by-animation.html
@@ -0,0 +1,275 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This by animation for all XML property types</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg id="svg" viewBox="0 0 300 300" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- All additive types except AnimatedPath are tested here -->
+<defs>
+ <marker id="marker" viewBox="0 0 10 10" markerWidth="4" markerHeight="3" refX="1" refY="5" orient="-45deg">
+ <polyline id="polyline" points="0,0 10,5 0,10 1,5" fill="green"/>
+ </marker>
+
+ <filter id="filter">
+ <feConvolveMatrix id="feConvolveMatrix" kernelUnitLength="20 30" kernelMatrix="0 1 0 0 1 0 0 1 0" divisor="37.5" order="6 6" targetX="5" preserveAlpha="false"/>
+ </filter>
+</defs>
+
+<!-- Non-additive types AnimatedBoolean, AnimatedEnumeration, AnimatedPreserveAspectRatio, AnimatedString are tested in non-additive-type-by-animation.svg -->
+
+<path id="path" d="M45,50 L55,50" transform="rotate(45)" stroke-width="10" stroke="green" marker-end="url(#marker)"/>
+<rect id="rect" y="0" width="100" height="100" fill="black" filter="url(#filter)"/>
+<text id="text" x="50" y="50" dy="5 -10 10 -10">ABCD</text>
+
+<!-- AnimatedAngle -->
+<animate id="an1" xlink:href="#marker" attributeName="orient" begin="0s" dur="4s" by="45deg" fill="freeze"/>
+
+<!-- AnimatedColor -->
+<animate xlink:href="#rect" attributeName="fill" begin="0s" dur="4s" by="green" fill="freeze"/>
+
+<!-- AnimatedLength -->
+<animate xlink:href="#rect" attributeName="y" begin="0s" dur="4s" by="100" fill="freeze"/>
+
+<!-- AnimatedLengthList -->
+<animate xlink:href="#text" attributeName="dy" begin="0s" dur="4s" by="-10 20 -20 20" fill="freeze"/>
+
+<!-- AnimatedNumberOptionalNumber -->
+<animate xlink:href="#feConvolveMatrix" attributeName="kernelUnitLength" begin="0s" dur="4s" by="-10 -20" fill="freeze"/>
+
+<!-- AnimatedNumber -->
+<animate xlink:href="#feConvolveMatrix" attributeName="divisor" begin="0s" dur="4s" by="-17.5" fill="freeze"/>
+
+<!-- AnimatedNumberList -->
+<animate xlink:href="#feConvolveMatrix" attributeName="kernelMatrix" begin="0s" dur="4s" by="2 1 3 2 1 3 2 1 3" fill="freeze"/>
+
+<!-- AnimatedIntegerOptionalInteger -->
+<animate xlink:href="#feConvolveMatrix" attributeName="order" begin="0s" dur="4s" by="-3 -3" fill="freeze"/>
+
+<!-- AnimatedInteger -->
+<animate xlink:href="#feConvolveMatrix" attributeName="targetX" begin="0s" dur="4s" by="-4" fill="freeze"/>
+
+<!-- AnimatedPoints -->
+<animate xlink:href="#polyline" attributeName="points" begin="0s" dur="4s" by="0,0 10,5 0,10 1,5" fill="freeze"/>
+
+<!-- AnimatedRect -->
+<animate xlink:href="#svg" attributeName="viewBox" begin="0s" dur="4s" by="0 0 -100 -100" fill="freeze"/>
+
+<!-- AnimatedTransformList -->
+<animateTransform xlink:href="#path" attributeName="transform" type="rotate" begin="0s" dur="4s" by="-45" fill="freeze"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function checkBaseVal() {
+ assert_equals(marker.orientAngle.baseVal.value, -45);
+ assert_equals(feConvolveMatrix.divisor.baseVal, 37.5);
+ assert_equals(feConvolveMatrix.orderX.baseVal, 6);
+ assert_equals(feConvolveMatrix.orderY.baseVal, 6);
+ assert_equals(feConvolveMatrix.targetX.baseVal, 5);
+ assert_equals(feConvolveMatrix.kernelUnitLengthX.baseVal, 20);
+ assert_equals(feConvolveMatrix.kernelUnitLengthY.baseVal, 30);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.numberOfItems, 9);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(0).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(1).value, 1);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(2).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(3).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(4).value, 1);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(5).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(6).value, 0);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(7).value, 1);
+ assert_equals(feConvolveMatrix.kernelMatrix.baseVal.getItem(8).value, 0);
+ assert_equals(rect.y.baseVal.value, 0);
+ assert_equals(text.dy.baseVal.numberOfItems, 4);
+ assert_equals(text.dy.baseVal.getItem(0).value, 5);
+ assert_equals(text.dy.baseVal.getItem(1).value, -10);
+ assert_equals(text.dy.baseVal.getItem(2).value, 10);
+ assert_equals(text.dy.baseVal.getItem(3).value, -10);
+ assert_equals(svg.viewBox.baseVal.x, 0);
+ assert_equals(svg.viewBox.baseVal.y, 0);
+ assert_equals(svg.viewBox.baseVal.width, 300);
+ assert_equals(svg.viewBox.baseVal.height, 300);
+ assert_equals(polyline.points.numberOfItems, 4);
+ assert_equals(polyline.points.getItem(0).x, 0);
+ assert_equals(polyline.points.getItem(0).y, 0);
+ assert_equals(polyline.points.getItem(1).x, 10);
+ assert_equals(polyline.points.getItem(1).y, 5);
+ assert_equals(polyline.points.getItem(1).x, 10);
+ assert_equals(polyline.points.getItem(1).y, 5);
+ assert_equals(polyline.points.getItem(2).x, 0);
+ assert_equals(polyline.points.getItem(2).y, 10);
+ assert_equals(path.transform.baseVal.numberOfItems, 1);
+ assert_equals(path.transform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.baseVal.getItem(0).angle, 45);
+}
+
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, -45, epsilon);
+ assert_approx_equals(feConvolveMatrix.divisor.animVal, 37.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 6, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 6, epsilon);
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthX.animVal, 20, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthY.animVal, 30, epsilon);
+ assert_equals(feConvolveMatrix.kernelMatrix.animVal.numberOfItems, 9);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(0).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(1).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(2).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(3).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(4).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(5).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(6).value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(7).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(8).value, 0, epsilon);
+ assert_approx_equals(rect.y.animVal.value, 0, epsilon);
+ assert_equals(text.dy.animVal.numberOfItems, 4);
+ assert_approx_equals(text.dy.animVal.getItem(0).value, 5, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(1).value, -10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(2).value, 10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(3).value, -10, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.width, 300, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.height, 300, epsilon);
+ assert_equals(polyline.animatedPoints.numberOfItems, 4);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).y, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).y, 10, epsilon);
+ assert_equals(path.transform.animVal.numberOfItems, 2);
+ assert_equals(path.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.animVal.getItem(0).angle, 45);
+ assert_equals(path.transform.animVal.getItem(1).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_approx_equals(path.transform.animVal.getItem(1).angle, 0, epsilon);
+ expectFillColor(rect, 0, 0, 0);
+ checkBaseVal();
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, -22.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.divisor.animVal, 28.75, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 5, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 5, epsilon);
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthX.animVal, 15, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthY.animVal, 20, epsilon);
+ assert_equals(feConvolveMatrix.kernelMatrix.animVal.numberOfItems, 9);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(0).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(1).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(2).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(3).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(4).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(5).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(6).value, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(7).value, 1.5, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(8).value, 1.5, epsilon);
+ assert_approx_equals(rect.y.animVal.value, 50, epsilon);
+ assert_equals(text.dy.animVal.numberOfItems, 4);
+ assert_approx_equals(text.dy.animVal.getItem(0).value, 0, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(1).value, 0, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(2).value, 0, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(3).value, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.width, 250, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.height, 250, epsilon);
+ assert_equals(polyline.animatedPoints.numberOfItems, 4);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).y, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 15, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 7.5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 15, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 7.5, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).y, 15, epsilon);
+ assert_equals(path.transform.animVal.numberOfItems, 2);
+ assert_equals(path.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.animVal.getItem(0).angle, 45);
+ assert_equals(path.transform.animVal.getItem(1).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_approx_equals(path.transform.animVal.getItem(1).angle, -22.5, epsilon);
+ expectFillColor(rect, 0, 63, 0);
+ checkBaseVal();
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_approx_equals(feConvolveMatrix.divisor.animVal, 20, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthX.animVal, 10, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelUnitLengthY.animVal, 10, epsilon);
+ assert_equals(feConvolveMatrix.kernelMatrix.animVal.numberOfItems, 9);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(0).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(1).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(2).value, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(3).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(4).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(5).value, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(6).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(7).value, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.kernelMatrix.animVal.getItem(8).value, 3, epsilon);
+ assert_approx_equals(rect.y.animVal.value, 100, epsilon);
+ assert_equals(text.dy.animVal.numberOfItems, 4);
+ assert_approx_equals(text.dy.animVal.getItem(0).value, -5, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(1).value, 10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(2).value, -10, epsilon);
+ assert_approx_equals(text.dy.animVal.getItem(3).value, 10, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.width, 200, epsilon);
+ assert_approx_equals(svg.viewBox.animVal.height, 200, epsilon);
+ assert_equals(polyline.animatedPoints.numberOfItems, 4);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(0).y, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 20, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).x, 20, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(1).y, 10, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).x, 0, epsilon);
+ assert_approx_equals(polyline.animatedPoints.getItem(2).y, 20, epsilon);
+ assert_equals(path.transform.animVal.numberOfItems, 2);
+ assert_equals(path.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_equals(path.transform.animVal.getItem(0).angle, 45);
+ assert_equals(path.transform.animVal.getItem(1).type, SVGTransform.SVG_TRANSFORM_ROTATE);
+ assert_approx_equals(path.transform.animVal.getItem(1).angle, -45, epsilon);
+ expectFillColor(rect, 0, 128, 0);
+ checkBaseVal();
+}
+
+smil_async_test((t) => {
+ marker = rootSVGElement.ownerDocument.getElementsByTagName("marker")[0];
+ filter = rootSVGElement.ownerDocument.getElementsByTagName("filter")[0];
+ feConvolveMatrix = rootSVGElement.ownerDocument.getElementsByTagName("feConvolveMatrix")[0];
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+ svg = rootSVGElement.ownerDocument.getElementsByTagName("svg")[0];
+ path = rootSVGElement.ownerDocument.getElementsByTagName("path")[0];
+ polyline = rootSVGElement.ownerDocument.getElementsByTagName("polyline")[0];
+ text = rootSVGElement.ownerDocument.getElementsByTagName("text")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/additive-values-width-animation.html b/testing/web-platform/tests/svg/animations/additive-values-width-animation.html
new file mode 100644
index 0000000000..5b874f5a4f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/additive-values-width-animation.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests values animation and additive='sum'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 0 to 50 to 100, all linear interpolated. As additive is set to sum it should add the current baseValue
+ to the new animated value each time a value from the values list is consumed. Expected:
+ At 0s, width=10, at 2s, width=50+10=60, at 4s, width=100+10=110.
+
+ Our testing harness will change the baseValue from 10 to 60 at 5s. The current animated value (before the script change)
+ is: <baseValue>+<animValue>: 10 + (100/6*5) = 93.333 at this point. As we change the baseValue to 60, the equation now looks like:
+ 60 + (100/6*5) = 143.333. Before the script change the last second of the animation would have animated width from 85 to 110.
+ Due the script change its now animating from 93.999 to 143.333 during the last second.
+-->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" additive="sum" values="0; 50; 100" begin="0s" dur="6s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 60, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 93.3, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function changeBaseVal() {
+ // At 5s, only change the baseVal.
+ rect.width.baseVal.value = 60;
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 143.33, epsilon);
+ assert_equals(rect.width.baseVal.value, 60);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 160, epsilon);
+ assert_equals(rect.width.baseVal.value, 60);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 3.0, sample2],
+ ["an1", 4.999, sample3],
+ ["an1", 5.0, changeBaseVal],
+ ["an1", 5.001, sample4],
+ ["an1", 6.001, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animVal-basics.html b/testing/web-platform/tests/svg/animations/animVal-basics.html
new file mode 100644
index 0000000000..7eb968af01
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animVal-basics.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Trivial animVal testcase, to see wheter we support it at all. Should result in a 200x200 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("from", "200");
+animate.setAttribute("to", "100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 200, epsilon);
+ assert_equals(rect.width.baseVal.value, 200);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.width.animVal.value, 150, epsilon);
+ assert_equals(rect.width.baseVal.value, 200);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 200);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-calcMode-spline-by.html b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-by.html
new file mode 100644
index 0000000000..5ce9bcc763
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-by.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with by animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("by", "-100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-by.html b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-by.html
new file mode 100644
index 0000000000..1f15760c7d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-by.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with from-by animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "100");
+animate.setAttribute("by", "-100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-to.html b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-to.html
new file mode 100644
index 0000000000..4d60800831
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-from-to.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with from-to animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-calcMode-spline-to.html b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-to.html
new file mode 100644
index 0000000000..4a26cd716e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-to.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with to animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("to", "0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-calcMode-spline-values.html b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-values.html
new file mode 100644
index 0000000000..46952aa45d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-calcMode-spline-values.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with values animation. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("values", "100;0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;1");
+animate.setAttribute("keySplines", "0.25 .5 .25 0.85");
+animate.setAttribute("calcMode", "spline");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.x.animVal.value, 18.8, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-color-calcMode-discrete.html b/testing/web-platform/tests/svg/animations/animate-color-calcMode-discrete.html
new file mode 100644
index 0000000000..980f39282e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-color-calcMode-discrete.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode discrete with from-to animation on colors. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("color", "rgb(128,255,255)");
+rect.setAttribute("fill", "currentColor");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "color");
+animate.setAttribute("from", "rgb(255,0,0)");
+animate.setAttribute("to", "rgb(0,255,255)");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("calcMode", "discrete");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ expectFillColor(rect, 128, 255, 255);
+}
+
+function sample2() {
+ expectFillColor(rect, 255, 0, 0);
+}
+
+function sample3() {
+ expectFillColor(rect, 0, 255, 255);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-color-fill-currentColor.html b/testing/web-platform/tests/svg/animations/animate-color-fill-currentColor.html
new file mode 100644
index 0000000000..2780ce2ac9
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-color-fill-currentColor.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation on 'currentColor'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "currentColor");
+rect.setAttribute("color", "red");
+rect.setAttribute("onclick", "executeTest()");
+
+var animateColor = createSVGElement("animate");
+animateColor.setAttribute("id", "animateColor");
+animateColor.setAttribute("attributeName", "color");
+animateColor.setAttribute("from", "red");
+animateColor.setAttribute("to", "green");
+animateColor.setAttribute("dur", "3s");
+animateColor.setAttribute("begin", "0s");
+animateColor.setAttribute("fill", "freeze");
+rect.appendChild(animateColor);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+
+ expectFillColor(rect, 255, 0, 0);
+}
+
+function sample2() {
+
+ expectFillColor(rect, 128, 64, 0);
+}
+
+function sample3() {
+
+ expectFillColor(rect, 0, 128, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateColor", 0.0, sample1],
+ ["animateColor", 1.5, sample2],
+ ["animateColor", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-color-fill-from-by.html b/testing/web-platform/tests/svg/animations/animate-color-fill-from-by.html
new file mode 100644
index 0000000000..410b27b75a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-color-fill-from-by.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation on 'currentColor'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "currentColor");
+rect.setAttribute("color", "#d00000");
+rect.setAttribute("onclick", "executeTest()");
+
+var animateColor = createSVGElement("animate");
+animateColor.setAttribute("id", "animateColor");
+animateColor.setAttribute("attributeName", "color");
+animateColor.setAttribute("from", "#d00000");
+animateColor.setAttribute("by", "#0000d0");
+animateColor.setAttribute("dur", "3s");
+animateColor.setAttribute("begin", "0s");
+animateColor.setAttribute("fill", "freeze");
+rect.appendChild(animateColor);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+
+ expectFillColor(rect, 208, 0, 0);
+}
+
+function sample2() {
+
+ expectFillColor(rect, 208, 0, 104);
+}
+
+function sample3() {
+
+ expectFillColor(rect, 208, 0, 208);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateColor", 0.0, sample1],
+ ["animateColor", 1.5, sample2],
+ ["animateColor", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-color-transparent.html b/testing/web-platform/tests/svg/animations/animate-color-transparent.html
new file mode 100644
index 0000000000..e2a946cfb0
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-color-transparent.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests that 'transparent' is treated as a valid color.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "test");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "#00FF00");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "fill");
+animate.setAttribute("from", "transparent");
+animate.setAttribute("by", "red");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("begin", "0s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function expectTransparent() {
+ expectFillColor(rect, 0, 255, 0);
+}
+
+function expectOtherColor() {
+ expectFillColor(rect, 127, 0, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, expectTransparent],
+ ["animation", 1.5, expectOtherColor]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-css-xml-attributeType.html b/testing/web-platform/tests/svg/animations/animate-css-xml-attributeType.html
new file mode 100644
index 0000000000..4494eb7736
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-css-xml-attributeType.html
@@ -0,0 +1,88 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests that XML and CSS attributeTypes can be switched between.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var polygon = createSVGElement("polygon");
+polygon.setAttribute("id", "polygon");
+polygon.setAttribute("points", "100 0 200 0 200 100 100 100");
+polygon.setAttribute("fill", "green");
+polygon.setAttribute("onclick", "executeTest()");
+
+var set = createSVGElement("set");
+set.setAttribute("id", "set");
+set.setAttribute("attributeName", "points");
+set.setAttribute("attributeType", "XML");
+set.setAttribute("to", "300 0 400 0 400 100 300 100");
+set.setAttribute("begin", "0s");
+polygon.appendChild(set);
+rootSVGElement.appendChild(polygon);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 100, epsilon);
+ assert_equals(polygon.points.getItem(0).x, 100);
+}
+
+function sample2() {
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 300, epsilon);
+ // change the animationType to CSS which is invalid.
+ set.setAttribute("attributeType", "CSS");
+}
+
+function sample3() {
+ // verify that the animation resets.
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 100, epsilon);
+ // change the animation to a CSS animatable value.
+ set.setAttribute("attributeName", "opacity");
+ set.setAttribute("to", "0.8");
+}
+
+function sample4() {
+ assert_approx_equals(parseFloat(getComputedStyle(polygon).opacity), 0.8, epsilon);
+ // change the animation to a non-CSS animatable value.
+ set.setAttribute("attributeName", "points");
+ set.setAttribute("to", "200 0 300 0 300 100 200 100");
+}
+
+function sample5() {
+ // verify that the animation does not run.
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 100, epsilon);
+ assert_approx_equals(parseFloat(getComputedStyle(polygon).opacity), 1.0, epsilon);
+ // change the animationType to XML which is valid.
+ set.setAttribute("attributeType", "XML");
+}
+
+function sample6() {
+ assert_approx_equals(polygon.animatedPoints.getItem(0).x, 200, epsilon);
+ assert_equals(polygon.points.getItem(0).x, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["set", 0.0, sample1],
+ ["set", 0.5, sample2],
+ ["set", 1.0, sample3],
+ ["set", 1.5, sample4],
+ ["set", 2.0, sample5],
+ ["set", 2.5, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-currentColor.html b/testing/web-platform/tests/svg/animations/animate-currentColor.html
new file mode 100644
index 0000000000..a8b3c1f16f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-currentColor.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation on 'currentColor'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "red");
+rect.setAttribute("color", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animateCurrentColor = createSVGElement("animate");
+animateCurrentColor.setAttribute("id", "animateCurrentColor");
+animateCurrentColor.setAttribute("attributeName", "fill");
+animateCurrentColor.setAttribute("from", "red");
+animateCurrentColor.setAttribute("to", "currentColor");
+animateCurrentColor.setAttribute("dur", "3s");
+animateCurrentColor.setAttribute("begin", "0s");
+animateCurrentColor.setAttribute("fill", "freeze");
+rect.appendChild(animateCurrentColor);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial conditions
+ expectFillColor(rect, 255, 0, 0);
+}
+
+function sample2() {
+ // Check half-time conditions
+ expectFillColor(rect, 128, 64, 0);
+}
+
+function sample3() {
+ // Check end condition
+ expectFillColor(rect, 0, 128, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateCurrentColor", 0.0, sample1],
+ ["animateCurrentColor", 1.5, sample2],
+ ["animateCurrentColor", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-dynamic-update-attributeName.html b/testing/web-platform/tests/svg/animations/animate-dynamic-update-attributeName.html
new file mode 100644
index 0000000000..47ca52526a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-dynamic-update-attributeName.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test behavior on dynamic-update of attributeName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "red");
+rect.setAttribute("color", "red");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "color");
+animate.setAttribute("from", "green");
+animate.setAttribute("to", "green");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+animate.setAttribute("calcMode", "discrete");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ expectColor(rect, 255, 0, 0);
+ assert_equals(rect.style.color, "");
+}
+
+function sample2() {
+ expectColor(rect, 0, 128, 0);
+ assert_equals(rect.style.color, "");
+}
+
+function sample3() {
+ // Set 'attributeName' from 'color' to 'fill'
+ animate.setAttribute("attributeName", "fill");
+}
+
+function sample4() {
+ expectFillColor(rect, 0, 128, 0);
+ assert_equals(rect.style.color, "");
+ assert_equals(rect.style.fill, "");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.5, sample3],
+ ["animation", 3.0, sample4],
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-02-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-02-t-drt.html
new file mode 100644
index 0000000000..31f34ce56f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-02-t-drt.html
@@ -0,0 +1,183 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-09.svg -->
+<!-- renamed for 1.1 suite to animate-elem-02-t.svg -->
+<!-- -->
+<!-- Test 'additive' and 'accumulate' attributes. -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Rick Graham Feb/05/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root"
+ width="100%" height="100%" viewBox="0 0 480 360">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+<!--nav data here-->
+ <OperatorScript version="$Revision: 1.8 $" testname="animate-elem-02-t.svg">
+ <Paragraph>
+ Test 'additive' and 'accumulate' attributes.
+ </Paragraph>
+ <Paragraph>
+ The four pictures show the effect with the four possible combinations of
+ 'additive' (either 'replace' or 'sum') and 'accumulate' (either 'none' or 'sum').
+ Because two animations are animating the height, the effects of 'additive' and
+ 'accumulate' are sometimes different than when there is only a single animation.
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-02-t</title>
+ <desc id="test-desc">Test 'additive' and 'accumulate' attributes.</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content" font-family="Arial" font-size="30">
+
+ <g transform="translate(0, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an5" attributeName="height" calcMode="discrete" additive="replace" accumulate="none"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.5</text>
+ </g>
+ <g transform="translate(110, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an6" attributeName="height" calcMode="discrete" additive="sum" accumulate="none"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.6</text>
+ </g>
+ <g transform="translate(220, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an7" attributeName="height" calcMode="discrete" additive="replace" accumulate="sum"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.7</text>
+ </g>
+ <g transform="translate(330, 0)">
+ <rect x="60" y="20" width="50" height="200" fill="#dfdfdf" stroke="#dfdfdf" stroke-width="4"/>
+ <line x1="40" x2="100" y1="220" y2="220" fill="none" stroke="#880000" stroke-width="4"/>
+ <line x1="40" x2="100" y1="120" y2="120" fill="none" stroke="#880000" stroke-width="4"/>
+ <rect x="60" y="20" width="50" height="20" fill="#0f5" stroke="#085" stroke-width="4">
+ <animate id="an8" attributeName="height" calcMode="discrete" additive="sum" accumulate="sum"
+ repeatCount="2" from="200" to="20" begin="0s" dur="4s" fill="freeze"/>
+ </rect>
+ <text x="30" y="285" fill="navy">anim.8</text>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.8 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ </g>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sampleAfterBegin() {
+ assert_equals(rect1.height.animVal.value, 200);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 220);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 200);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+function sampleAfterMid() {
+ assert_equals(rect1.height.animVal.value, 20);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 40);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 20);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+function sampleAfterBeginOfFirstRepetition() {
+ assert_equals(rect1.height.animVal.value, 200);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 220);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 220);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+function sampleAfterMidOfFirstRepetition() {
+ assert_equals(rect1.height.animVal.value, 20);
+ assert_equals(rect1.height.baseVal.value, 20);
+
+ assert_equals(rect2.height.animVal.value, 40);
+ assert_equals(rect2.height.baseVal.value, 20);
+
+ assert_equals(rect3.height.animVal.value, 40);
+ assert_equals(rect3.height.baseVal.value, 20);
+}
+
+smil_async_test((t) => {
+ rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[1];
+ rect2 = rects[3];
+ rect3 = rects[5];
+ rect4 = rects[7];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an5", 0.0, sampleAfterBegin],
+ ["an5", 1.999, sampleAfterBegin],
+ ["an5", 2.0, sampleAfterMid],
+ ["an5", 3.999, sampleAfterMid],
+ ["an5", 4.0, sampleAfterBeginOfFirstRepetition],
+ ["an5", 5.999, sampleAfterBeginOfFirstRepetition],
+ ["an5", 6.001, sampleAfterMidOfFirstRepetition],
+ ["an5", 7.999, sampleAfterMidOfFirstRepetition],
+ ["an5", 8.001, sampleAfterMidOfFirstRepetition],
+ ["an5", 60.0, sampleAfterMidOfFirstRepetition]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-14-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-14-t-drt.html
new file mode 100644
index 0000000000..64fc35f596
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-14-t-drt.html
@@ -0,0 +1,140 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-14-t.svg -->
+<!-- renamed and split for svgt/b to animate-elem-07-t-a.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.6 $" testname="animate-elem-14-t.svg">
+ <Paragraph>
+ Test 'calcMode'=discrete
+ </Paragraph>
+ <Paragraph>
+ One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided
+ to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The
+ black text and ruler lines help show the size and movement of the rectangle over time.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="discrete" (i.e., a jumping animation).
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-14-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="discrete"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.2;.4;.6"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">6</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="discrete" values="300;255;180;30" keyTimes="0;.2;.4;.6" begin="0s" dur="10s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.6 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 4s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4s to 6s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 6s to 10s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.2;.4;.6" begin="0s" dur="10s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample1],
+ ["an1", 2.001, sample2],
+ ["an1", 3.999, sample2],
+ ["an1", 4.001, sample3],
+ ["an1", 5.999, sample3],
+ ["an1", 6.001, sample4],
+ ["an1", 7.001, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 9.001, sample4],
+ ["an1", 9.999, sample4],
+ ["an1", 10.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-15-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-15-t-drt.html
new file mode 100644
index 0000000000..9d5cb1b437
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-15-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-15-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.5 $" testname="animate-elem-15-t.svg">
+ <Paragraph>
+ Test 'calcMode'=paced
+ </Paragraph>
+ <Paragraph>
+ One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided
+ to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The
+ black text and ruler lines help show the size and movement of the rectangle over time.
+ </Paragraph>
+ <Paragraph>
+ This test shows calcMode="paced" for an animation that has constant velocity, thus showing how 'values'
+ and 'keyTimes' are ignored.
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-15-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="paced"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.25;.5;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="230" y="140">1.5</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">9</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="paced" values="300;255;180;30" keyTimes="0;.25;.5;1" begin="0s" dur="9s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.5 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2.25s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2.25s to 4.5s
+ assert_approx_equals(rect.width.animVal.value, 232.5, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4.5s to 9s
+ assert_approx_equals(rect.width.animVal.value, 165, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 9s to 9s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.25;.5;1" begin="0s" dur="9s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.249, sample2],
+ ["an1", 2.251, sample2],
+ ["an1", 4.499, sample3],
+ ["an1", 4.501, sample3],
+ ["an1", 8.999, sample4],
+ ["an1", 9.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-16-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-16-t-drt.html
new file mode 100644
index 0000000000..0ac98e2fc8
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-16-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-16-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.1 $" testname="animate-elem-07-t-c.svg">
+ <Paragraph>
+ Test 'calcMode'=linear
+ </Paragraph>
+ <Paragraph>
+ One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided
+ to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The
+ black text and ruler lines help show the size and movement of the rectangle over time.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="linear".
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-16-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="linear"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.25;.5;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="linear" values="300;255;180;30" keyTimes="0;.25;.5;1" begin="0s" dur="8s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.1 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 4s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 8s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.25;.5;1" begin="0s" dur="8s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample2],
+ ["an1", 2.001, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample3],
+ ["an1", 7.999, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-17-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-17-t-drt.html
new file mode 100644
index 0000000000..1b10149195
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-17-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-17-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.6 $" testname="animate-elem-17-t.svg">
+ <Paragraph>
+ Test 'calcMode'=spline
+ </Paragraph>
+ <Paragraph>
+ One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided
+ to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The
+ black text and ruler lines help show the size and movement of the rectangle over time.
+ </Paragraph>
+ <Paragraph>
+ This animation shows calcMode="spline". Between time 4 seconds and 8 seconds, the animation displays an ease-in/ease-out approach
+ instead of a constant linear approach which would have been the case if calcMode had been linear instead.
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-17-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="spline"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.25;.5;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">4</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="spline" values="300;255;180;30" keyTimes="0;.25;.5;1" keySplines="0,0,1,1;0,0,1,1;1,0,0,1" begin="0s" dur="8s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.6 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 4s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 4s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 8s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.25;.5;1" keySplines="0,0,1,1;0,0,1,1;1,0,0,1" begin="0s" dur="8s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample2],
+ ["an1", 2.001, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample3],
+ ["an1", 7.999, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-18-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-18-t-drt.html
new file mode 100644
index 0000000000..4f9dbb7765
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-18-t-drt.html
@@ -0,0 +1,137 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-18-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.1 $" testname="animate-elem-07-t-e.svg">
+ <Paragraph>
+ Test 'calcMode'=discrete
+ </Paragraph>
+ <Paragraph>
+ One animation has been defined to animate the height of a rectangle. Ruler lines and text are provided
+ to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The
+ black text and ruler lines help show the size and movement of the rectangle over time.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="discrete" (i.e., a jumping animation).
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-18-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="discrete"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.2;.6;.8"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">2</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">6</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="discrete" values="300;255;180;30" keyTimes="0;.2;.6;.8" begin="0s" dur="10s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.1 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 2s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 2s to 6s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 6s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 10s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: keyTimes="0;.2;.6;.8" begin="0s" dur="10s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample1],
+ ["an1", 2.001, sample2],
+ ["an1", 5.999, sample2],
+ ["an1", 6.001, sample3],
+ ["an1", 7.999, sample3],
+ ["an1", 8.001, sample4],
+ ["an1", 9.999, sample4],
+ ["an1", 10.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-elem-19-t-drt.html b/testing/web-platform/tests/svg/animations/animate-elem-19-t-drt.html
new file mode 100644
index 0000000000..9b9d61c90b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-elem-19-t-drt.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>A copy of the corresponding W3C-SVG-1.1 test, which dumps the animation at certain times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+
+<!--======================================================================-->
+<!--= Copyright 2000 World Wide Web Consortium, (Massachusetts =-->
+<!--= Institute of Technology, Institut National de Recherche en =-->
+<!--= Informatique et en Automatique, Keio University). All Rights =-->
+<!--= Reserved. See http://www.w3.org/Consortium/Legal/. =-->
+<!--======================================================================-->
+<!-- =====================================================================-->
+<!-- -->
+<!-- animation-add-BE-08.svg -->
+<!-- renamed for 1.1 suite to animate-elem-07-f.svg -->
+<!-- renamed and split for svgt/b to animate-elem-19-t.svg -->
+<!-- -->
+<!-- Test possible values for 'keyTimes' -->
+<!-- -->
+<!-- Author : Jon Ferraiolo 11-Aug-2000 -->
+<!-- Revised for 1.1 : Mathias Larsson Carlander Feb/12/2002 -->
+<!-- Revised for svgt/b: Ola Andersson Jun/26/2002 -->
+<!-- -->
+<!-- History: -->
+<!-- 11-Aug-2000, JF: Serial#1 created. -->
+<!-- -->
+<!-- =====================================================================-->
+<!--======================================================================-->
+<!--= Note. After October 2000, revision history is kept as CVS 'commit' =-->
+<!--= log messages, and therefore is no longer in the preceding preamble.=-->
+<!--======================================================================-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" version="1.1" baseProfile="tiny">
+ <SVGTestCase xmlns="http://www.w3.org/2000/02/svg/testsuite/description/">
+ <OperatorScript version="$Revision: 1.6 $" testname="animate-elem-19-t.svg">
+ <Paragraph>
+ Test 'calcMode'=linear
+ </Paragraph>
+ <Paragraph>
+ One animation has been defined to animate the width of a rectangle. Ruler lines and text are provided
+ to help show what the correct behavior is. The red text shows the values for the 'calcMode' and 'keyTimes' attributes. The
+ black text and ruler lines help show the size and movement of the rectangle over time.
+ </Paragraph>
+ <Paragraph>
+ This test shows an animation with calcMode="linear".
+ </Paragraph>
+ </OperatorScript>
+ </SVGTestCase>
+ <title id="test-title">animate-elem-19-t</title>
+ <desc id="test-desc">Test possible values for 'keyTimes'</desc>
+ <!--======================================================================-->
+ <!--Content of Test Case follows... =====================-->
+ <!--======================================================================-->
+ <g id="test-body-content">
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="45">calcMode="linear"</text>
+ <text font-family="Arial" fill="red" font-size="40" x="3" y="100">keyTimes="0;.5;.75;1"</text>
+ <g xml:space="preserve" font-family="Arial" font-size="13.5" stroke-width="3" >
+ <g transform="translate(150,140)">
+ <text font-size="36" x="-140" y="140">Time (s):</text>
+ <text font-size="36" x="290" y="140">0</text>
+ <line x1="300" y1="0" x2="300" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="245" y="140">4</text>
+ <line x1="255" y1="0" x2="255" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="170" y="140">6</text>
+ <line x1="180" y1="0" x2="180" y2="100" fill="none" stroke="#880000" />
+ <text font-size="36" x="20" y="140">8</text>
+ <line x1="30" y1="0" x2="30" y2="100" fill="none" stroke="#880000" />
+ <rect x="0" y="0" width="300" height="80" fill="#44AAFF" stroke="#880088" stroke-width="4" >
+ <animate id="an1" attributeName="width" calcMode="linear" values="300;255;180;30" keyTimes="0;.5;.75;1" begin="0s" dur="8s" fill="freeze"/>
+ </rect>
+
+ </g>
+
+ </g>
+
+ </g>
+ <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">$Revision: 1.6 $</text>
+ <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
+ <script>
+ // Pause the animation at t=0.
+ document.querySelector("svg").pauseAnimations();
+ </script>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() { // From 0s to 4s
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample2() { // From 4s to 6s
+ assert_approx_equals(rect.width.animVal.value, 255, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample3() { // From 6s to 8s
+ assert_approx_equals(rect.width.animVal.value, 180, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+function sample4() { // From 8s to 8s
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 300);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // Sampling according to: values="300;255;180;30" keyTimes="0;.5;.75;1" begin="0s" dur="8s"
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 3.999, sample2],
+ ["an1", 4.001, sample2],
+ ["an1", 5.999, sample3],
+ ["an1", 6.001, sample3],
+ ["an1", 7.999, sample4],
+ ["an1", 8.001, sample4],
+ ["an1", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-end-attribute-numeric-precision.html b/testing/web-platform/tests/svg/animations/animate-end-attribute-numeric-precision.html
new file mode 100644
index 0000000000..d0515ac850
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-end-attribute-numeric-precision.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests end conditions are respected properly near the limits of float numeric precision</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("values", "0;300");
+animate.setAttribute("begin", "0.333333333333333s");
+animate.setAttribute("dur", "0.4256483205159505s");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.x.animVal.value, 100, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.x.animVal.value, 300, epsilon);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+var animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-fill-freeze-with-repeatDur.html b/testing/web-platform/tests/svg/animations/animate-fill-freeze-with-repeatDur.html
new file mode 100644
index 0000000000..aab9eacff2
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-fill-freeze-with-repeatDur.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for animation freeze when repeatDur is not a multiple of dur</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect x='0' y='0' width='50' height='50' fill='green'>
+ <animate id="anim" attributeName='x' from='0' to='100' dur='4s' begin='0s' repeatDur="6s" accumulate="sum" fill='freeze'/>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect1.x.animVal.value, 150, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 6.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-from-to-keyTimes.html b/testing/web-platform/tests/svg/animations/animate-from-to-keyTimes.html
new file mode 100644
index 0000000000..7295bcdb63
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-from-to-keyTimes.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests discrete from-to-keyTimes animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("to", "200");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("keyTimes", "0;0.25");
+animate.setAttribute("calcMode", "discrete");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_equals(rect.x.animVal.value, 100);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_equals(rect.x.animVal.value, 200);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.5, sample1],
+ ["animation", 1.5, sample2],
+ ["animation", 2.5, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-gradient-transform.html b/testing/web-platform/tests/svg/animations/animate-gradient-transform.html
new file mode 100644
index 0000000000..ddb9946fda
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-gradient-transform.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests if gradientTransform of a gradient is animateable.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var gradient = createSVGElement("linearGradient");
+gradient.setAttribute("id", "gradient");
+gradient.setAttribute("gradientUnits", "userSpaceOnUse");
+gradient.setAttribute("x1", "0");
+gradient.setAttribute("x2", "200");
+gradient.setAttribute("gradientTransform", "translate(0)");
+
+var stop1 = createSVGElement("stop");
+stop1.setAttribute("offset", "0");
+stop1.setAttribute("stop-color", "green");
+
+var stop2 = createSVGElement("stop");
+stop2.setAttribute("offset", "1");
+stop2.setAttribute("stop-color", "red");
+
+var animate = createSVGElement("animateTransform");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "gradientTransform");
+animate.setAttribute("type", "translate");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "200");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("fill", "freeze");
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("fill", "url(#gradient)");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("onclick", "executeTest()");
+
+gradient.appendChild(stop1);
+gradient.appendChild(stop2);
+gradient.appendChild(animate);
+
+rootSVGElement.appendChild(gradient);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial conditions
+ shouldThrow("gradient.gradientTransform.animVal.consolidate()");
+ assert_equals(gradient.gradientTransform.animVal.numberOfItems, 1);
+ assert_approx_equals(gradient.gradientTransform.animVal.getItem(0).matrix.e, 0, epsilon);
+ assert_equals(gradient.gradientTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+
+ assert_equals(gradient.gradientTransform.baseVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).matrix.e, 0);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_equals(gradient.gradientTransform.animVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_approx_equals(gradient.gradientTransform.animVal.getItem(0).matrix.e, 100, epsilon);
+
+ assert_equals(gradient.gradientTransform.baseVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).matrix.e, 0);
+}
+
+function sample3() {
+ // Check end conditions
+ assert_equals(gradient.gradientTransform.animVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_approx_equals(gradient.gradientTransform.animVal.getItem(0).matrix.e, 200, epsilon);
+
+ assert_equals(gradient.gradientTransform.baseVal.numberOfItems, 1);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_equals(gradient.gradientTransform.baseVal.getItem(0).matrix.e, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-inherit-css-property.html b/testing/web-platform/tests/svg/animations/animate-inherit-css-property.html
new file mode 100644
index 0000000000..a8b56bab2b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-inherit-css-property.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation with 'inherit'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var g = createSVGElement("g");
+g.setAttribute("fill", "green");
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100px");
+rect.setAttribute("height", "100px");
+rect.setAttribute("fill", "red");
+rect.setAttribute("onclick", "executeTest()");
+g.appendChild(rect);
+
+var animateInherit = createSVGElement("animate");
+animateInherit.setAttribute("id", "animateInherit");
+animateInherit.setAttribute("attributeName", "fill");
+animateInherit.setAttribute("from", "red");
+animateInherit.setAttribute("to", "inherit");
+animateInherit.setAttribute("dur", "3s");
+animateInherit.setAttribute("begin", "0s");
+animateInherit.setAttribute("fill", "freeze");
+rect.appendChild(animateInherit);
+rootSVGElement.appendChild(g);
+
+// Setup animation test
+function sample1() {
+ // Check initial conditions
+ expectFillColor(rect, 255, 0, 0);
+ assert_equals(rect.style.fill, "");
+}
+
+function sample2() {
+ // Check half-time conditions
+ expectFillColor(rect, 128, 64, 0);
+ assert_equals(rect.style.fill, "");
+}
+
+function sample3() {
+ // Check end conditions
+ expectFillColor(rect, 0, 128, 0);
+ assert_equals(rect.style.fill, "");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animateInherit", 0.0, sample1],
+ ["animateInherit", 1.5, sample2],
+ ["animateInherit", 3.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-insert-begin.html b/testing/web-platform/tests/svg/animations/animate-insert-begin.html
new file mode 100644
index 0000000000..5155391a91
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-insert-begin.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test behavior of dynamically inserting animate with begin attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "45");
+rect.setAttribute("width", "10");
+rect.setAttribute("height", "10");
+rect.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "90");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect.x.animVal.value, 90, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 3.0, sample2],
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-insert-no-begin.html b/testing/web-platform/tests/svg/animations/animate-insert-no-begin.html
new file mode 100644
index 0000000000..3db406ecd4
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-insert-no-begin.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test behavior of dynamically inserting animate without begin attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "45");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "90");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.x.animVal.value, 0, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect.x.animVal.value, 90, epsilon);
+ assert_equals(rect.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 3.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-keySplines.html b/testing/web-platform/tests/svg/animations/animate-keySplines.html
new file mode 100644
index 0000000000..0b02f71d3f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-keySplines.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Testing correct parsing of keySplines.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("fill", "green");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "height");
+animate.setAttribute("calcMode", "spline");
+animate.setAttribute("keyTimes", " 0 ; 0.3333333 ; 0.666666; 1 ");
+animate.setAttribute("keySplines", " 0 ,0 1 , 1 ; 0 0 , 1 , 1 ; .75 , 0 , 0 , .75 ; ");
+animate.setAttribute("values", "200;167;111;0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "9s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.height.animVal.value, 167, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(rect.height.animVal.value, 111, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(rect.height.animVal.value, 0, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample4() {
+ // Check end conditions
+ assert_approx_equals(rect.height.animVal.value, 100, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 3.0, sample1],
+ ["animation", 6.0, sample2],
+ ["animation", 8.999, sample3],
+ ["animation", 9.001, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-angle.html b/testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-angle.html
new file mode 100644
index 0000000000..a9c16740e6
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-angle.html
@@ -0,0 +1,104 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Animate SVGMarkerElement orientAttr from an angle to an angle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "strokeWidth");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttribute("stroke", "green");
+path.setAttribute("stroke-width", "10");
+path.setAttribute("marker-start", "url(#marker)");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("d", "M 130 135 L 180 135 L 180 185");
+path.setAttribute("transform", "translate(-130, -120)");
+rootSVGElement.appendChild(path);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "orient");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "90deg");
+animate1.setAttribute("to", "180deg");
+animate1.setAttribute("fill", "freeze");
+marker.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 135, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample4() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 2.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-auto.html b/testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-auto.html
new file mode 100644
index 0000000000..40fc57b4f3
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-auto.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Animate SVGMarkerElement orientAttr from an angle to auto</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "strokeWidth");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttribute("stroke", "green");
+path.setAttribute("stroke-width", "10");
+path.setAttribute("marker-start", "url(#marker)");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("d", "M 130 135 L 180 135 L 180 185");
+path.setAttribute("transform", "translate(-130, -120)");
+rootSVGElement.appendChild(path);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "orient");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "90deg");
+animate1.setAttribute("to", "auto");
+animate1.setAttribute("fill", "freeze");
+marker.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-marker-orient-from-auto-to-auto-start-reverse.html b/testing/web-platform/tests/svg/animations/animate-marker-orient-from-auto-to-auto-start-reverse.html
new file mode 100644
index 0000000000..b7a4e68562
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-marker-orient-from-auto-to-auto-start-reverse.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Animate SVGMarkerElement orientAttr from auto to auto-start-reverse</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "strokeWidth");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttribute("stroke", "green");
+path.setAttribute("stroke-width", "10");
+path.setAttribute("marker-start", "url(#marker)");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("d", "M 130 135 L 180 135 L 180 185");
+path.setAttribute("transform", "translate(-130, -120)");
+rootSVGElement.appendChild(path);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "orient");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "auto");
+animate1.setAttribute("to", "auto-start-reverse");
+animate1.setAttribute("fill", "freeze");
+marker.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO_START_REVERSE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-marker-orient-to-angle.html b/testing/web-platform/tests/svg/animations/animate-marker-orient-to-angle.html
new file mode 100644
index 0000000000..6b4ba2bfef
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-marker-orient-to-angle.html
@@ -0,0 +1,94 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Animate SVGMarkerElement orientAttr to an angle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "strokeWidth");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttribute("stroke", "green");
+path.setAttribute("stroke-width", "10");
+path.setAttribute("marker-start", "url(#marker)");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("d", "M 130 135 L 180 135 L 180 185");
+path.setAttribute("transform", "translate(-130, -120)");
+rootSVGElement.appendChild(path);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "orient");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("to", "180deg");
+animate1.setAttribute("fill", "freeze");
+marker.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete-keyTimes.html b/testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete-keyTimes.html
new file mode 100644
index 0000000000..0e80e03f88
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete-keyTimes.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode discrete with from-to animation on numbers. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("values", "100;200;300");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("keyTimes", "0;0.5;1");
+animate.setAttribute("calcMode", "discrete");
+animate.setAttribute("fill", "freeze");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_equals(rect.x.animVal.value, 100);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_equals(rect.x.animVal.value, 200);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_equals(rect.x.animVal.value, 300);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.499, sample1],
+ ["animation", 1.501, sample2],
+ ["animation", 2.999, sample2],
+ ["animation", 3.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete.html b/testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete.html
new file mode 100644
index 0000000000..11563233b4
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode discrete with from-to animation on numbers. You should see a green 100x100 rect and only PASS messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "100");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "0");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("calcMode", "discrete");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_equals(rect.x.animVal.value, 100);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_equals(rect.x.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 150;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-Cc-Ss.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-Cc-Ss.tentative.html
new file mode 100644
index 0000000000..69b3cc7af4
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Cc-Ss.tentative.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (C-c and S-s)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+animate.setAttribute("to", "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(
+ path, "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(
+ path, "M -20 -20 c 30 10 30 10 40 40 s 10 15 -30 -10 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(
+ path, "M -20 -20 c 10 30 10 30 40 40 s 30 5 -10 -30 Z");
+}
+
+function sample4() {
+ assert_animated_path_equals(
+ path, "M -20 -20 c 0.00999832 39.99 0.00999832 39.99 40 40 s 39.99 0.00499916 -0.00999832 -39.99 Z");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-Ll-Vv-Hh.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-Ll-Vv-Hh.tentative.html
new file mode 100644
index 0000000000..8a1e2cb032
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Ll-Vv-Hh.tentative.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (L-l, V-v and H-h)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -30 -30 L 30 0 V 30 H 0 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -30 -30 L 30 0 V 30 H 0 Z");
+animate.setAttribute("to", "M 30 30 l -60 -30 v -30 h 30 Z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(path, "M -30 -30 L 30 0 V 30 H 0 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(path, "M -15 -15 l 30 15 v 15 h -15 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(path, "M 15 15 l -30 -15 v -15 h 15 Z");
+}
+
+function sample4() {
+ assert_animated_path_equals(path, "M 29.985 29.985 l -59.97 -29.985 v -29.985 h 29.985 Z");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-Mm-Aa-Z.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-Mm-Aa-Z.tentative.html
new file mode 100644
index 0000000000..fd0787792f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Mm-Aa-Z.tentative.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (M-m, A-a and Z)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", 'M -80 40 A 150 160 30 1 1 0 100 M 40 60 A 170 180 90 1 1 300 200 Z M 300 100');
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", 'M -80 40 A 150 160 30 1 1 0 100 M 40 60 A 170 180 90 1 1 300 200 Z M 300 100');
+animate.setAttribute("to", 'm -70 30 a 160 170 60 1 1 60 40 m 120 70 a 180 190 120 1 1 100 150 Z m 120 -60');
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(
+ path, "M -80 40 A 150 160 30 1 1 0 100 M 40 60 A 170 180 90 1 1 300 200 Z M 300 100");
+}
+
+function sample2() {
+ assert_animated_path_equals(
+ path, "m -77.5 37.5 a 152.5 162.5 37.5 1 1 75 55 m 60 -12.5 a 172.5 182.5 97.5 1 1 220 142.5 Z m 225 15");
+}
+
+function sample3() {
+ assert_animated_path_equals(
+ path, "m -72.5 32.5 a 157.5 167.5 52.5 1 1 65 45 m 100 42.5 a 177.5 187.5 112.5 1 1 140 147.5 Z m 155 -35");
+}
+
+function sample4() {
+ assert_animated_path_equals(
+ path, "m -70.0025 30.0025 a 159.997 169.997 59.9925 1 1 60.005 40.005 m 119.98 69.9725 a 179.997 189.997 119.993 1 1 100.04 149.998 Z m 120.035 -59.975");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-Qq-Tt.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-Qq-Tt.tentative.html
new file mode 100644
index 0000000000..e8b0ad8f71
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Qq-Tt.tentative.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (Q-q and T-t)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+animate.setAttribute("to", "M -30 -30 q 30 0 30 30 t -30 30 z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(path, "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(path, "M -30 -30 q 52.5 0 52.5 30 t -52.5 30 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(path, "M -30 -30 q 37.5 0 37.5 30 t -37.5 30 Z");
+}
+
+function sample4() {
+ assert_animated_path_equals(path, "M -30 -30 q 30.0075 0 30.0075 30 t -30.0075 30 Z");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-cC-sS-inverse.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-cC-sS-inverse.tentative.html
new file mode 100644
index 0000000000..5b19f69b2d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-cC-sS-inverse.tentative.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (c-C and s-S)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 Z");
+animate.setAttribute("to", "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(
+ path, "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(
+ path, "M -20 -20 C -10 10 -10 10 20 20 S 50 25 10 -10 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(
+ path, "M -20 -20 C 10 -10 10 -10 20 20 S 30 35 -10 10 Z");
+}
+
+function sample4() {
+ assert_animated_path_equals(
+ path, "M -20 -20 C 19.99 -19.99 19.99 -19.99 20 20 S 20.01 39.995 -19.99 19.99 Z");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-lL-vV-hH-inverse.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-lL-vV-hH-inverse.tentative.html
new file mode 100644
index 0000000000..3a96eb2945
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-lL-vV-hH-inverse.tentative.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (l-L, v-V and h-H)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M 30 30 l -60 -30 v -30 h 30 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M 30 30 l -60 -30 v -30 h 30 Z");
+animate.setAttribute("to", "M -30 -30 L 30 0 V 30 H 0 Z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(path, "M 30 30 l -60 -30 v -30 h 30 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(path, "M 15 15 L -15 0 V -15 H 0 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(path, "M -15 -15 L 15 0 V 15 H 0 Z");
+}
+
+function sample4() {
+ assert_animated_path_equals(path, "M -29.985 -29.985 L 29.985 0 V 29.985 H 0 Z");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-mM-aA-Z-inverse.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-mM-aA-Z-inverse.tentative.html
new file mode 100644
index 0000000000..df32a4a250
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-mM-aA-Z-inverse.tentative.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (m-M, a-A and Z)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", 'm -70 30 a 160 170 60 1 1 60 40 m 120 70 a 180 190 120 1 1 100 150 Z m 120 -60');
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", 'm -70 30 a 160 170 60 1 1 60 40 m 120 70 a 180 190 120 1 1 100 150 Z m 120 -60');
+animate.setAttribute("to", 'M -80 40 A 150 160 30 1 1 0 100 M 40 60 A 170 180 90 1 1 300 200 Z M 300 100');
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(
+ path, "m -70 30 a 160 170 60 1 1 60 40 m 120 70 a 180 190 120 1 1 100 150 Z m 120 -60");
+}
+
+function sample2() {
+ assert_animated_path_equals(
+ path, "M -72.5 32.5 A 157.5 167.5 52.5 1 1 -7.5 77.5 M 92.5 120 A 177.5 187.5 112.5 1 1 232.5 267.5 Z M 247.5 85");
+}
+
+function sample3() {
+ assert_animated_path_equals(
+ path, "M -77.5 37.5 A 152.5 162.5 37.5 1 1 -2.5 92.5 M 57.5 80 A 172.5 182.5 97.5 1 1 277.5 222.5 Z M 282.5 95");
+}
+
+function sample4() {
+ assert_animated_path_equals(
+ path, "M -79.9975 39.9975 A 150.003 160.003 30.0075 1 1 -0.00249481 99.9925 M 40.0175 60.02 A 170.003 180.003 90.0075 1 1 299.977 200.022 Z M 299.982 99.995");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-animation-qQ-tT-inverse.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-animation-qQ-tT-inverse.tentative.html
new file mode 100644
index 0000000000..6ae4d1f1dc
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-qQ-tT-inverse.tentative.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Path animation where coordinate modes of start and end differ (q-Q and t-T)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M -30 -30 q 30 0 30 30 t -30 30 Z");
+path.setAttribute("fill", "green");
+path.setAttribute("transform", "translate(50, 50)");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M -30 -30 q 30 0 30 30 t -30 30 Z");
+animate.setAttribute("to", "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(path, "M -30 -30 q 30 0 30 30 t -30 30 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(path, "M -30 -30 Q 7.5 -30 7.5 0 T -30 30 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(path, "M -30 -30 Q 22.5 -30 22.5 0 T -30 30 Z");
+}
+
+function sample4() {
+ assert_animated_path_equals(path, "M -30 -30 Q 29.9925 -30 29.9925 0 T -30 30 Z");
+}
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 3.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-path-to-animation.tentative.html b/testing/web-platform/tests/svg/animations/animate-path-to-animation.tentative.html
new file mode 100644
index 0000000000..a20a33f6a4
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-to-animation.tentative.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>calcMode spline with 'to' animation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M 40 40 L 60 40 L 60 60 L 40 60 Z");
+path.setAttribute("fill", "green");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("to", "M 0 0 L 100 0 L 100 100 L 0 100 z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_animated_path_equals(path, "M 40 40 L 60 40 L 60 60 L 40 60 Z");
+}
+
+function sample2() {
+ assert_animated_path_equals(path, "M 20 20 L 80 20 L 80 80 L 20 80 Z");
+}
+
+function sample3() {
+ assert_animated_path_equals(
+ path, "M 0.00999928 0.00999928 L 99.99 0.00999928 L 99.99 99.99 L 0.00999928 99.99 Z");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-reset-freeze.html b/testing/web-platform/tests/svg/animations/animate-reset-freeze.html
new file mode 100644
index 0000000000..0b0d90003d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-reset-freeze.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>SVG Animations: Rewinding fill='freeze' animations</title>
+<link rel="help" href="https://svgwg.org/specs/animations/">
+<link rel="issue" href="https://bugs.webkit.org/show_bug.cgi?id=89846">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red"/>
+ <rect id="rect" x="0" width="100" height="100" fill="green">
+ <set attributeName="x" to="100" begin="4s" fill="freeze"/>
+ <set attributeName="x" to="200" begin="1s" dur="1s" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ let svg = document.querySelector('svg');
+ let rect = document.getElementById('rect');
+ svg.pauseAnimations();
+ svg.setCurrentTime(100);
+
+ window.onload = t.step_func(() => {
+ window.requestAnimationFrame(t.step_func_done(() => {
+ assert_equals(rect.x.animVal.value, 100, "'x' is 100 at t=100");
+ svg.setCurrentTime(0);
+ assert_equals(rect.x.animVal.value, 0, "'x' is 0 at t=0");
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animate-stop-currentcolor.html b/testing/web-platform/tests/svg/animations/animate-stop-currentcolor.html
new file mode 100644
index 0000000000..1536035dec
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-stop-currentcolor.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>Animating 'stop-color' from 'currentcolor'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <linearGradient id="lg" style="color: green">
+ <stop stop-color="red">
+ <animate attributeName="stop-color" from="currentcolor" to="green" dur="10s" fill="freeze"/>
+ </stop>
+ </linearGradient>
+ <rect width="100" height="100" fill="url(#lg)"/>
+</svg>
+<script>
+ async_test(t => {
+ let svg = document.querySelector("svg");
+ svg.pauseAnimations();
+ svg.setCurrentTime(5);
+ onload = t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ let stop = document.querySelector("stop");
+ assert_equals(getComputedStyle(stop).getPropertyValue("stop-color"),
+ "rgb(0, 128, 0)");
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-base.html b/testing/web-platform/tests/svg/animations/animateMotion-base.html
new file mode 100644
index 0000000000..e69b121a06
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-base.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<head>
+<base href="/">
+</head>
+<html>
+<title>Test for checking position of the svg element when there is a <base> attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+ <line id="line" x2="100" display="none"/>
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" begin="0s" dur="4s" fill="freeze">
+ <mpath href="#line"/>
+ </animateMotion>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 50, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-circle.html b/testing/web-platform/tests/svg/animations/animateMotion-circle.html
new file mode 100644
index 0000000000..3cf713f904
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-circle.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for checking position of the svg element when animateMotion's mpath is a circle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <circle id="circle" cx="-100" r="100" display="none"/>
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" begin="0s" dur="4s" fill="freeze">
+ <mpath href="#circle"/>
+ </animateMotion>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, -200, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-display-none.html b/testing/web-platform/tests/svg/animations/animateMotion-display-none.html
new file mode 100644
index 0000000000..104744c17f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-display-none.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for checking position of the svg element when animateMotion's mpath is display:none</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <path id="path" d="M0,0 100,0" display="none"/>
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" begin="0s" dur="4s" fill="freeze">
+ <mpath href="#path"/>
+ </animateMotion>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 50, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-ellipse.html b/testing/web-platform/tests/svg/animations/animateMotion-ellipse.html
new file mode 100644
index 0000000000..109ae4f586
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-ellipse.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for checking position of the svg element when animateMotion's mpath is an ellipse</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <ellipse id="ellipse" cx="-100" rx="100" display="none"/>
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" begin="0s" dur="4s" fill="freeze">
+ <mpath href="#ellipse"/>
+ </animateMotion>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, -200, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-fill-freeze.html b/testing/web-platform/tests/svg/animations/animateMotion-fill-freeze.html
new file mode 100644
index 0000000000..4e768efb00
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-fill-freeze.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for animation freeze when repeatDur is not a multiple of dur</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" to="100,0" begin="0s" dur="4s" fill="freeze" />
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 50, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+function sample4() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3],
+ ["anim", 6.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-fill-remove.html b/testing/web-platform/tests/svg/animations/animateMotion-fill-remove.html
new file mode 100644
index 0000000000..aeb74b4b0f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-fill-remove.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for animation freeze when repeatDur is not a multiple of dur</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" to="100,0" begin="0s" dur="4s" fill="remove" />
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 50, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample4() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3],
+ ["anim", 6.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-keyPoints-001.html b/testing/web-platform/tests/svg/animations/animateMotion-keyPoints-001.html
new file mode 100644
index 0000000000..1397bd6039
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-keyPoints-001.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>'calcMode' paced and 'keyPoints' on &lt;animateMotion> with 'path'</title>
+<link rel="help" href="https://svgwg.org/specs/animations/#AnimateMotionElement">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red"/>
+ <rect id="target" transform="translate(100, -50)" width="100" height="100" fill="green">
+ <animateMotion dur="5s" keyPoints="1;0" keyTimes="0;1" path="M-200,50h250"/>
+ </rect>
+</svg>
+<script>
+const rootSVGElement = document.querySelector('svg');
+
+function sample(expectedX) {
+ const target = document.getElementById('target');
+ const targetCTM = target.getCTM();
+ assert_approx_equals(targetCTM.e, expectedX, 1e-3, 'x position');
+ assert_equals(targetCTM.f, 0, 'y position');
+ const restOfCTM = ['a', 'b', 'c', 'd'].map(p => targetCTM[p]);
+ assert_array_equals(restOfCTM, [1, 0, 0, 1], 'rest of CTM');
+}
+
+smil_async_test(t => {
+ runAnimationTest(t, [
+ // [animationId, time, sampleCallback]
+ ['anim', 1, sample.bind(this, 100)],
+ ['anim', 2, sample.bind(this, 50)],
+ ['anim', 3, sample.bind(this, 0)],
+ ]);
+});
+window.animationStartsImmediately = true;
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-line.html b/testing/web-platform/tests/svg/animations/animateMotion-line.html
new file mode 100644
index 0000000000..f304de62dc
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-line.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for checking position of the svg element when animateMotion's mpath is a line</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <line id="line" x2="100" display="none"/>
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" begin="0s" dur="4s" fill="freeze">
+ <mpath href="#line"/>
+ </animateMotion>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 50, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-multiple.html b/testing/web-platform/tests/svg/animations/animateMotion-multiple.html
new file mode 100644
index 0000000000..494d75a785
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-multiple.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for checking position of the svg element when multiple animateMotion are acting on it</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" values="20,0" begin="0s"/>
+ <animateMotion values="40,0;80,0" begin="2s" dur="4s"/>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 20, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 20, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 40, epsilon);
+}
+
+function sample4() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 60, epsilon);
+}
+
+function sample5() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 20, epsilon);
+}
+
+function sample6() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 20, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 1.0, sample2],
+ ["anim", 2.0, sample3],
+ ["anim", 4.0, sample4],
+ ["anim", 6.0, sample5],
+ ["anim", 7.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-rect.html b/testing/web-platform/tests/svg/animations/animateMotion-rect.html
new file mode 100644
index 0000000000..8853b047c3
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-rect.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for checking position of the svg element when animateMotion's mpath is a rect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect id="rect" width="100" height="100" display="none"/>
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" begin="0s" dur="4s" fill="freeze">
+ <mpath href="#rect"/>
+ </animateMotion>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[1];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/animateMotion-still.html b/testing/web-platform/tests/svg/animations/animateMotion-still.html
new file mode 100644
index 0000000000..bf9007ac2f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateMotion-still.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test animations that only express an offset</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect width="50" height="50" x="0" y="0" fill="green">
+ <animateMotion id="anim" path="M 100 100 L 100 100"
+ begin="0s" dur="2s" repeatCount="2" accumulate="sum" fill="remove" />
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 200, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 200, epsilon);
+}
+
+function sample4() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+function sample5() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 1.0, sample1],
+ ["anim", 2.0, sample2],
+ ["anim", 3.0, sample3],
+ ["anim", 4.0, sample4],
+ ["anim", 5.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animateTransform-pattern-transform.html b/testing/web-platform/tests/svg/animations/animateTransform-pattern-transform.html
new file mode 100644
index 0000000000..614444bf71
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animateTransform-pattern-transform.html
@@ -0,0 +1,99 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests animation of 'patternTransform'. Should result in a 100x100 rect and only PASS messages.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var pattern = createSVGElement("pattern");
+pattern.setAttribute("id", "pattern");
+pattern.setAttribute("width", "200");
+pattern.setAttribute("height", "200");
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "url(#pattern)");
+rect.setAttribute("onclick", "executeTest()");
+
+var patternRect = createSVGElement("rect");
+patternRect.setAttribute("id", "patternRect");
+patternRect.setAttribute("width", "100");
+patternRect.setAttribute("height", "100");
+patternRect.setAttribute("fill", "green");
+pattern.appendChild(patternRect);
+
+var animate = createSVGElement("animateTransform");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "patternTransform");
+animate.setAttribute("type", "scale");
+animate.setAttribute("from", "1");
+animate.setAttribute("to", "2");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+pattern.appendChild(animate);
+defs.appendChild(pattern);
+
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_equals(pattern.patternTransform.animVal.numberOfItems, 0);
+ assert_equals(pattern.patternTransform.baseVal.numberOfItems, 0);
+}
+
+function sample2() {
+ assert_equals(pattern.patternTransform.animVal.numberOfItems, 1);
+ assert_equals(pattern.patternTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(pattern.patternTransform.animVal.getItem(0).matrix.a, 1, epsilon);
+
+ assert_equals(pattern.patternTransform.baseVal.numberOfItems, 0);
+}
+
+function sample3() {
+ // Check half-time conditions
+ assert_equals(pattern.patternTransform.animVal.numberOfItems, 1);
+ assert_equals(pattern.patternTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(pattern.patternTransform.animVal.getItem(0).matrix.a, 1.5, epsilon);
+
+ assert_equals(pattern.patternTransform.baseVal.numberOfItems, 0);
+}
+
+function sample4() {
+ // Check half-time conditions
+ assert_equals(pattern.patternTransform.animVal.numberOfItems, 1);
+ assert_equals(pattern.patternTransform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(pattern.patternTransform.animVal.getItem(0).matrix.a, 2, epsilon);
+
+ assert_equals(pattern.patternTransform.baseVal.numberOfItems, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 2.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/animated-classname-crash.svg b/testing/web-platform/tests/svg/animations/animated-classname-crash.svg
new file mode 100644
index 0000000000..5b28addfdd
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animated-classname-crash.svg
@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="blue">
+ <style>.v { fill: green }</style>
+ <g>
+ <set attributeName="class" to="v" begin="1s"/>
+ <rect width="100" height="100"/>
+ </g>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-001.html b/testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-001.html
new file mode 100644
index 0000000000..21271ff030
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-001.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>An animation of an attribute ('class') does not change the DOM attribute value</title>
+<link rel="help" href="https://www.w3.org/TR/2001/REC-smil-animation-20010904/#BasicAnim">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ .animated {
+ fill: blue;
+ }
+</style>
+<svg>
+ <rect class="base">
+ <set attributeName="class" to="animated"/>
+ </rect>
+ <rect>
+ <set attributeName="class" to="animated"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ onload = t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ let rects = document.getElementsByTagName('rect');
+ assert_true(rects[0].hasAttribute('class'));
+ assert_equals(rects[0].getAttribute('class'), 'base');
+ assert_equals(getComputedStyle(rects[0]).getPropertyValue('fill'), 'rgb(0, 0, 255)');
+
+ assert_false(rects[1].hasAttribute('class'));
+ assert_equals(rects[1].getAttribute('class'), null);
+ assert_equals(getComputedStyle(rects[0]).getPropertyValue('fill'), 'rgb(0, 0, 255)');
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-002.html b/testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-002.html
new file mode 100644
index 0000000000..29878d02cb
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/attribute-value-unaffected-by-animation-002.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>An animation of an attribute ('orient') does not change the DOM attribute value</title>
+<link rel="help" href="https://www.w3.org/TR/2001/REC-smil-animation-20010904/#BasicAnim">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <marker orient="90">
+ <set attributeName="orient" to="auto"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ onload = t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ let marker = document.querySelector('marker');
+ marker.orientAngle.baseVal.valueInSpecifiedUnits = 180;
+ assert_equals(marker.getAttribute('orient'), '180');
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/attributeTypes.html b/testing/web-platform/tests/svg/animations/attributeTypes.html
new file mode 100644
index 0000000000..7a9ad43dd9
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/attributeTypes.html
@@ -0,0 +1,121 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This verifies several attributeTypes combiniations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- 'width' is a XML attribute, attributeType is set to "auto": this animation runs. -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="auto" attributeName="width" fill="freeze" from="10" to="100" begin="0s" dur="4s"/>
+</rect>
+
+<!-- 'width' is a XML attribute, attributeType is set to "CSS". 'width' is not a presentation attribute, so this animation won't run. -->
+<rect x="150" width="10" height="100" fill="green">
+ <animate id="an2" attributeType="CSS" attributeName="width" fill="freeze" from="10" to="100" begin="0s" dur="4s"/>
+</rect>
+
+<!-- 'fill' is a presentation attribute, mapped to CSS, attributeType is set to "auto": this animation runs. -->
+<rect y="150" width="100" height="100" fill="red">
+ <animate id="an3" attributeType="auto" attributeName="fill" fill="freeze" from="red" to="green" begin="0s" dur="4s"/>
+</rect>
+
+<!-- 'fill' is a presentation attribute, mapped to CSS, attributeType is set to "XML": this animation runs. -->
+<rect x="150" y="150" width="100" height="100" fill="red">
+ <animate id="an4" attributeType="XML" attributeName="fill" fill="freeze" from="red" to="green" begin="0s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.width.animVal.value, 10, epsilon);
+ assert_equals(rect1.width.baseVal.value, 10);
+ expectFillColor(rect1, 0, 128, 0);
+
+ assert_equals(rect2.width.animVal.value, 10);
+ assert_equals(rect2.width.baseVal.value, 10);
+ expectFillColor(rect2, 0, 128, 0);
+
+ assert_equals(rect3.width.animVal.value, 100);
+ assert_equals(rect3.width.baseVal.value, 100);
+ expectFillColor(rect3, 255, 0, 0);
+ assert_equals(rect3.getAttribute('fill'), "red");
+
+ assert_equals(rect4.width.animVal.value, 100);
+ assert_equals(rect4.width.baseVal.value, 100);
+ expectFillColor(rect4, 255, 0, 0);
+ assert_equals(rect4.getAttribute('fill'), "red");
+}
+
+function sample2() {
+ assert_approx_equals(rect1.width.animVal.value, 55, epsilon);
+ assert_equals(rect1.width.baseVal.value, 10);
+ expectFillColor(rect1, 0, 128, 0);
+
+ assert_equals(rect2.width.animVal.value, 55);
+ assert_equals(rect2.width.baseVal.value, 10);
+ expectFillColor(rect2, 0, 128, 0);
+
+ assert_equals(rect3.width.animVal.value, 100);
+ assert_equals(rect3.width.baseVal.value, 100);
+ expectFillColor(rect3, 128, 64, 0);
+ assert_equals(rect3.getAttribute('fill'), "red");
+
+ assert_equals(rect4.width.animVal.value, 100);
+ assert_equals(rect4.width.baseVal.value, 100);
+ expectFillColor(rect4, 128, 64, 0);
+ assert_equals(rect4.getAttribute('fill'), "red");
+}
+
+function sample3() {
+ assert_approx_equals(rect1.width.animVal.value, 100, epsilon);
+ assert_equals(rect1.width.baseVal.value, 10);
+ expectFillColor(rect1, 0, 128, 0);
+
+ assert_equals(rect2.width.animVal.value, 100);
+ assert_equals(rect2.width.baseVal.value, 10);
+ expectFillColor(rect2, 0, 128, 0);
+
+ assert_equals(rect3.width.animVal.value, 100);
+ assert_equals(rect3.width.baseVal.value, 100);
+ expectFillColor(rect3, 0, 128, 0);
+ assert_equals(rect3.getAttribute('fill'), "red");
+
+ assert_equals(rect4.width.animVal.value, 100);
+ assert_equals(rect4.width.baseVal.value, 100);
+ expectFillColor(rect4, 0, 128, 0);
+ assert_equals(rect4.getAttribute('fill'), "red");
+}
+
+smil_async_test((t) => {
+ rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+ rect2 = rects[1];
+ rect3 = rects[2];
+ rect4 = rects[3];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 60.0, sample3],
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/begin-attribute-mutation.html b/testing/web-platform/tests/svg/animations/begin-attribute-mutation.html
new file mode 100644
index 0000000000..f28c8e9ad1
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/begin-attribute-mutation.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Mutating the 'begin' attribute after the element has started</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="blue">
+ <animate id="anim" attributeName="x" values="100; 0"
+ begin="0s" dur="50ms" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ async_test(function(t) {
+ let anim = document.getElementById("anim");
+ anim.endEventsReceived = 0;
+ anim.addEventListener('endEvent', t.step_func(function() {
+ anim.endEventsReceived++;
+ if (anim.endEventsReceived)
+ t.done();
+ }));
+ onload = function() {
+ // Allow some time to pass before mutating 'begin'. This should ensure
+ // that the element has started.
+ requestAnimationFrame(function() {
+ anim.ownerSVGElement.setCurrentTime(0);
+ anim.setAttribute("begin", "50ms");
+ });
+ };
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/begin-event.svg b/testing/web-platform/tests/svg/animations/begin-event.svg
new file mode 100644
index 0000000000..c673dff9f6
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/begin-event.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'beginEvent'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" end="2s" fill="freeze"/>
+ <set attributeName="width" to="100" begin="anim.beginEvent"/>
+ </rect>
+ <script>
+ async_test(t => {
+ let set = document.querySelector('set');
+ set.addEventListener('beginEvent', t.step_func_done(function() {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ }));
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/beginelement-instance-time-1.html b/testing/web-platform/tests/svg/animations/beginelement-instance-time-1.html
new file mode 100644
index 0000000000..aa1cb8c983
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/beginelement-instance-time-1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>beginElement() timing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg width="100" height="20" style="border: grey 1px solid">
+ <rect width="1" height="20">
+ <animateMotion path="M0,0h100" dur="100ms"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ const svg = document.querySelector('svg');
+ const motion = document.querySelector('animateMotion');
+ motion.addEventListener('endEvent', t.step_func(() => {
+ t.step_timeout(t.step_func(() => {
+ motion.beginElement();
+ let start = svg.getCurrentTime();
+ requestAnimationFrame(t.step_func_done(() => {
+ svg.pauseAnimations();
+ let elapsed = svg.getCurrentTime() - start;
+ let expected_pos = Math.min(elapsed * 1000, 100);
+ let actual_pos = motion.parentElement.getCTM().e;
+ assert_approx_equals(actual_pos, expected_pos, 2, `position after ${elapsed}`);
+ }));
+ }), 50);
+ }), { once: true });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/beginevents-1.html b/testing/web-platform/tests/svg/animations/beginevents-1.html
new file mode 100644
index 0000000000..92debaf82a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/beginevents-1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>beginEvent dispatching</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red">
+ <animate begin="click" dur="10ms" fill="freeze"
+ attributeName="fill" from="red" to="blue"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ window.onload = t.step_func(() => {
+ let rect = document.querySelector("svg > rect");
+ let animate = rect.firstElementChild;
+ let beginEventCount = 0;
+ animate.addEventListener('beginEvent', t.step_func(() => {
+ beginEventCount++;
+ }));
+ animate.addEventListener('endEvent', t.step_func_done(() => {
+ assert_equals(beginEventCount, 1);
+ }));
+ rect.dispatchEvent(new Event("click"));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-freeze.html b/testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-freeze.html
new file mode 100644
index 0000000000..6774c3475a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-freeze.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests scripting a CSS property while animation is running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change opacity from 0 to 0.5 in 4s, a script at 2s will set the opacity CSS property to 1, fill is freeze so this won't have any visible effect, nor any effect to the computed style -->
+<rect opacity="0" width="100" height="100" fill="green">
+ <animate id="an1" attributeType="CSS" attributeName="opacity" fill="freeze" from="0" to="0.5" begin="0s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.25, epsilon);
+ rect.setAttribute("opacity", "1");
+}
+
+function sample3() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.25, epsilon);
+}
+
+function sample4() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.5, epsilon);
+}
+
+function sample5() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.5, epsilon);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 2.001, sample3],
+ ["an1", 3.999, sample4],
+ ["an1", 4.001, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-remove.html b/testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-remove.html
new file mode 100644
index 0000000000..a4e8a3ac40
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-remove.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests scripting a CSS property while animation is running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change opacity from 0 to 0.5 in 4s, a script at 2s will set the opacity CSS property to 1, fill is not freeze, so after the animation ends the opacity should be 1, not 0 -->
+<rect opacity="0" width="100" height="100" fill="green">
+ <animate id="an1" attributeType="CSS" attributeName="opacity" fill="remove" from="0" to="0.5" begin="0s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.25, epsilon);
+ rect.setAttribute("opacity", "1");
+}
+
+function sample3() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.25, epsilon);
+}
+
+function sample4() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.5, epsilon);
+}
+
+function sample5() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 1, epsilon);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 2.001, sample3],
+ ["an1", 3.999, sample4],
+ ["an1", 4.001, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/change-target-while-animating-SVG-property.html b/testing/web-platform/tests/svg/animations/change-target-while-animating-SVG-property.html
new file mode 100644
index 0000000000..68aa63a39d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/change-target-while-animating-SVG-property.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This changes the target of an animation while its running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<rect id="target1" width="150" height="100" fill="green"/>
+<rect id="target2" y="150" width="150" height="100" fill="green"/>
+
+<!-- an1: Change width by -100 in 4s on target1. The embedder script will change the target to 'target2' at 2s. -->
+<!-- target1 should be 100px at 2s and remain this way. target2 should be 50px and remain this way. -->
+<animate id="an1" xlink:href="#target1" attributeType="XML" attributeName="width" fill="freeze" by="-100" begin="0s" dur="4s"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.width.animVal.value, 150, epsilon);
+ assert_equals(rect1.width.baseVal.value, 150);
+
+ assert_approx_equals(rect2.width.animVal.value, 150, epsilon);
+ assert_equals(rect2.width.baseVal.value, 150);
+}
+
+function sample2() {
+ assert_approx_equals(rect1.width.animVal.value, 100, epsilon);
+ assert_equals(rect1.width.baseVal.value, 150);
+
+ assert_approx_equals(rect2.width.animVal.value, 150, epsilon);
+ assert_equals(rect2.width.baseVal.value, 150);
+
+ // Switch to new target while animation is running.
+ // The effect is that rect1 is now reset to the initial state, before any animation was applied to it.
+ // Compatible with FF. In Opera it only works when not driving the timeline using setCurrentTime.
+ rootSVGElement.ownerDocument.getElementById("an1").setAttributeNS(xlinkNS, "xlink:href", "#target2");
+}
+
+function sample3() {
+ assert_approx_equals(rect1.width.animVal.value, 150, epsilon);
+ assert_equals(rect1.width.baseVal.value, 150);
+
+ assert_approx_equals(rect2.width.animVal.value, 100, epsilon);
+ assert_equals(rect2.width.baseVal.value, 150);
+}
+
+function sample4() {
+ assert_approx_equals(rect1.width.animVal.value, 150, epsilon);
+ assert_equals(rect1.width.baseVal.value, 150);
+
+ assert_approx_equals(rect2.width.animVal.value, 50, epsilon);
+ assert_equals(rect2.width.baseVal.value, 150);
+}
+
+function sample5() {
+ assert_equals(rect1.width.animVal.value, 150);
+ assert_equals(rect1.width.baseVal.value, 150);
+
+ assert_equals(rect2.width.animVal.value, 50);
+ assert_equals(rect2.width.baseVal.value, 150);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+ rect2 = rects[1];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 2.001, sample3],
+ ["an1", 3.999, sample4],
+ ["an1", 4.001, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/correct-events-for-short-animations-with-syncbases.html b/testing/web-platform/tests/svg/animations/correct-events-for-short-animations-with-syncbases.html
new file mode 100644
index 0000000000..19e7eef8c1
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/correct-events-for-short-animations-with-syncbases.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+
+<meta charset="utf-8">
+<title>Correct events for short animations with syncbases</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+<link rel="help" href="https://svgwg.org/specs/animations/#TimingAttributes">
+
+<svg viewBox="0 0 250 50" xmlns="http://www.w3.org/2000/svg">
+ <g id="a" opacity="0">
+ <animate attributeName="opacity" from="0" to="1" begin="0ms;last.end+100ms" dur="10ms" fill="freeze"
+ id="first"/>
+ <animate attributeName="opacity" from="1" to="0" begin="last.end" dur="10ms" fill="freeze"/>
+ <rect x="0" y="0" width="50" height="50" fill="#AA0"/>
+ </g>
+ <g id="b" opacity="0">
+ <animate attributeName="opacity" from="1" to="1" begin="first.end+10ms" dur="10ms" fill="freeze"
+ id="last" onend="onend_filling()"/>
+ <animate attributeName="opacity" from="1" to="0" begin="last.end+1ms" dur="10ms" fill="freeze"
+ onbegin="onend_clearing()"/>
+ <rect x="50" y="0" width="50" height="50" fill="#AA0"/>
+ </g>
+</svg>
+<script>
+ let onend_clearing = null;
+ let onend_filling = null;
+
+ async_test(t => {
+ let svg = document.querySelector("svg");
+ // Deliberate no a
+ let b = document.querySelector("#b");
+ let passed = false;
+ let triggers = 0;
+ let filling_steps = 0;
+ let runs = 3; // Issue 379751 broke after 2 cycles, hence this is a 3.
+ onend_filling = t.step_func(() => {
+ filling_steps++;
+ if (filling_steps < (runs + 1)) return;
+ svg.pauseAnimations();
+ assert_unreached("Fired too many onend events.");
+ });
+ onend_clearing = t.step_func(() => {
+ triggers++;
+ if (triggers != runs) return;
+ svg.pauseAnimations();
+ // We don't check the first element, since it might have started fading in
+ assert_not_equals(window.getComputedStyle(b, null).opacity, "1");
+ t.done();
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/cyclic-syncbase-2.html b/testing/web-platform/tests/svg/animations/cyclic-syncbase-2.html
new file mode 100644
index 0000000000..7e27f469e8
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/cyclic-syncbase-2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Cyclic syncbase dependency with syncbase trigger</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="blue">
+ <animate attributeName="fill" from="yellow" to="blue" id="a"
+ begin="c.end; b.begin" dur="10ms"/>
+ </rect>
+ <rect width="100" height="100" x="100" fill="blue">
+ <animate attributeName="fill" from="yellow" to="blue" id="b"
+ begin="c.end; a.begin" dur="10ms"/>
+ </rect>
+ <rect width="100" height="100" x="200" fill="blue">
+ <animate attributeName="fill" from="yellow" to="blue" id="c"
+ begin="0; 15ms" dur="10ms"/>
+ </rect>
+</svg>
+<script>
+ async_test(function(t) {
+ let a = document.getElementById('a');
+ a.begun = 0;
+ a.addEventListener('beginEvent', t.step_func(function() {
+ a.begun++;
+ if (a.begun === 2)
+ t.done();
+ }));
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/cyclic-syncbase-events.html b/testing/web-platform/tests/svg/animations/cyclic-syncbase-events.html
new file mode 100644
index 0000000000..09d5c2e7b8
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/cyclic-syncbase-events.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Cyclic syncbase dependency with syncbase trigger - event dispatching</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="blue">
+ <animate attributeName="fill" from="yellow" to="blue" id="a"
+ begin="c.end; b.begin" dur="10ms"/>
+ </rect>
+ <rect width="100" height="100" x="100" fill="blue">
+ <animate attributeName="fill" from="yellow" to="blue" id="b"
+ begin="c.end; a.begin" dur="10ms"/>
+ </rect>
+ <rect width="100" height="100" x="200" fill="blue">
+ <animate attributeName="fill" from="yellow" to="blue" id="c"
+ begin="0; 15ms" dur="10ms"/>
+ </rect>
+</svg>
+<script>
+ promise_test(function(t) {
+ // Wait for two beginEvent/endEvent pairs on all the timed elements.
+ let promises = ['a', 'b', 'c'].map(function(id) {
+ return new EventWatcher(t, document.getElementById(id),
+ ['beginEvent', 'endEvent'])
+ .wait_for(['beginEvent', 'endEvent',
+ 'beginEvent', 'endEvent']);
+ });
+ return Promise.all(promises);
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/cyclic-syncbase.html b/testing/web-platform/tests/svg/animations/cyclic-syncbase.html
new file mode 100644
index 0000000000..c0351156e3
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/cyclic-syncbase.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test cyclic for svg animations for syncbases</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" end="5s"/>
+ <rect x="0" y="0" width="50" height="50" fill="green">
+ <set attributeName="x" to="100" id="anim1" begin="0; anim2.end" dur="1s"/>
+ <set attributeName="y" to="100" id="anim2" begin="anim1.end" dur="1s"/>
+ </rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 100, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.getBBox().x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.getBBox().y, 100, epsilon);
+}
+
+smil_async_test((t) => {
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["anim", 0.01, sample1],
+ ["anim", 1.01, sample2],
+ ["anim", 2.01, sample1],
+ ["anim", 3.01, sample2],
+ ["anim", 4.01, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/dependent-begin-on-syncbase.html b/testing/web-platform/tests/svg/animations/dependent-begin-on-syncbase.html
new file mode 100644
index 0000000000..591fb64ed8
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/dependent-begin-on-syncbase.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Dependent timed element begin (restart) on syncbase</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="10" height="10" fill="red">
+ <set attributeName="fill" to="blue" begin="0s; other.end" id="dependent"/>
+ </rect>
+ <rect x="10" width="10" height="10" fill="blue">
+ <animate attributeName="fill" from="yellow" to="red"
+ begin="indefinite" dur="10ms" id="other"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ let count = 0;
+ let dependent = document.getElementById('dependent');
+ dependent.addEventListener('endEvent', t.step_func(() => count++));
+ let other = document.getElementById('other');
+ // Wait for #other to end and check animation values.
+ other.addEventListener('endEvent', t.step_func(() => {
+ t.step_timeout(() => {
+ assert_equals(count, 1);
+ assert_equals(getComputedStyle(dependent, null).fill, 'rgb(0, 0, 255)');
+ assert_equals(getComputedStyle(other, null).fill, 'rgb(0, 0, 255)');
+ t.done();
+ });
+ }));
+ let svg = other.ownerSVGElement;
+ // Check initial values.
+ window.onload = t.step_func(() => {
+ window.requestAnimationFrame(t.step_func(() => {
+ assert_equals(count, 0);
+ assert_equals(getComputedStyle(other, null).fill, 'rgb(0, 0, 255)');
+ assert_equals(getComputedStyle(dependent, null).fill, 'rgb(0, 0, 255)');
+ svg.unpauseAnimations();
+ }));
+ });
+ svg.pauseAnimations();
+ other.beginElementAt(0.01);
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/dependent-end-on-syncbase.html b/testing/web-platform/tests/svg/animations/dependent-end-on-syncbase.html
new file mode 100644
index 0000000000..4879e5f6ce
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/dependent-end-on-syncbase.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Dependent timed element end on syncbase</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="10" height="10" fill="blue">
+ <set attributeName="fill" to="yellow" end="other.end" id="dependent"/>
+ </rect>
+ <rect x="10" width="10" height="10" fill="blue">
+ <animate attributeName="fill" from="yellow" to="red"
+ begin="indefinite" dur="10ms" id="other"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ let count = 0;
+ let dependent = document.getElementById('dependent');
+ dependent.addEventListener('endEvent', t.step_func(() => count++));
+ let other = document.getElementById('other');
+ // Wait for #other to end and check animation values.
+ other.addEventListener('endEvent', t.step_func(() => {
+ t.step_timeout(() => {
+ assert_equals(count, 1);
+ assert_equals(getComputedStyle(dependent, null).fill, 'rgb(0, 0, 255)');
+ assert_equals(getComputedStyle(other, null).fill, 'rgb(0, 0, 255)');
+ t.done();
+ });
+ }));
+ let svg = other.ownerSVGElement;
+ // Check initial values.
+ window.onload = t.step_func(() => {
+ window.requestAnimationFrame(t.step_func(() => {
+ assert_equals(count, 0);
+ assert_equals(getComputedStyle(dependent, null).fill, 'rgb(255, 255, 0)');
+ assert_equals(getComputedStyle(other, null).fill, 'rgb(0, 0, 255)');
+ svg.unpauseAnimations();
+ }));
+ });
+ svg.pauseAnimations();
+ other.beginElementAt(0.01);
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/end-attribute-change-end-time.html b/testing/web-platform/tests/svg/animations/end-attribute-change-end-time.html
new file mode 100644
index 0000000000..9f05d7d405
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/end-attribute-change-end-time.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Mutation of the 'end' attribute changes current interval end</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="green">
+ <set attributeName="fill" to="red"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ onload = t.step_func(() => {
+ t.step_timeout(() => {
+ let set = document.querySelector('set');
+ set.setAttribute('end', '0s');
+ requestAnimationFrame(t.step_func_done(() => {
+ assert_equals(getComputedStyle(set.targetElement, null).fill, 'rgb(0, 128, 0)');
+ }));
+ });
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/end-event.svg b/testing/web-platform/tests/svg/animations/end-event.svg
new file mode 100644
index 0000000000..aa0854d692
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/end-event.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'endEvent'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" end="2s"/>
+ <set attributeName="width" to="100" begin="anim.endEvent"/>
+ </rect>
+ <script>
+ async_test(t => {
+ document.documentElement.setCurrentTime(1.99);
+
+ let set = document.querySelector('set');
+ set.addEventListener('beginEvent', t.step_func_done(function() {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ }));
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/end-of-time-001-crash.html b/testing/web-platform/tests/svg/animations/end-of-time-001-crash.html
new file mode 100644
index 0000000000..bd38d93161
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/end-of-time-001-crash.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Seeking the time container to a large value does not cause a crash (or hang)</title>
+<svg>
+ <rect height="100" width="100" fill="blue">
+ <animateTransform begin="18446744073709551557" dur="2" repeatCount="indefinite"
+ attributeName="transform" type="rotate" from="0,15,15" to="360,15,15"/>
+ </rect>
+</svg>
+<script>
+ let svg = document.querySelector("svg");
+ svg.setCurrentTime(18446744073709551557);
+ let html = document.documentElement;
+ html.addEventListener("TestRendered", () => html.classList.remove("reftest-wait"));
+</script>
diff --git a/testing/web-platform/tests/svg/animations/end-of-time-002-crash.html b/testing/web-platform/tests/svg/animations/end-of-time-002-crash.html
new file mode 100644
index 0000000000..6951820f51
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/end-of-time-002-crash.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Seeking the time container to a large value does not cause a crash (or hang)</title>
+<svg>
+ <rect height="100" width="100" fill="blue">
+ <animateTransform begin="18446744073709551557" dur="2" repeatCount="indefinite"
+ attributeName="transform" type="rotate" from="0,15,15" to="360,15,15"/>
+ </rect>
+</svg>
+<script>
+ let svg = document.querySelector("svg");
+ svg.setCurrentTime(9000000000000000);
+ let html = document.documentElement;
+ html.addEventListener("TestRendered", () => html.classList.remove("reftest-wait"));
+</script>
diff --git a/testing/web-platform/tests/svg/animations/eventbase-non-svg-element.html b/testing/web-platform/tests/svg/animations/eventbase-non-svg-element.html
new file mode 100644
index 0000000000..f4e7f793e4
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/eventbase-non-svg-element.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Non-SVGElements are allowed as event-bases</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect height="100" width="100" fill="red">
+ <set attributeName="fill" begin="e.test" to="green"/>
+ </rect>
+</svg>
+<div id="e"></div>
+<script>
+async_test(t => {
+ document.querySelector("set").onbegin = t.step_func_done();
+ document.getElementById("e").dispatchEvent(new Event("test"));
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/first-interval-in-the-past-contribute.html b/testing/web-platform/tests/svg/animations/first-interval-in-the-past-contribute.html
new file mode 100644
index 0000000000..a4c7383b8e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/first-interval-in-the-past-contribute.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Inserting animation elements that end before current presentation time</title>
+<link rel="help" href="https://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/rendering-utils.js"></script>
+<svg>
+ <rect width="100" height="100" fill="orange">
+ <animate attributeName="fill" values="blue;red" dur="10ms" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ promise_test(t => {
+ const rect = document.querySelector('rect');
+ const endWatcher = new Promise(resolve => {
+ document.querySelector('animate').onend = resolve;
+ });
+ return endWatcher
+ .then(() => {
+ const oldAnimation = rect.firstElementChild;
+ const newAnimation = oldAnimation.cloneNode(false);
+ newAnimation.setAttribute('values', 'red;green');
+ rect.replaceChild(newAnimation, oldAnimation);
+ return waitForAtLeastOneFrame();
+ })
+ .then(() => {
+ assert_equals(getComputedStyle(rect).fill, 'rgb(0, 128, 0)', 'new animation applies');
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/first-interval-in-the-past-dont-contribute.html b/testing/web-platform/tests/svg/animations/first-interval-in-the-past-dont-contribute.html
new file mode 100644
index 0000000000..1e9281ae03
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/first-interval-in-the-past-dont-contribute.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Animation element that end before time container begin</title>
+<link rel="help" href="https://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/rendering-utils.js"></script>
+<svg>
+ <rect width="100" height="100" fill="green">
+ <animate attributeName="fill" values="red;red" begin="-1s" dur="1s" fill="freeze"/>
+ </rect>
+ <set attributeName="stroke-width" to="10"/>
+</svg>
+<script>
+ promise_test(t => {
+ const animationStart = new Promise(resolve => {
+ document.querySelector('set').onbegin = resolve;
+ });
+ return animationStart
+ .then(() =>
+ waitForAtLeastOneFrame())
+ .then(() => {
+ const rect = document.querySelector('rect');
+ assert_equals(getComputedStyle(rect).fill, 'rgb(0, 128, 0)', 'animation does not apply');
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/force-use-shadow-tree-recreation-while-animating.html b/testing/web-platform/tests/svg/animations/force-use-shadow-tree-recreation-while-animating.html
new file mode 100644
index 0000000000..7a60e0280b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/force-use-shadow-tree-recreation-while-animating.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This test forces use shadow tree recreation while an animating is running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<defs>
+ <rect id="rect" width="10" height="100" fill="red">
+ <animate id="an1" attributeName="width" fill="freeze" from="10" to="100" begin="0s" dur="4s"/>
+ </rect>
+</defs>
+
+<use xlink:href="#rect"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function forceUseShadowTreeRecreation() {
+ rect.setAttribute("fill", "green");
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.999, sample2],
+ ["an1", 2.0, forceUseShadowTreeRecreation],
+ ["an1", 2.001, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 60.0, sample3],
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/interval-restart-events.html b/testing/web-platform/tests/svg/animations/interval-restart-events.html
new file mode 100644
index 0000000000..3c3ad89a32
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/interval-restart-events.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Event dispatching on interval restart</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg height="0">
+ <rect width="100" height="100" fill="blue">
+ <animate attributeName="x" begin="0s; 10ms" end="20ms" from="0" to="100"
+ id="target"/>
+ <set attributeName="visibility" begin="0s" end="50ms" from="visible" to="visible"
+ id="timekeeper"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ let begin_count = 0, end_count = 0;
+ let target = document.getElementById("target");
+ target.addEventListener("beginEvent", t.step_func(() => {
+ begin_count++;
+ }));
+ target.addEventListener("endEvent", t.step_func(() => {
+ end_count++;
+ }));
+ let timekeeper = document.getElementById("timekeeper");
+ timekeeper.addEventListener("endEvent", t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ assert_equals(begin_count, end_count);
+ }));
+ }));
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/keysplines-x-limits.html b/testing/web-platform/tests/svg/animations/keysplines-x-limits.html
new file mode 100644
index 0000000000..376f04e659
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/keysplines-x-limits.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>'keySplines' with x-values outside of the 0 to 1 range</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect x="10" width="10" height="10" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="20" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="-1 0 1 1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="30" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="2 0 1 1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="10" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="0 0 -1 1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="40" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="0 0 2 1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="50" fill="blue">
+ <animateMotion values="0,50; 250,50" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="-10 0 1 1"
+ calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="60" fill="blue">
+ <animateMotion values="0,60; 250,60" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="10 0 1 1"
+ calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="70" fill="blue">
+ <animateMotion values="0,70; 250,70" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="0 0 -10 1"
+ calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="80" fill="blue">
+ <animateMotion values="0,80; 250,80" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="0 0 10 1"
+ calcMode="spline"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(2.5);
+ window.onload = t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ let rects = document.getElementsByTagName('rect');
+ assert_equals(rects[0].getBBox().x, 125, 'animations applied');
+ assert_equals(rects[1].getBBox().x, 10, 'first control point x less than zero');
+ assert_equals(rects[2].getBBox().x, 10, 'first control point x greater than one');
+ assert_equals(rects[3].getBBox().x, 10, 'second control point x less than zero');
+ assert_equals(rects[4].getBBox().x, 10, 'second control point x greater than one');
+ assert_equals(rects[5].getBBox().x, 10, 'first control point x less than zero');
+ assert_equals(rects[6].getBBox().x, 10, 'first control point x greater than one');
+ assert_equals(rects[7].getBBox().x, 10, 'second control point x less than zero');
+ assert_equals(rects[8].getBBox().x, 10, 'second control point x greater than one');
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/keysplines-y-limits.html b/testing/web-platform/tests/svg/animations/keysplines-y-limits.html
new file mode 100644
index 0000000000..ccfbbe3957
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/keysplines-y-limits.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>'keySplines' with y-values outside of the 0 to 1 range</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect x="10" width="10" height="10" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="20" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="0 -1 1 1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="30" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="0 2 1 1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="10" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="0 0 1 -1" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="40" fill="blue">
+ <animate attributeName="x" values="0; 250" dur="5s"
+ keyTimes="0; 1" keySplines="0 0 1 2" calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="50" fill="blue">
+ <animateMotion values="0,50; 250,50" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="0 -10 1 1"
+ calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="60" fill="blue">
+ <animateMotion values="0,60; 250,60" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="0 10 1 1"
+ calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="70" fill="blue">
+ <animateMotion values="0,70; 250,70" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="0 0 1 -10"
+ calcMode="spline"/>
+ </rect>
+ <rect x="10" width="10" height="10" y="80" fill="blue">
+ <animateMotion values="0,80; 250,80" dur="5s" keyPoints="0; 1"
+ keyTimes="0; 1" keySplines="0 0 1 10"
+ calcMode="spline"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(2.5);
+ window.onload = t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ let rects = document.getElementsByTagName('rect');
+ assert_equals(rects[0].getBBox().x, 125, 'animations applied');
+ assert_equals(rects[1].getBBox().x, 10, 'first control point y less than zero');
+ assert_equals(rects[2].getBBox().x, 10, 'first control point y greater than one');
+ assert_equals(rects[3].getBBox().x, 10, 'second control point y less than zero');
+ assert_equals(rects[4].getBBox().x, 10, 'second control point y greater than one');
+ assert_equals(rects[5].getBBox().x, 10, 'first control point y less than zero');
+ assert_equals(rects[6].getBBox().x, 10, 'first control point y greater than one');
+ assert_equals(rects[7].getBBox().x, 10, 'second control point y less than zero');
+ assert_equals(rects[8].getBBox().x, 10, 'second control point y greater than one');
+ }));
+ });
+ });
+</script>
+
diff --git a/testing/web-platform/tests/svg/animations/multiple-animations-ending.html b/testing/web-platform/tests/svg/animations/multiple-animations-ending.html
new file mode 100644
index 0000000000..a9b7853bb0
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/multiple-animations-ending.html
@@ -0,0 +1,421 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This checks the effect on multiple animations ending on one target</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- Test that the first element can end while others continue without crashing, and the second
+ can end and remain frozen. Also test that a third element can animate after the second has ended
+ but that the result is still to return to the second animation's freeze position. -->
+<rect x='0' y='0' width='50' height='50' fill='green'>
+ <animate id="an1" attributeName='x' from='0' to='100' begin='0s' dur='1s' />
+ <animate id="an2" attributeName='x' from='200' to='250' begin='1.5s' dur='1s' fill='freeze' />
+ <animate id="an3" attributeName='x' from='50' to='0' begin='2.5s' dur='0.5s' />
+</rect>
+
+<!-- Test that a second element can take priority over the first from 0-1s, then
+ test that the first element can animate for 1s, and finally test that the
+ second element can once again animate after the first has ended. After all
+ animations end, test that they are removed and the rect returns to its home. -->
+<rect x='200' y='75' width='50' height='50' fill='green'>
+ <animate id="an4" attributeName='x' from='0' to='10' begin='1s' dur='1s'/>
+ <animate id="an5" attributeName='x' from='100' to='0' begin='0s' dur='2.5s'/>
+</rect>
+
+<!-- Test that a repeating animation can take priority over another animation, and that the
+ end state is the second animation's freeze value. Also test that, after a pause, a third
+ animation can take over and have its freeze value satisfied at the end. -->
+<rect x='0' y='150' width='50' height='50' fill='green'>
+ <animate id="an6" attributeName='x' from='200' to='240' begin='0s' dur='2s' fill='freeze'/>
+ <animate id="an7" attributeName='x' from='0' to='5' begin='1s' dur='0.1s' repeatCount="5" fill='freeze'/>
+ <animate id="an8" attributeName='x' from='250' to='150' begin='3s' dur='1s' fill='freeze'/>
+</rect>
+
+<!-- Test that 4 animations can animate a rect in 20px 'steps' and that correct freeze values are
+ honored even though the animation elements are specified in non-sequential order. Also test
+ that two repeating animations (active for only a short duration) only momentarily
+ affect the overall animation and are correctly removed. -->
+<rect x='0' y='225' width='50' height='50' fill='green'>
+ <animate id="an9" attributeName='x' from='200' to='250' begin='1.6s' dur='0.1s' repeatCount="2" fill='remove'/>
+ <animate id="anA" attributeName='x' from='160' to='180' begin='3s' dur='0.5s' fill='freeze'/>
+ <animate id="anB" attributeName='x' from='110' to='130' begin='2s' dur='0.5s' fill='freeze'/>
+ <animate id="anC" attributeName='x' from='10' to='30' begin='0s' dur='0.5s' fill='freeze'/>
+ <animate id="anD" attributeName='x' from='60' to='80' begin='1s' dur='0.5s' fill='freeze'/>
+ <animate id="anE" attributeName='x' from='200' to='250' begin='3.6s' dur='0.1s' repeatCount="2" fill='remove'/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 10, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 80, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 210, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample3() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 80, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 210, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample4() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 80, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 210, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample5() {
+ assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 60, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 220, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample6() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 0, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 60, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample7() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 0, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 60, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample8() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 5, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample9() {
+ assert_approx_equals(rect1.x.animVal.value, 200, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 5, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample10() {
+ assert_approx_equals(rect1.x.animVal.value, 200, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 5, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample11() {
+ assert_approx_equals(rect1.x.animVal.value, 225, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 10, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample12() {
+ assert_approx_equals(rect1.x.animVal.value, 225, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 20, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 110, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample13() {
+ assert_approx_equals(rect1.x.animVal.value, 225, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 20, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 110, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample14() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample15() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample16() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample17() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample18() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 250, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 160, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample19() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 250, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 160, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample20() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample21() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample22() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 150, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample23() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 200);
+
+ assert_approx_equals(rect3.x.animVal.value, 150, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+
+ assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+ assert_equals(rect4.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+ rect2 = rects[1];
+ rect3 = rects[2];
+ rect4 = rects[3];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 0.499, sample2],
+ ["an1", 0.5, sample3],
+ ["an1", 0.501, sample4],
+ ["an1", 0.999, sample5],
+ ["an1", 1.0, sample6],
+ ["an1", 1.001, sample7],
+ ["an1", 1.499, sample8],
+ ["an1", 1.5, sample9],
+ ["an1", 1.501, sample10],
+ ["an1", 1.999, sample11],
+ ["an1", 2.0, sample12],
+ ["an1", 2.001, sample13],
+ ["an1", 2.499, sample14],
+ ["an1", 2.5, sample15],
+ ["an1", 2.501, sample16],
+ ["an1", 2.999, sample17],
+ ["an1", 3.0, sample18],
+ ["an1", 3.001, sample19],
+ ["an1", 3.499, sample20],
+ ["an1", 3.5, sample21],
+ ["an1", 4.0, sample22],
+ ["an1", 9.0, sample23]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/multiple-animations-fill-freeze.html b/testing/web-platform/tests/svg/animations/multiple-animations-fill-freeze.html
new file mode 100644
index 0000000000..d4a71dcac2
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/multiple-animations-fill-freeze.html
@@ -0,0 +1,149 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This checks the effect on multiple animations on one target</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<rect x='0' y='0' width='50' height='50' fill='green'>
+ <animate id="an1" attributeName='x' from='0' to='100' begin='0s' dur='2s' fill='freeze'/>
+ <animate id="an2" attributeName='x' from='150' to='250' begin='4s' dur='2s' fill='freeze'/>
+</rect>
+
+<rect x='0' y='100' width='50' height='50' fill='green'>
+ <animate id="an3" attributeName='x' from='0' to='100' begin='0s' dur='2s' fill='remove'/>
+ <animate id="an4" attributeName='x' from='150' to='250' begin='4s' dur='2s' fill='freeze'/>
+</rect>
+
+<rect x='0' y='200' width='50' height='50' fill='green'>
+ <animate id="an5" attributeName='x' from='0' to='100' begin='0s' dur='2s' fill='freeze'/>
+ <animate id="an6" attributeName='x' from='150' to='250' begin='4s' dur='2s' fill='remove'/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 0, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 50, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 50, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample3() {
+ assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 100, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample4() {
+ assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 100, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample5() {
+ assert_approx_equals(rect1.x.animVal.value, 150, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 150, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 150, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample6() {
+ assert_approx_equals(rect1.x.animVal.value, 200, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample7() {
+ assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 250, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_approx_equals(rect3.x.animVal.value, 250, epsilon);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample8() {
+ assert_equals(rect1.x.animVal.value, 250);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_equals(rect2.x.animVal.value, 250);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ assert_equals(rect3.x.animVal.value, 100);
+ assert_equals(rect3.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+ rect2 = rects[1];
+ rect3 = rects[2];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.0, sample2],
+ ["an1", 1.999, sample3],
+ ["an1", 2.001, sample4],
+ ["an1", 3.0, sample4],
+ ["an1", 3.999, sample4],
+ ["an1", 4.0, sample5],
+ ["an1", 5.0, sample6],
+ ["an1", 5.999, sample7],
+ ["an1", 6.001, sample8],
+ ["an1", 60.0, sample8]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/multiple-begin-additive-animation.html b/testing/web-platform/tests/svg/animations/multiple-begin-additive-animation.html
new file mode 100644
index 0000000000..9e75bdf17a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/multiple-begin-additive-animation.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests additive='sum' support on animate elements with multiple begin times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
+<rect width="100" height="100" fill="green">
+ <animate id="an1" attributeName="y" attributeType="XML" begin="0s" dur="12s" from="100" to="900" fill="freeze" />
+ <animate attributeName="x" attributeType="XML" calcMode="discrete" begin="0s; 2s" from="0" to="400" dur="8s" additive="sum" />
+</rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function checkBaseValues() {
+return;
+ assert_equals(rect.x.baseVal.value, 0);
+ assert_equals(rect.y.baseVal.value, 0);
+}
+
+function sample1() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 100, epsilon);
+ checkBaseValues();
+}
+
+function sample2() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 166.67, epsilon);
+ checkBaseValues();
+}
+
+function sample3() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 366.60, epsilon);
+ checkBaseValues();
+}
+
+function sample4() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 366.73, epsilon);
+ checkBaseValues();
+}
+
+function sample5() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 499.93, epsilon);
+ checkBaseValues();
+}
+
+function sample6() {
+ assert_equals(rect.x.animVal.value, 400);
+ assert_approx_equals(rect.y.animVal.value, 500.06, epsilon);
+ checkBaseValues();
+}
+
+function sample7() {
+ assert_equals(rect.x.animVal.value, 400);
+ assert_approx_equals(rect.y.animVal.value, 566.67, epsilon);
+ checkBaseValues();
+}
+
+function sample8() {
+ assert_equals(rect.x.animVal.value, 400);
+ assert_approx_equals(rect.y.animVal.value, 633.33, epsilon);
+ checkBaseValues();
+}
+
+function sample9() {
+ assert_equals(rect.x.animVal.value, 400);
+ assert_approx_equals(rect.y.animVal.value, 700, epsilon);
+ checkBaseValues();
+}
+
+function sample10() {
+ assert_equals(rect.x.animVal.value, 400);
+ assert_approx_equals(rect.y.animVal.value, 766.60, epsilon);
+ checkBaseValues();
+}
+
+function sample11() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 766.67, epsilon);
+ checkBaseValues();
+}
+
+function sample12() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 833.33, epsilon);
+ checkBaseValues();
+}
+
+function sample13() {
+ assert_equals(rect.x.animVal.value, 0);
+ assert_approx_equals(rect.y.animVal.value, 900, epsilon);
+ checkBaseValues();
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.0, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample4],
+ ["an1", 5.999, sample5],
+ ["an1", 6.001, sample6],
+ ["an1", 7.0, sample7],
+ ["an1", 7.999, sample8],
+ ["an1", 8.001, sample8],
+ ["an1", 9.0, sample9],
+ ["an1", 9.999, sample10],
+ ["an1", 10.001, sample11],
+ ["an1", 11.0, sample12],
+ ["an1", 11.999, sample13],
+ ["an1", 12.001, sample13],
+ ["an1", 60.0, sample13]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/non-additive-type-by-animation.html b/testing/web-platform/tests/svg/animations/non-additive-type-by-animation.html
new file mode 100644
index 0000000000..b596f73544
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/non-additive-type-by-animation.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This by animation for all non-additive property types - should have no effect.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg id="svg" viewBox="0 0 200 200" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+ <filter id="filter">
+ <feConvolveMatrix id="feConvolveMatrix" kernelMatrix="0 1 0 0 1 0 0 1 0" order="6 6" targetX="5" preserveAlpha="false"/>
+ </filter>
+</defs>
+
+<rect id="rect" y="100" width="100" height="100" fill="black" filter="url(#filter)"/>
+
+<!-- AnimatedBoolean -->
+<animate id="an1" xlink:href="#feConvolveMatrix" attributeName="preserveAlpha" begin="0s" dur="4s" by="true" fill="freeze"/>
+
+<!-- AnimatedEnumeration -->
+<animate xlink:href="#filter" attributeName="filterUnits" begin="0s" dur="4s" by="userSpaceOnUse" fill="freeze"/>
+
+<!-- AnimatedPreserveAspectRatio -->
+<animate xlink:href="#svg" attributeName="preserveAspectRatio" begin="0s" dur="4s" by="xMaxYMax slice" fill="freeze"/>
+
+<!-- AnimatedString -->
+<animate xlink:href="#feConvolveMatrix" attributeName="result" begin="0s" dur="4s" by="test" fill="freeze"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample() {
+ assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+ assert_equals(filter.filterUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(svg.preserveAspectRatio.animVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+ assert_equals(svg.preserveAspectRatio.animVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+ assert_equals(feConvolveMatrix.result.animVal, "");
+
+ assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+ assert_equals(filter.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(svg.preserveAspectRatio.baseVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+ assert_equals(svg.preserveAspectRatio.baseVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+ assert_equals(feConvolveMatrix.result.baseVal, "");
+}
+
+smil_async_test((t) => {
+ filter = rootSVGElement.ownerDocument.getElementsByTagName("filter")[0];
+ feConvolveMatrix = rootSVGElement.ownerDocument.getElementsByTagName("feConvolveMatrix")[0];
+ svg = rootSVGElement.ownerDocument.getElementsByTagName("svg")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample],
+ ["an1", 1.999, sample],
+ ["an1", 2.001, sample],
+ ["an1", 3.999, sample],
+ ["an1", 4.001, sample]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/non-additive-type-from-by-animation.html b/testing/web-platform/tests/svg/animations/non-additive-type-from-by-animation.html
new file mode 100644
index 0000000000..e974e38177
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/non-additive-type-from-by-animation.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This is a from by animation for all non-additive property types - should have no effect.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg id="svg" viewBox="0 0 200 200" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+ <filter id="filter">
+ <feConvolveMatrix id="feConvolveMatrix" kernelMatrix="0 1 0 0 1 0 0 1 0" order="6 6" targetX="5" preserveAlpha="false"/>
+ </filter>
+</defs>
+
+<rect id="rect" y="100" width="100" height="100" fill="black" filter="url(#filter)"/>
+
+<!-- AnimatedBoolean -->
+<animate id="an1" xlink:href="#feConvolveMatrix" attributeName="preserveAlpha" begin="0s" dur="4s" from="false" by="true" fill="freeze"/>
+
+<!-- AnimatedEnumeration -->
+<animate xlink:href="#filter" attributeName="filterUnits" begin="0s" dur="4s" from="objectBoundingBox" by="userSpaceOnUse" fill="freeze"/>
+
+<!-- AnimatedPreserveAspectRatio -->
+<animate xlink:href="#svg" attributeName="preserveAspectRatio" begin="0s" dur="4s" from="xMaxYMax meet" by="xMaxYMax slice" fill="freeze"/>
+
+<!-- AnimatedString -->
+<animate xlink:href="#feConvolveMatrix" attributeName="result" begin="0s" dur="4s" from="foo" by="test" fill="freeze"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample() {
+ assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+ assert_equals(filter.filterUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(svg.preserveAspectRatio.animVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+ assert_equals(svg.preserveAspectRatio.animVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+ assert_equals(feConvolveMatrix.result.animVal, "");
+
+ assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+ assert_equals(filter.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(svg.preserveAspectRatio.baseVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+ assert_equals(svg.preserveAspectRatio.baseVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+ assert_equals(feConvolveMatrix.result.baseVal, "");
+}
+
+smil_async_test((t) => {
+ filter = rootSVGElement.ownerDocument.getElementsByTagName("filter")[0];
+ feConvolveMatrix = rootSVGElement.ownerDocument.getElementsByTagName("feConvolveMatrix")[0];
+ svg = rootSVGElement.ownerDocument.getElementsByTagName("svg")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample],
+ ["an1", 1.999, sample],
+ ["an1", 2.001, sample],
+ ["an1", 3.999, sample],
+ ["an1", 4.001, sample]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/onbegin.svg b/testing/web-platform/tests/svg/animations/onbegin.svg
new file mode 100644
index 0000000000..d3de366f47
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/onbegin.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>'onbegin' event handler content attribute</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" end="2s" fill="freeze"
+ onbegin="document.getElementById('anim2').beginElement()"/>
+ <set id="anim2" attributeName="width" to="100" begin="indefinite"/>
+ </rect>
+ <script>
+ async_test(t => {
+ let set = document.getElementById('anim2');
+ set.addEventListener('beginEvent', t.step_func_done(function() {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ }));
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/onend.svg b/testing/web-platform/tests/svg/animations/onend.svg
new file mode 100644
index 0000000000..46b78af37a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/onend.svg
@@ -0,0 +1,20 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>'onend' event handler content attribute</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" end="2s" fill="freeze"
+ onend="document.getElementById('anim2').beginElement()"/>
+ <set id="anim2" attributeName="width" to="100" begin="indefinite"/>
+ </rect>
+ <script>
+ async_test(t => {
+ document.documentElement.setCurrentTime(1.99);
+
+ let set = document.getElementById('anim2');
+ set.addEventListener('beginEvent', t.step_func_done(function() {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ }));
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/onrepeat.svg b/testing/web-platform/tests/svg/animations/onrepeat.svg
new file mode 100644
index 0000000000..cd4a265b31
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/onrepeat.svg
@@ -0,0 +1,20 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>'onrepeat' event handler content attribute</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="1s" fill="freeze" repeatCount="2"
+ onrepeat="document.getElementById('anim2').beginElement()"/>
+ <set id="anim2" attributeName="width" to="100" begin="indefinite" />
+ </rect>
+ <script>
+ async_test(t => {
+ document.documentElement.setCurrentTime(0.99);
+
+ let set = document.getElementById('anim2');
+ set.addEventListener('beginEvent', t.step_func_done(function() {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ }));
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/pruning-first-interval.html b/testing/web-platform/tests/svg/animations/pruning-first-interval.html
new file mode 100644
index 0000000000..5a1d1463be
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/pruning-first-interval.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Timed element not active after first interval active duration changes to unresolved</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="green">
+ <set attributeName="fill" to="red" fill="freeze"
+ begin="click" end="click" dur="100ms" repeatCount="indefinite"/>
+ </rect>
+</svg>
+<script>
+ async_test(function(t) {
+ let set = document.querySelector('set');
+ window.onload = t.step_func(function() {
+ t.step_timeout(function() {
+ set.setAttribute('begin', '-100ms');
+ set.setAttribute('begin', 'click');
+ set.parentNode.appendChild(set);
+ set.setAttribute('end', '-100ms');
+ set.setAttribute('end', 'click');
+ window.requestAnimationFrame(t.step_func_done(function() {
+ let target = set.targetElement;
+ assert_equals(getComputedStyle(target).fill, 'rgb(0, 128, 0)');
+ }));
+ }, 0);
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/reinserting-svg-into-document.html b/testing/web-platform/tests/svg/animations/reinserting-svg-into-document.html
new file mode 100644
index 0000000000..28d9dc93ce
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/reinserting-svg-into-document.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<title>Reinserting SVG animation into document should continue the animation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg id="svg">
+ <rect id="rect" x="0" y="0" width="20" height="20">
+ <animate attributeName="x" begin="0" from="0" to="90" dur="3s" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+async_test(t => {
+ const svg = document.getElementById('svg');
+
+ // The timeline starts after 'load'.
+ window.onload = t.step_func(() => {
+ svg.setCurrentTime(1);
+
+ t.step_timeout(() => {
+ assert_not_equals(svg.getCurrentTime(), 0, 'started');
+
+ // Removing and re-adding the SVG shouldn't change anything about the
+ // underlying animation.
+ document.body.removeChild(svg);
+ document.body.appendChild(svg);
+
+ // The SVG animation will continue after the next frame runs.
+ window.requestAnimationFrame(t.step_func_done(() => {
+ const rect = document.getElementById('rect');
+ assert_greater_than_equal(svg.getCurrentTime(), 1);
+ assert_greater_than_equal(rect.x.animVal.value, 30);
+ svg.setCurrentTime(2);
+ assert_approx_equals(rect.x.animVal.value, 60, 1);
+ }));
+ });
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/remove-animation-element-while-animation-is-running.html b/testing/web-platform/tests/svg/animations/remove-animation-element-while-animation-is-running.html
new file mode 100644
index 0000000000..764d25b69f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/remove-animation-element-while-animation-is-running.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This removes an animation element while the animation is running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<rect x='0' y='0' width='50' height='50' fill='green'>
+ <animate id="an1" attributeName='x' from='50' to='150' begin='0s' dur='2s' fill='freeze'/>
+</rect>
+
+<rect x='0' y='100' width='50' height='50' fill='green'>
+ <animate id="an2" attributeName='x' from='50' to='150' begin='0s' dur='2s' fill='remove'/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 50, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+}
+
+function sample2() {
+ assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+
+ // Remove the animation element animating rect1
+ // The effect is that rect1 is now reset to the initial state, before any animation was applied to it.
+ // Compatible with FF. In Opera it shows a repainting bug currently (two rects are visible!).
+ var an1 = rootSVGElement.ownerDocument.getElementById("an1");
+ an1.parentNode.removeChild(an1);
+}
+
+function sample3() {
+ assert_equals(rect1.x.animVal.value, 0);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+ assert_equals(rect2.x.baseVal.value, 0);
+}
+
+function sample4() {
+ assert_equals(rect1.x.animVal.value, 0);
+ assert_equals(rect1.x.baseVal.value, 0);
+
+ assert_equals(rect2.x.animVal.value, 0);
+ assert_equals(rect2.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+ var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+ rect1 = rects[0];
+ rect2 = rects[1];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 1.0, sample2],
+ ["an2", 1.001, sample3],
+ ["an2", 2.001, sample4],
+ ["an2", 60.0, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/repeat-event.svg b/testing/web-platform/tests/svg/animations/repeat-event.svg
new file mode 100644
index 0000000000..0a9a3cb893
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-event.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'repeatEvent'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="1s" repeatCount="2" fill="freeze"/>
+ <set attributeName="width" to="100" begin="anim.repeatEvent"/>
+ </rect>
+ <script>
+ async_test(t => {
+ document.documentElement.setCurrentTime(0.99);
+
+ let set = document.querySelector('set');
+ set.addEventListener('beginEvent', t.step_func_done(function() {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ }));
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeat-iteration-event-001.svg b/testing/web-platform/tests/svg/animations/repeat-iteration-event-001.svg
new file mode 100644
index 0000000000..0cf7a7adac
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-iteration-event-001.svg
@@ -0,0 +1,27 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation does not triggers on 'repeat(0)'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="100" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <set attributeName="width" to="0" begin="anim.repeat(0)"/>
+ </rect>
+ <script>
+ function waitForFrame() {
+ return new Promise(resolve => {
+ window.requestAnimationFrame(resolve);
+ });
+ }
+
+ promise_test(t => {
+ let set = document.querySelector("set");
+ new EventWatcher(t, set, 'beginEvent');
+ let windowWatcher = new EventWatcher(t, window, 'load');
+ return windowWatcher.wait_for('load').then(() => {
+ return waitForFrame();
+ }).then(() => {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ });
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeat-iteration-event-002.svg b/testing/web-platform/tests/svg/animations/repeat-iteration-event-002.svg
new file mode 100644
index 0000000000..6d2f379a82
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-iteration-event-002.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'repeat(1)'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <set attributeName="width" to="100" begin="anim.repeat(1)"/>
+ </rect>
+ <script>
+ promise_test(t => {
+ document.documentElement.setCurrentTime(1.995);
+ let set = document.querySelector("set");
+ return new EventWatcher(t, set, 'beginEvent').wait_for('beginEvent').then(() => {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ });
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeat-iteration-event-003.svg b/testing/web-platform/tests/svg/animations/repeat-iteration-event-003.svg
new file mode 100644
index 0000000000..50cb47e61e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-iteration-event-003.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'repeat(2)'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <set attributeName="width" to="100" begin="anim.repeat(2)"/>
+ </rect>
+ <script>
+ promise_test(t => {
+ document.documentElement.setCurrentTime(3.995);
+ let set = document.querySelector("set");
+ return new EventWatcher(t, set, 'beginEvent').wait_for('beginEvent').then(() => {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ });
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeat-iteration-event-004.svg b/testing/web-platform/tests/svg/animations/repeat-iteration-event-004.svg
new file mode 100644
index 0000000000..93c12d6662
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-iteration-event-004.svg
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'repeat(3)'</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="0" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <set attributeName="width" to="100" begin="anim.repeat(3)"/>
+ </rect>
+ <script>
+ promise_test(t => {
+ document.documentElement.setCurrentTime(5.995);
+ let set = document.querySelector("set");
+ return new EventWatcher(t, set, 'beginEvent').wait_for('beginEvent').then(() => {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ });
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeat-iteration-event-005.svg b/testing/web-platform/tests/svg/animations/repeat-iteration-event-005.svg
new file mode 100644
index 0000000000..63ba7fbcd9
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-iteration-event-005.svg
@@ -0,0 +1,29 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>No repeat iteration at interval end</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <rect width="100" height="100" fill="green">
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <set attributeName="width" to="0" begin="anim.repeat(4)"/>
+ </rect>
+ <script>
+ function waitForFrame() {
+ return new Promise(resolve => {
+ window.requestAnimationFrame(resolve);
+ });
+ }
+
+ promise_test(t => {
+ document.documentElement.setCurrentTime(7.995);
+ let set = document.querySelector("set");
+ new EventWatcher(t, set, 'beginEvent');
+ let anim = document.getElementById("anim");
+ let animWatcher = new EventWatcher(t, anim, 'endEvent');
+ return animWatcher.wait_for('endEvent').then(() => {
+ return waitForFrame();
+ }).then(() => {
+ assert_equals(set.parentNode.getBBox().width, 100);
+ });
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeat-iteration-event-006.svg b/testing/web-platform/tests/svg/animations/repeat-iteration-event-006.svg
new file mode 100644
index 0000000000..de4c8f1dae
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeat-iteration-event-006.svg
@@ -0,0 +1,48 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+ <title>Animation triggers on 'repeatEvent' iteration</title>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharness.js"/>
+ <script xmlns="http://www.w3.org/1999/xhtml" src="/resources/testharnessreport.js"/>
+ <g>
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <rect x="0" y="0" width="100" height="100" fill="green">
+ <set attributeName="fill" to="red" begin="anim.repeat(0)"/>
+ </rect>
+ <rect x="200" y="0" width="100" height="100" fill="red">
+ <set attributeName="fill" to="green" begin="anim.repeat(1)"/>
+ </rect>
+ <rect x="0" y="200" width="100" height="100" fill="red">
+ <set attributeName="fill" to="green" begin="anim.repeat(2)"/>
+ </rect>
+ <rect x="200" y="200" width="100" height="100" fill="red">
+ <set attributeName="fill" to="green" begin="anim.repeat(3)"/>
+ </rect>
+ </g>
+ <script>
+ promise_test(t => {
+ let svg = document.documentElement;
+ let anim = document.getElementById('anim');
+ let animWatcher = new EventWatcher(t, anim, ['beginEvent', 'repeatEvent']);
+ // Wait for #anims 'beginEvent' and then step through the
+ // 'repeatEvents' one at a time.
+ let stepsPromise = animWatcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(1.99);
+ return animWatcher.wait_for('repeatEvent');
+ }).then(() => {
+ svg.setCurrentTime(3.99);
+ return animWatcher.wait_for('repeatEvent');
+ }).then(() => {
+ svg.setCurrentTime(5.99);
+ return animWatcher.wait_for('repeatEvent');
+ });
+ let setElements = document.getElementsByTagName('set');
+ let setBeginWatchers = Array.from(setElements).map(element => {
+ return new EventWatcher(t, element, 'beginEvent');
+ });
+ // Expect 'beginEvent' to be dispatched for all but the first 'set' element.
+ let beginPromises = setBeginWatchers.slice(1).map(watcher => {
+ return watcher.wait_for('beginEvent');
+ })
+ return Promise.all([stepsPromise, ...beginPromises]);
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeatcount-numeric-limit.tentative.svg b/testing/web-platform/tests/svg/animations/repeatcount-numeric-limit.tentative.svg
new file mode 100644
index 0000000000..aa0432559b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeatcount-numeric-limit.tentative.svg
@@ -0,0 +1,26 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml">
+ <title>A huge 'repeatCount' (1e+309) is treated as unspecified</title>
+ <h:link rel="help" href="https://svgwg.org/specs/animations/#TimingAttributes"/>
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+
+ <rect width="50" height="100" fill="blue">
+ <animate attributeName="fill" from="#007f00" to="green" dur="10ms" fill="freeze"
+ repeatCount="1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"/>
+ </rect>
+ <rect width="50" height="100" fill="blue" x="50">
+ <animate attributeName="fill" from="#007f00" to="green" dur="10ms" fill="freeze"
+ repeatCount="1e+309"/>
+ </rect>
+ <script>
+ promise_test(t => {
+ let watchers = Array.from(document.getElementsByTagName('animate')).map(element => {
+ let watcher = new EventWatcher(t, element, ['endEvent', 'repeatEvent']);
+ return watcher.wait_for('endEvent').then(() => {
+ assert_equals(getComputedStyle(element).fill, 'rgb(0, 128, 0)');
+ });
+ });
+ return Promise.all(watchers);
+ });
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/repeatn-remove-add-animation.html b/testing/web-platform/tests/svg/animations/repeatn-remove-add-animation.html
new file mode 100644
index 0000000000..8098a88535
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeatn-remove-add-animation.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Remove and add an animation element while the animation is repeating</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+ <rect x="0" y="0" width="50" height="50" fill="lime">
+ <set attributeName="fill" to="red" begin="anim.repeat(0)"/>
+ </rect>
+ <rect x="50" y="0" width="50" height="50" fill="red">
+ <set attributeName="fill" to="lime" begin="anim.repeat(1)"/>
+ </rect>
+ <rect x="0" y="50" width="50" height="50" fill="red">
+ <set attributeName="fill" to="lime" begin="anim.repeat(2)"/>
+ </rect>
+ <rect x="50" y="50" width="50" height="50" fill="red">
+ <set attributeName="fill" to="lime" begin="anim.repeat(3)"/>
+ </rect>
+</svg>
+<script>
+ function recreate(anim) {
+ anim.parentNode.removeChild(anim);
+ return document.querySelector('svg').appendChild(anim.cloneNode());
+ }
+
+ function waitFrame() {
+ return new Promise(resolve => {
+ window.requestAnimationFrame(resolve);
+ });
+ }
+
+ function checkSetElements(setElements, expected) {
+ let fillValues = Array.from(setElements).map(set => {
+ return getComputedStyle(set.targetElement, '').fill;
+ });
+ let remappedExpected = expected.map(color => {
+ const colorMap = {'red': 'rgb(255, 0, 0)', 'lime': 'rgb(0, 255, 0)'};
+ return colorMap[color];
+ })
+ assert_array_equals(fillValues, remappedExpected);
+ }
+
+ promise_test(t => {
+ let svg = document.querySelector('svg');
+ let anim = document.getElementById('anim');
+ let animWatcher = new EventWatcher(t, anim, ['beginEvent', 'repeatEvent']);
+ // Wait for #anims 'beginEvent' and then step through the
+ // 'repeatEvents' one at a time.
+ let stepsPromise = animWatcher.wait_for('beginEvent').then(() => {
+ checkSetElements(setElements, ['lime', 'red', 'red', 'red']);
+ svg.setCurrentTime(1.999);
+ return animWatcher.wait_for('repeatEvent');
+ }).then(() => {
+ return waitFrame();
+ }).then(() => {
+ checkSetElements(setElements, ['lime', 'lime', 'red', 'red']);
+ svg.setCurrentTime(2.999);
+ return waitFrame();
+ }).then(() => {
+ checkSetElements(setElements, ['lime', 'lime', 'red', 'red']);
+ svg.setCurrentTime(3.999);
+ return animWatcher.wait_for('repeatEvent');
+ }).then(() => {
+ return waitFrame();
+ }).then(() => {
+ checkSetElements(setElements, ['lime', 'lime', 'lime', 'red']);
+ let newAnim = recreate(anim);
+ let animWatcher = new EventWatcher(t, newAnim, ['repeatEvent']);
+ svg.setCurrentTime(5.999);
+ return animWatcher.wait_for('repeatEvent');
+ }).then(() => {
+ return waitFrame();
+ }).then(() => {
+ checkSetElements(setElements, ['lime', 'lime', 'lime', 'lime']);
+ });
+ let setElements = document.getElementsByTagName('set');
+ let setBeginWatchers = Array.from(setElements).map(element => {
+ return new EventWatcher(t, element, 'beginEvent');
+ });
+ // Expect 'beginEvent' to be dispatched once for all but the first 'set' element.
+ let setPromises = setBeginWatchers.slice(1).map(watcher => {
+ return watcher.wait_for('beginEvent').then(evt => {
+ let target = evt.target.targetElement;
+ assert_equals(getComputedStyle(target, '').fill, 'rgb(0, 255, 0)');
+ });
+ });
+ return Promise.all([stepsPromise, ...setPromises]);
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/restart-never-and-begin-click.html b/testing/web-platform/tests/svg/animations/restart-never-and-begin-click.html
new file mode 100644
index 0000000000..1a94c8c25b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/restart-never-and-begin-click.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+
+svg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100px;
+ height: 100px;
+}
+
+</style>
+<svg>
+<rect width="100" height="100" fill="black">
+<animate attributeName="opacity" to="0" dur="100ms" begin="click" restart="never">
+</rect>
+</svg>
+<script>
+
+promise_test(async test => {
+ const target = document.querySelector("rect");
+ const animation = document.querySelector("animate");
+
+ // Wait a frame and click on the element to start the animation.
+ await new Promise(requestAnimationFrame);
+
+ // Ensure the animation runs once completely.
+ await Promise.all([
+ new Promise(resolve => animation.addEventListener("beginEvent", resolve, { once: true })),
+ new Promise(resolve => animation.addEventListener("endEvent", resolve, { once: true })),
+ test_driver.click(target)
+ ]);
+
+ // Wait another frame.
+ await new Promise(requestAnimationFrame);
+
+ // Track whether the animation will start again.
+ let began = false;
+ animation.addEventListener("beginEvent", event => began = true, { once: true });
+
+ // Click on the element, which should not trigger the animation.
+ await test_driver.click(target);
+
+ // Wait a couple of frames to give it time to run.
+ await new Promise(requestAnimationFrame);
+ await new Promise(requestAnimationFrame);
+
+ assert_false(began, "The animation must not restart");
+}, "Setting restart='never' prevents animation with begin='click' from restarting");
+
+</script>
+</body>
diff --git a/testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-exceptions.html b/testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-exceptions.html
new file mode 100644
index 0000000000..fe06ac1a37
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-exceptions.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>SVGAnimationElement exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg height="0"><animate begin="foo.begin"/></svg>
+<script>
+setup(function() {
+ window.animationElement = document.querySelector('animate');
+});
+
+test(function() {
+ assert_throws_dom('InvalidStateError', function() { animationElement.getStartTime() });
+}, document.title+', getStartTime throws with unresolved interval.');
+
+test(function() {
+ assert_throws_dom('NotSupportedError', function() { animationElement.getSimpleDuration() });
+}, document.title+', getSimpleDuration throws with undefined simple duration.');
+</script>
diff --git a/testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-getStartTime.html b/testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-getStartTime.html
new file mode 100644
index 0000000000..fec3ff4db2
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/scripted/SVGAnimationElement-getStartTime.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<title>SVGAnimationElement.getStartTime() returns the start time of the current interval.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg height="0">
+ <animate attributeName="visibility" begin="1s; 3s" dur="1s"/>
+ <animate attributeName="visibility" begin="1s; 3s" dur="1s" fill="freeze"/>
+</svg>
+<script>
+setup(function() {
+ window.animationElements = document.querySelectorAll('animate');
+ window.timeContainer = document.querySelector('svg');
+});
+
+function checkStartTime(values, t) {
+ assert_equals(animationElements[0].getStartTime(), values[0],
+ 'start time @ ' + t);
+ assert_equals(animationElements[1].getStartTime(), values[1],
+ 'start time @ ' + t);
+}
+
+function checkHasNoCurrentInterval(t) {
+ assert_throws_dom('InvalidStateError', () => {
+ animationElements[0].getStartTime()
+ }, 'no interval @ ' + t);
+ assert_throws_dom('InvalidStateError', () => {
+ animationElements[1].getStartTime()
+ }, 'no interval @ ' + t);
+}
+
+async_test(t => {
+ timeContainer.pauseAnimations();
+ // Wait for the timeline to start.
+ onload = t.step_func(() => {
+ t.step_timeout(function() {
+ assert_equals(timeContainer.getCurrentTime(), 0);
+ checkStartTime([1, 1], 0);
+ timeContainer.setCurrentTime(1);
+ checkStartTime([1, 1], 1);
+ timeContainer.setCurrentTime(1.5);
+ checkStartTime([1, 1], 1.5);
+ timeContainer.setCurrentTime(2);
+ checkStartTime([3, 3], 2);
+ timeContainer.setCurrentTime(2.5);
+ checkStartTime([3, 3], 2.5);
+ timeContainer.setCurrentTime(3);
+ checkStartTime([3, 3], 3);
+ timeContainer.setCurrentTime(4);
+ checkHasNoCurrentInterval(4);
+ timeContainer.setCurrentTime(5);
+ checkHasNoCurrentInterval(5);
+ t.done();
+ }, 0);
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/scripted/animatetransform-type-missing-value-default.html b/testing/web-platform/tests/svg/animations/scripted/animatetransform-type-missing-value-default.html
new file mode 100644
index 0000000000..aceca27f4c
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/scripted/animatetransform-type-missing-value-default.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<title>&lt;animateTransform> 'type' attribute missing/invalid value default</title>
+<link rel="help" href="https://svgwg.org/specs/animations/#AnimateTransformElementTypeAttribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg height="10">
+ <rect width="10" height="10" fill="blue">
+ <animateTransform attributeName="transform" type="translate"
+ fill="freeze" dur="1s" from="10 0" to="10 0"/>
+ </rect>
+ <rect width="10" height="10" fill="blue">
+ <animateTransform attributeName="transform"
+ fill="freeze" dur="1s" from="30 0" to="30 0"/>
+ </rect>
+ <rect width="10" height="10" fill="blue">
+ <animateTransform attributeName="transform" type="foo"
+ fill="freeze" dur="1s" from="50 0" to="50 0"/>
+ </rect>
+ <rect width="10" height="10" fill="blue">
+ <animateTransform attributeName="transform" type="foo"
+ fill="freeze" dur="1s" from="70 0" to="70 0"/>
+ </rect>
+</svg>
+<script>
+ const animations = document.querySelectorAll('animateTransform');
+
+ async_test(t => {
+ animations[0].addEventListener('beginEvent', t.step_func_done(function() {
+ let ctm = animations[0].targetElement.getCTM();
+ assert_equals(ctm.e, 10);
+ assert_equals(ctm.f, 0);
+ }));
+ }, document.title + ', "type" attribute is "translate"');
+
+ async_test(t => {
+ animations[1].addEventListener('beginEvent', t.step_func_done(function() {
+ let ctm = animations[1].targetElement.getCTM();
+ assert_equals(ctm.e, 30);
+ assert_equals(ctm.f, 0);
+ }));
+ }, document.title + ', missing "type" attribute');
+
+ async_test(t => {
+ animations[2].addEventListener('beginEvent', t.step_func_done(function() {
+ let ctm = animations[2].targetElement.getCTM();
+ assert_equals(ctm.e, 0);
+ assert_equals(ctm.f, 0);
+ }));
+ }, document.title + ', invalid "type" attribute');
+
+ async_test(t => {
+ animations[3].addEventListener('beginEvent', t.step_func(function() {
+ animations[3].removeAttribute('type');
+
+ window.requestAnimationFrame(t.step_func_done(function() {
+ let ctm = animations[3].targetElement.getCTM();
+ assert_equals(ctm.e, 70);
+ assert_equals(ctm.f, 0);
+ }));
+ }));
+ }, document.title + ', removed "type" attribute');
+</script>
diff --git a/testing/web-platform/tests/svg/animations/scripted/end-element-on-inactive-element.svg b/testing/web-platform/tests/svg/animations/scripted/end-element-on-inactive-element.svg
new file mode 100644
index 0000000000..34be9b9781
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/scripted/end-element-on-inactive-element.svg
@@ -0,0 +1,20 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml">
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+ <rect width="100" height="100" fill="red">
+ <set id="anim" attributeName="fill" to="green" begin="indefinite"/>
+ </rect>
+ <script>
+ async_test(t => {
+ let anim = document.getElementById("anim");
+ onload = t.step_func(() => {
+ anim.endElement();
+ anim.beginElement();
+
+ requestAnimationFrame(t.step_func_done(() => {
+ assert_equals(getComputedStyle(anim.parentNode).fill, "rgb(0, 128, 0)");
+ }));
+ });
+ }, "endElement() on an inactive element");
+ </script>
+</svg>
diff --git a/testing/web-platform/tests/svg/animations/scripted/onhover-syncbases.html b/testing/web-platform/tests/svg/animations/scripted/onhover-syncbases.html
new file mode 100644
index 0000000000..de757f369a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/scripted/onhover-syncbases.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Check if onhover events reset correctly when triggered multiple times</title>
+ <link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#interact-EventAttributes">
+ <link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <svg>
+ <circle id="circle" cx="150" cy="75" r="50" fill="#F00">
+ <set attributeName="fill" to="#0F0" begin="mouseover"/>
+ <set attributeName="fill" to="#F00" begin="mouseout"/>
+ </circle>
+ </svg>
+ <script>
+async_test(t => {
+ let rounds = 5; // How many times the cursor is moved in and out
+ let circle = document.querySelector("#circle");
+ let delay = 20;
+ function f() {
+ assert_equals(window.getComputedStyle(circle, null).fill,
+ "rgb(255, 0, 0)")
+ if (rounds-- == 0) {
+ t.done();
+ return;
+ }
+
+ circle.dispatchEvent(new Event("mouseover"));
+ t.step_timeout(function() {
+ assert_equals(window.getComputedStyle(circle, null).fill,
+ "rgb(0, 255, 0)")
+ circle.dispatchEvent(new Event("mouseout"))
+ t.step_timeout(f, delay);
+ }, delay);
+ }
+ t.step_timeout(f, 0);
+});
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/svg/animations/scripted/paced-value-animation-overwrites-keyTimes.html b/testing/web-platform/tests/svg/animations/scripted/paced-value-animation-overwrites-keyTimes.html
new file mode 100644
index 0000000000..56f67dc5ed
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/scripted/paced-value-animation-overwrites-keyTimes.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<title>Paced value animation doesn't overwrite keyTimes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta charset="utf-8">
+<link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+<link rel="help" href="https://www.w3.org/TR/SMIL20/animation.html#animationNS-animateMotionElement">
+<link rel="bug" href="https://bugs.chromium.org/p/chromium/issues/detail?id=231525&hotlist_id=5524&sort=%20rank%20-ID">
+
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="500" height="500">
+ <rect x="151" y="1" width="98" height="98" fill="red"/>
+ <rect id="rect" x="0" y="0" width="100" height="100" fill="green">
+ <animate id="animate1" attributeName="x" dur="10s" calcMode="paced" values="100; 150; 200;" keyTimes="0; 0.2; 1"/>
+ </rect>
+</svg>
+
+<script>
+ async_test(function(t) {
+ window.onload = t.step_func(function() {
+ let svg = document.getElementById('svg');
+ let animate1 = document.getElementById('animate1');
+ let rect = document.getElementById('rect');
+ t.step_timeout(function() {
+ // animate1's keyTimes should not be affected by starting with calcMode=paced
+ animate1.setAttribute('calcMode', 'linear');
+ svg.pauseAnimations();
+ svg.setCurrentTime(2);
+ window.requestAnimationFrame(t.step_func(function() {
+ window.requestAnimationFrame(t.step_func_done(function() {
+ assert_approx_equals(rect.x.animVal.value, 150, 5);
+ }));
+ }));
+ }, 10);
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-1.html b/testing/web-platform/tests/svg/animations/seeking-events-1.html
new file mode 100644
index 0000000000..8a93b45aa1
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-1.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Seeking forwards does not dispatch events for skipped elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="50" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="5s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+ <rect width="50" height="100" x="50" fill="red">
+ <set id="anim2" attributeName="fill" to="green" begin="9s" dur="11s"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(10);
+ new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ let anim2_watcher = new EventWatcher(t, document.getElementById('anim2'), SMIL_EVENTS);
+ return anim2_watcher.wait_for('beginEvent');
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-2.html b/testing/web-platform/tests/svg/animations/seeking-events-2.html
new file mode 100644
index 0000000000..4bfe05b84d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Seeking backwards dispatches 'endEvent' if the element is not active at the seeked-to time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="50" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="5s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+ <rect width="50" height="100" x="50" fill="green">
+ <set id="anim2" attributeName="fill" to="red" begin="9s" dur="11s"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(10);
+ let anim1_watcher = new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ let anim2_watcher = new EventWatcher(t, document.getElementById('anim2'), SMIL_EVENTS);
+ return anim2_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(5.5);
+ return Promise.all([anim1_watcher.wait_for('beginEvent'),
+ anim2_watcher.wait_for('endEvent')]);
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-3.html b/testing/web-platform/tests/svg/animations/seeking-events-3.html
new file mode 100644
index 0000000000..0a8530c212
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-3.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Seeking backwards does not dispatch events for skipped elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="50" height="100" fill="green">
+ <set id="anim1" attributeName="fill" to="red" begin="5s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+ <rect width="50" height="100" x="50" fill="green">
+ <set id="anim2" attributeName="fill" to="red" begin="9s" dur="11s"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(10);
+ new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ let anim2_watcher = new EventWatcher(t, document.getElementById('anim2'), SMIL_EVENTS);
+ return anim2_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(4);
+ return anim2_watcher.wait_for('endEvent');
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-4.html b/testing/web-platform/tests/svg/animations/seeking-events-4.html
new file mode 100644
index 0000000000..5877f0df3a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-4.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Seeking forwards dispatches 'endEvent' if the element is not active at the seeked-to time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="50" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="5s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+ <rect width="50" height="100" x="50" fill="green">
+ <set id="anim2" attributeName="fill" to="red" begin="9s" dur="2s"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(5.5);
+ let anim1_watcher = new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ new EventWatcher(t, document.getElementById('anim2'), SMIL_EVENTS);
+ return anim1_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(11);
+ return anim1_watcher.wait_for('endEvent');
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-5.html b/testing/web-platform/tests/svg/animations/seeking-events-5.html
new file mode 100644
index 0000000000..8d660be615
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-5.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Seeking forwards does not dispatch 'repeatEvent'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="5s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(5.5);
+ let anim1_watcher = new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ return anim1_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(6.5);
+ return new Promise(resolve => {
+ t.step_timeout(resolve);
+ });
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-6.html b/testing/web-platform/tests/svg/animations/seeking-events-6.html
new file mode 100644
index 0000000000..05dfece67a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-6.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Seeking backwards does not dispatch 'repeatEvent'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="5s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(6.5);
+ let anim1_watcher = new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ return anim1_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(5.5);
+ return new Promise(resolve => {
+ t.step_timeout(resolve);
+ });
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-7.html b/testing/web-platform/tests/svg/animations/seeking-events-7.html
new file mode 100644
index 0000000000..b3804f84cb
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-7.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Seeking forwards to a new interval dispatches both 'endEvent' and 'beginEvent'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="2s; 6s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(2.5);
+ let anim1_watcher = new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ return anim1_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(7.5);
+ return anim1_watcher.wait_for(['endEvent', 'beginEvent']);
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-events-8.html b/testing/web-platform/tests/svg/animations/seeking-events-8.html
new file mode 100644
index 0000000000..f679f2f06f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-events-8.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Seeking backwards to a new interval dispatches both 'endEvent' and 'beginEvent'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="red">
+ <set id="anim1" attributeName="fill" to="green" begin="2s; 6s" dur="1s" repeatCount="2" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ const SMIL_EVENTS = ['beginEvent', 'repeatEvent', 'endEvent'];
+
+ promise_test(function(t) {
+ let svg = document.querySelector('svg');
+ svg.pauseAnimations();
+ svg.setCurrentTime(6.5);
+ let anim1_watcher = new EventWatcher(t, document.getElementById('anim1'), SMIL_EVENTS);
+ return anim1_watcher.wait_for('beginEvent').then(() => {
+ svg.setCurrentTime(2.5);
+ return anim1_watcher.wait_for(['endEvent', 'beginEvent']);
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/seeking-to-large-time.html b/testing/web-platform/tests/svg/animations/seeking-to-large-time.html
new file mode 100644
index 0000000000..2f89200cbb
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/seeking-to-large-time.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>SVGSVGElement.prototype.setCurrentTime: Large time argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="green">
+ <set attributeName="fill" to="red"
+ begin="9223372036854775807" dur="10ms"/>
+ </rect>
+</svg>
+<script>
+ async_test(function(t) {
+ onload = t.step_func(function() {
+ document.querySelector("svg").setCurrentTime(9223372036854775807);
+ requestAnimationFrame(t.step_func(function() {
+ t.step_timeout(function() {
+ let rect = document.querySelector('rect');
+ assert_equals(getComputedStyle(rect).fill, 'rgb(0, 128, 0)');
+ t.done();
+ }, 11);
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/short-simple-duration-and-fractional-repeatcount.html b/testing/web-platform/tests/svg/animations/short-simple-duration-and-fractional-repeatcount.html
new file mode 100644
index 0000000000..025dd5092d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/short-simple-duration-and-fractional-repeatcount.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Short simple duration and fractional repeatCount does not hang</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg>
+ <rect width="100" height="100" fill="blue">
+ <animate attributeName="fill" from="red" to="orange"
+ begin="-10ms" dur="0.001ms" repeatCount="0.5"/>
+ </rect>
+</svg>
+<script>
+ async_test(t => {
+ onload = t.step_func(() => {
+ requestAnimationFrame(t.step_func(() => {
+ requestAnimationFrame(t.step_func_done(() => {
+ let rect = document.querySelector("rect");
+ assert_equals(getComputedStyle(rect).fill, 'rgb(0, 0, 255)');
+ }));
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/single-values-animation.html b/testing/web-platform/tests/svg/animations/single-values-animation.html
new file mode 100644
index 0000000000..40aa346186
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/single-values-animation.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests values animation with just a single entry</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width immediately to 100 at 2s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" values="100" begin="2s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample2],
+ ["an1", 60.0, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/slider-switch.html b/testing/web-platform/tests/svg/animations/slider-switch.html
new file mode 100644
index 0000000000..59aa8f29ca
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/slider-switch.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<title>Check correct event bases for onclick</title>
+<meta charset="utf-8">
+<link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#interact-EventAttributes">
+<link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg width="200" height="100">
+ <rect x="0" y="0" width="100" height="100" id="a" fill="#0AA">
+ <set begin="a.click" attributeName="display" to="none" fill="freeze"/>
+ <set begin="b.click" attributeName="display" to="block" fill="freeze"/>
+ </rect>
+ <rect x="100" y="0" width="100" height="100" id="b" display="none" fill="#A0A">
+ <set begin="a.click" attributeName="display" to="block" fill="freeze"/>
+ <set begin="b.click" attributeName="display" to="none" fill="freeze"/>
+ </rect>
+</svg>
+<script>
+ let clicks_remaining = 2;
+ let a = document.querySelector("#a");
+ let b = document.querySelector("#b");
+ function perform_clicks(t) {
+ t.step_timeout(function() {
+ a.dispatchEvent(new Event("click"));
+ t.step_timeout(function() {
+ b.dispatchEvent(new Event("click"));
+ }, 20);
+ }, 20);
+ }
+ async_test(t => {
+ let observer = document.querySelector("#b > set + set");
+ observer.addEventListener('beginEvent', t.step_func(function() {
+ if (clicks_remaining == 0) {
+ assert_equals(window.getComputedStyle(a).display, "block");
+ assert_equals(window.getComputedStyle(b).display, "none");
+ t.done();
+ return;
+ }
+ perform_clicks(t);
+ clicks_remaining--;
+ }));
+ window.onload = t.step_func(() => {
+ perform_clicks(t);
+ clicks_remaining--;
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/spaces-at-end-of-path-data.html b/testing/web-platform/tests/svg/animations/spaces-at-end-of-path-data.html
new file mode 100644
index 0000000000..235259becc
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/spaces-at-end-of-path-data.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<title>Allow trailing empty entry in value list</title>
+<meta charset="utf-8">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://svgwg.org/specs/animations/#ValuesAttribute">
+<link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+
+<svg viewbox="0 0 100 100">
+ <path fill="#1EB287">
+ <animate attributeName="d"
+ dur="1s"
+ repeatCount="indefinite"
+ values="M 0,0 L 50, 0 L 100,100 Z;
+ M 100,0 L 0, 100 L 50, 0 Z; "/>
+ </path>
+</svg>
+
+<script>
+ async_test(function(t) {
+ window.onload = t.step_func(function() {
+ window.requestAnimationFrame(t.step_func_done(function() {
+ let path = document.querySelector("path");
+ assert_not_equals(window.getComputedStyle(path).d, "none");
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/support/animated-path-helpers.js b/testing/web-platform/tests/svg/animations/support/animated-path-helpers.js
new file mode 100644
index 0000000000..3f6fffb907
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/support/animated-path-helpers.js
@@ -0,0 +1,76 @@
+function roundNumbers(value, digits) {
+ // Round numbers to |digits| decimal places.
+ return value.
+ replace(/-?\d*\.\d+(e-?\d+)?/g, function(n) {
+ return (parseFloat(n).toFixed(digits)).
+ replace(/\.\d+/, function(m) {
+ return m.replace(/0+$/, '');
+ }).
+ replace(/\.$/, '').
+ replace(/^-0$/, '0');
+ });
+}
+
+function normalizeValue(value, digits) {
+ // Round numbers and place whitespace between tokens.
+ return roundNumbers(value, digits).
+ replace(/([\w\d.]+|[^\s])/g, '$1 ').
+ replace(/\s+/g, ' ');
+}
+
+// Transform a path seg list into a path string, rounding numbers to |digits|
+// decimal places.
+function serializePathSegList(list, digits) {
+ function segmentArguments(segment) {
+ const kCommandDescriptor = {
+ 'M': ['x', 'y'],
+ 'L': ['x', 'y'],
+ 'C': ['x1', 'y1', 'x2', 'y2', 'x', 'y'],
+ 'Q': ['x1', 'y1', 'x', 'y'],
+ 'S': ['x2', 'y2', 'x', 'y'],
+ 'T': ['x', 'y'],
+ 'A': ['r1', 'r2', 'angle', 'largeArcFlag', 'sweepFlag', 'x', 'y'],
+ 'H': ['x'],
+ 'V': ['y'],
+ 'Z': []
+ };
+ let command = segment.pathSegTypeAsLetter.toUpperCase();
+ return kCommandDescriptor[command].map(field => {
+ return Number(segment[field]).toFixed(digits);
+ });
+ }
+ return Array.from(list).map(segment => {
+ let command = segment.pathSegTypeAsLetter;
+ if (command === 'z')
+ command = 'Z';
+ return [command, ...segmentArguments(segment)].join(' ');
+ }).join(' ');
+}
+
+function normalizeProperty(path_string) {
+ let probePathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+ probePathElement.setAttribute('d', path_string);
+ document.documentElement.appendChild(probePathElement);
+ let string = getComputedStyle(probePathElement).getPropertyValue('d');
+ probePathElement.remove();
+ return string;
+}
+
+// Assert that the animated path data of |target| matches that of
+// |expected_path_string|. Numbers will be rounded to 2 decimal places.
+function assert_animated_path_equals(target, expected_path_string) {
+ const kDecimals = 2;
+ let expected, actual;
+ if ('animatedPathSegList' in target) {
+ let probePathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+ probePathElement.setAttribute('d', expected_path_string);
+ expected = serializePathSegList(probePathElement.pathSegList, kDecimals)
+ actual = serializePathSegList(target.animatedPathSegList, kDecimals);
+ } else if ('d' in target.style) {
+ expected = normalizeValue(normalizeProperty(expected_path_string), kDecimals);
+ actual = normalizeValue(getComputedStyle(target).getPropertyValue('d'), kDecimals);
+ } else {
+ assert_unreached('no animated path data');
+ }
+ assert_equals(actual, expected);
+}
diff --git a/testing/web-platform/tests/svg/animations/svg-style-animate-crash.html b/testing/web-platform/tests/svg/animations/svg-style-animate-crash.html
new file mode 100644
index 0000000000..0ed2140617
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svg-style-animate-crash.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Starting a CSS Animation and Web Animation at the same time on SVG style elements</title>
+<link rel="help" href="https://crbug.com/1264236">
+<style>
+ @keyframes anim {
+ from { color: green; }
+ to { color: red; }
+ }
+
+ #target {
+ animation: anim 1s linear;
+ }
+</style>
+<svg>
+ <style id=target>Test</style>
+</svg>
+<script>
+ addEventListener('load', () => {
+ target.animate({'top': ['0px', '10px']}, 1000);
+ target.offsetTop;
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-grad.html b/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-grad.html
new file mode 100644
index 0000000000..7a81463368
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-grad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from deg to grad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0deg");
+animate.setAttribute("to", "200grad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-rad.html b/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-rad.html
new file mode 100644
index 0000000000..b8ad7300cf
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-rad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from deg to rad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0deg");
+animate.setAttribute("to", "3.14159265rad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-deg.html b/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-deg.html
new file mode 100644
index 0000000000..dd5822db81
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-deg.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from grad to deg.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0grad");
+animate.setAttribute("to", "180deg");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-rad.html b/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-rad.html
new file mode 100644
index 0000000000..28bef66d0f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-rad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from grad to rad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0grad");
+animate.setAttribute("to", "3.14159265rad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-deg.html b/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-deg.html
new file mode 100644
index 0000000000..412f384cc7
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-deg.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from rad to deg.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0rad");
+animate.setAttribute("to", "180deg");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-grad.html b/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-grad.html
new file mode 100644
index 0000000000..d27c052be2
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-grad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from rad to grad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0rad");
+animate.setAttribute("to", "200grad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+ assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+ assert_equals(marker.orientAngle.baseVal.value, 0);
+
+ assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgboolean-animation-1.html b/testing/web-platform/tests/svg/animations/svgboolean-animation-1.html
new file mode 100644
index 0000000000..3e3de673a3
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgboolean-animation-1.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGBoolean.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+defs.appendChild(filter);
+
+var feConvolveMatrix = createSVGElement("feConvolveMatrix");
+feConvolveMatrix.setAttribute("id", "effect");
+feConvolveMatrix.setAttribute("kernelMatrix", "0 0 0 0 1 0 0 0 0");
+feConvolveMatrix.setAttribute("preserveAlpha", "false");
+filter.appendChild(feConvolveMatrix);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "preserveAlpha");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "false");
+animate.setAttribute("to", "true");
+feConvolveMatrix.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+ assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+}
+
+function sample2() {
+ assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+ assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+}
+
+function sample3() {
+ assert_equals(feConvolveMatrix.preserveAlpha.animVal, true);
+ assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-1.html b/testing/web-platform/tests/svg/animations/svgenum-animation-1.html
new file mode 100644
index 0000000000..05b75e9ad8
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-1.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGUnitTypes enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var pattern = createSVGElement("pattern");
+pattern.setAttribute("id", "pattern");
+pattern.setAttribute("patternUnits", "userSpaceOnUse");
+pattern.setAttribute("patternContentUnits", "userSpaceOnUse");
+pattern.setAttribute("width", "50");
+pattern.setAttribute("height", "50");
+defs.appendChild(pattern);
+
+var patternChild = createSVGElement("rect");
+patternChild.setAttribute("width", "1");
+patternChild.setAttribute("height", "1");
+patternChild.setAttribute("fill", "green");
+pattern.appendChild(patternChild);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "url(#pattern)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "patternContentUnits");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "userSpaceOnUse");
+animate.setAttribute("to", "objectBoundingBox");
+animate.setAttribute("fill", "freeze");
+pattern.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(pattern.patternContentUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(pattern.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+}
+
+function sample2() {
+ assert_equals(pattern.patternContentUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(pattern.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-10.html b/testing/web-platform/tests/svg/animations/svgenum-animation-10.html
new file mode 100644
index 0000000000..e645ea5066
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-10.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGMarkerUnitsType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "userSpaceOnUse");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttribute("stroke", "green");
+path.setAttribute("stroke-width", "10");
+path.setAttribute("marker-start", "url(#marker)");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("d", "M 130 135 L 180 135 L 180 185");
+path.setAttribute("transform", "translate(-130, -120)");
+rootSVGElement.appendChild(path);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "markerUnits");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "userSpaceOnUse");
+animate1.setAttribute("to", "strokeWidth");
+animate1.setAttribute("fill", "freeze");
+marker.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_equals(marker.markerUnits.animVal, SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE);
+ assert_equals(marker.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE);
+}
+
+function sample2() {
+ assert_equals(marker.markerUnits.animVal, SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH);
+ assert_equals(marker.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-11.html b/testing/web-platform/tests/svg/animations/svgenum-animation-11.html
new file mode 100644
index 0000000000..ebf8409f2e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-11.html
@@ -0,0 +1,95 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test BlendModeType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+rootSVGElement.appendChild(filter);
+
+var feFlood = createSVGElement("feFlood");
+feFlood.setAttribute("in", "SourceGraphic");
+feFlood.setAttribute("flood-color", "green");
+feFlood.setAttribute("flood-opacity", "0.5");
+feFlood.setAttribute("result", "img");
+filter.appendChild(feFlood);
+
+var feBlend = createSVGElement("feBlend");
+feBlend.setAttribute("in", "SourceGraphic");
+feBlend.setAttribute("in2", "img");
+feBlend.setAttribute("mode", "lighten");
+filter.appendChild(feBlend);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("onclick", "executeTest()");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rootSVGElement.appendChild(rect);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "mode");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "5s");
+animate1.setAttribute("values", "normal;multiply;screen;darken;lighten");
+animate1.setAttribute("fill", "freeze");
+feBlend.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_equals(feBlend.mode.animVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+ assert_equals(feBlend.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+}
+
+function sample2() {
+ assert_equals(feBlend.mode.animVal, SVGFEBlendElement.SVG_FEBLEND_MODE_NORMAL);
+ assert_equals(feBlend.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+}
+
+function sample3() {
+ assert_equals(feBlend.mode.animVal, SVGFEBlendElement.SVG_FEBLEND_MODE_MULTIPLY);
+ assert_equals(feBlend.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+}
+
+function sample4() {
+ assert_equals(feBlend.mode.animVal, SVGFEBlendElement.SVG_FEBLEND_MODE_SCREEN);
+ assert_equals(feBlend.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+}
+
+function sample5() {
+ assert_equals(feBlend.mode.animVal, SVGFEBlendElement.SVG_FEBLEND_MODE_DARKEN);
+ assert_equals(feBlend.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 0.999, sample2],
+ ["animation", 1.001, sample3],
+ ["animation", 1.999, sample3],
+ ["animation", 2.001, sample4],
+ ["animation", 2.999, sample4],
+ ["animation", 3.001, sample5],
+ ["animation", 3.999, sample5],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-12.html b/testing/web-platform/tests/svg/animations/svgenum-animation-12.html
new file mode 100644
index 0000000000..bd60bbc20c
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-12.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGSpreadMethodType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var gradient = createSVGElement("linearGradient");
+gradient.setAttribute("id", "gradient");
+rootSVGElement.appendChild(gradient);
+
+var stop = createSVGElement("stop");
+stop.setAttribute("offset", "1");
+stop.setAttribute("stop-color", "green");
+gradient.appendChild(stop);
+
+var feBlend = createSVGElement("feBlend");
+feBlend.setAttribute("in", "SourceGraphic");
+feBlend.setAttribute("in2", "img");
+feBlend.setAttribute("mode", "lighten");
+gradient.appendChild(feBlend);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("onclick", "executeTest()");
+rect.setAttribute("fill", "url(#gradient)");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rootSVGElement.appendChild(rect);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "spreadMethod");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "3s");
+animate1.setAttribute("values", "pad;reflect;repeat");
+animate1.setAttribute("fill", "freeze");
+gradient.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_equals(gradient.spreadMethod.animVal, SVGGradientElement.SVG_SPREADMETHOD_PAD);
+ assert_equals(gradient.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_PAD);
+}
+
+function sample2() {
+ assert_equals(gradient.spreadMethod.animVal, SVGGradientElement.SVG_SPREADMETHOD_REFLECT);
+ assert_equals(gradient.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_PAD);
+}
+
+function sample3() {
+ assert_equals(gradient.spreadMethod.animVal, SVGGradientElement.SVG_SPREADMETHOD_REPEAT);
+ assert_equals(gradient.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_PAD);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample1],
+ ["animation", 0.999, sample1],
+ ["animation", 1.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 2.999, sample3],
+ ["animation", 3.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-13.html b/testing/web-platform/tests/svg/animations/svgenum-animation-13.html
new file mode 100644
index 0000000000..c6dbb0c44d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-13.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test ChannelSelectorType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defsElement = createSVGElement("defs");
+rootSVGElement.appendChild(defsElement);
+
+var feImage1 = createSVGElement("feImage");
+feImage1.setAttribute("result", "Map");
+feImage1.setAttributeNS(xlinkNS, "xlink:href", "../W3C-SVG-1.1/resources/sphere.png");
+
+var feImage2 = createSVGElement("feImage");
+feImage2.setAttribute("result", "Texture");
+feImage2.setAttributeNS(xlinkNS, "xlink:href", "../W3C-SVG-1.1/resources/DisplaceChecker.png");
+
+var displacementMap = createSVGElement("feDisplacementMap");
+displacementMap.setAttribute("in", "Texture");
+displacementMap.setAttribute("in2", "Map");
+displacementMap.setAttribute("scale", "64");
+displacementMap.setAttribute("xChannelSelector", "B");
+displacementMap.setAttribute("yChannelSelector", "G");
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("filterUnit", "objectBoundingBox");
+filter.setAttribute("x", "0");
+filter.setAttribute("y", "0");
+filter.setAttribute("width", "1");
+filter.setAttribute("height", "1");
+filter.appendChild(feImage1);
+filter.appendChild(feImage2);
+filter.appendChild(displacementMap);
+defsElement.appendChild(filter);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("onclick", "executeTest()");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("filter", "url(#filter)");
+rootSVGElement.appendChild(rect);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "xChannelSelector");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("values", "R;G;B;A");
+animate1.setAttribute("fill", "freeze");
+displacementMap.appendChild(animate1);
+
+// Setup animation test
+function sample1() {
+ assert_equals(displacementMap.xChannelSelector.animVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+ assert_equals(displacementMap.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+}
+
+function sample2() {
+ assert_equals(displacementMap.xChannelSelector.animVal, SVGFEDisplacementMapElement.SVG_CHANNEL_R);
+ assert_equals(displacementMap.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+}
+
+function sample3() {
+ assert_equals(displacementMap.xChannelSelector.animVal, SVGFEDisplacementMapElement.SVG_CHANNEL_G);
+ assert_equals(displacementMap.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+}
+
+function sample4() {
+ assert_equals(displacementMap.xChannelSelector.animVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(displacementMap.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 0.999, sample2],
+ ["animation", 1.001, sample3],
+ ["animation", 1.999, sample3],
+ ["animation", 2.001, sample1],
+ ["animation", 2.999, sample1],
+ ["animation", 3.001, sample4],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample4]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-2.html b/testing/web-platform/tests/svg/animations/svgenum-animation-2.html
new file mode 100644
index 0000000000..a1e27a5ef3
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-2.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test EdgeModeType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var convolveMatrix = createSVGElement("feConvolveMatrix");
+convolveMatrix.setAttribute("in", "SourceGraphic");
+convolveMatrix.setAttribute("order", "3");
+convolveMatrix.setAttribute("kernelMatrix", "3 0 3 0 0 0 3 0 3");
+convolveMatrix.setAttribute("targetX", "0");
+convolveMatrix.setAttribute("edgeMode", "wrap");
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("filterUnits", "userSpaceOnUse");
+filter.setAttribute("x", "0");
+filter.setAttribute("y", "0");
+filter.setAttribute("width", "200");
+filter.setAttribute("height", "200");
+filter.appendChild(convolveMatrix);
+defs.appendChild(filter);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "edgeMode");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("values", "duplicate;none");
+convolveMatrix.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(convolveMatrix.edgeMode.animVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP);
+ assert_equals(convolveMatrix.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP);
+}
+
+function sample2() {
+ assert_equals(convolveMatrix.edgeMode.animVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_DUPLICATE);
+ assert_equals(convolveMatrix.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP);
+}
+
+function sample3() {
+ assert_equals(convolveMatrix.edgeMode.animVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE);
+ assert_equals(convolveMatrix.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-3.html b/testing/web-platform/tests/svg/animations/svgenum-animation-3.html
new file mode 100644
index 0000000000..5ed9f5aa88
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-3.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLengthAdjustType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Initiate the test by clicking at (1, 50) - the 'S'.
+window.clickX = 1;
+
+// Setup test document
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.setAttribute("y", "50");
+text.setAttribute("textLength", "200");
+text.textContent = "Stretched text";
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "lengthAdjust");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "spacing");
+animate.setAttribute("to", "spacingAndGlyphs");
+animate.setAttribute("fill", "freeze");
+text.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.lengthAdjust.animVal, SVGTextContentElement.LENGTHADJUST_SPACING);
+ assert_equals(text.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACING);
+}
+
+function sample2() {
+ assert_equals(text.lengthAdjust.animVal, SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS);
+ assert_equals(text.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACING);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-4.html b/testing/web-platform/tests/svg/animations/svgenum-animation-4.html
new file mode 100644
index 0000000000..652e49655e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-4.html
@@ -0,0 +1,182 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test CompositeOperationType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defsElement = createSVGElement("defs");
+rootSVGElement.appendChild(defsElement);
+
+var off1 = createSVGElement("feOffset");
+off1.setAttribute("dx", "35");
+off1.setAttribute("dy", "25");
+off1.setAttribute("result", "off1");
+
+var flood1 = createSVGElement("feFlood");
+flood1.setAttribute("flood-color", "#408067");
+flood1.setAttribute("flood-opacity", ".8");
+flood1.setAttribute("result", "F1");
+
+var overComposite1 = createSVGElement("feComposite");
+overComposite1.setAttribute("in", "F1");
+overComposite1.setAttribute("in2", "off1");
+overComposite1.setAttribute("operator", "over");
+overComposite1.setAttribute("k1", ".5");
+overComposite1.setAttribute("k2", ".1");
+overComposite1.setAttribute("k3", ".5");
+overComposite1.setAttribute("k4", ".3");
+
+overComposite1.setAttribute("result", "C1");
+
+var off2 = createSVGElement("feOffset");
+off2.setAttribute("in", "SourceGraphic");
+off2.setAttribute("dx", "60");
+off2.setAttribute("dy", "50");
+off2.setAttribute("result", "off2");
+
+var flood2 = createSVGElement("feFlood");
+flood2.setAttribute("flood-color", "#408067");
+flood2.setAttribute("flood-opacity", ".6");
+flood2.setAttribute("result", "F2");
+
+var overComposite2 = createSVGElement("feComposite");
+overComposite2.setAttribute("in", "F2");
+overComposite2.setAttribute("in2", "off2");
+overComposite2.setAttribute("operator", "in");
+overComposite2.setAttribute("result", "C2");
+
+var off3 = createSVGElement("feOffset");
+off3.setAttribute("in", "SourceGraphic");
+off3.setAttribute("dx", "85");
+off3.setAttribute("dy", "75");
+off3.setAttribute("result", "off3");
+
+var flood3 = createSVGElement("feFlood");
+flood3.setAttribute("flood-color", "#408067");
+flood3.setAttribute("flood-opacity", ".4");
+flood3.setAttribute("result", "F3");
+
+var overComposite3 = createSVGElement("feComposite");
+overComposite3.setAttribute("in2", "off3");
+overComposite3.setAttribute("operator", "in");
+overComposite3.setAttribute("result", "C3");
+
+var merge = createSVGElement("feMerge");
+
+var mergeNode1 = createSVGElement("feMergeNode");
+mergeNode1.setAttribute("in", "C1");
+
+var mergeNode2 = createSVGElement("feMergeNode");
+mergeNode2.setAttribute("in", "C2");
+
+var mergeNode3 = createSVGElement("feMergeNode");
+mergeNode3.setAttribute("in", "C3");
+
+var mergeNode4 = createSVGElement("feMergeNode");
+mergeNode4.setAttribute("in", "SourceGraphic");
+
+merge.appendChild(mergeNode3);
+merge.appendChild(mergeNode2);
+merge.appendChild(mergeNode1);
+merge.appendChild(mergeNode4);
+
+var overFilter = createSVGElement("filter");
+overFilter.setAttribute("id", "overFilter");
+overFilter.setAttribute("filterUnits", "objectBoundingBox");
+overFilter.setAttribute("x", "0");
+overFilter.setAttribute("y", "0");
+overFilter.setAttribute("width", "3.5");
+overFilter.setAttribute("height", "4");
+overFilter.appendChild(off1);
+overFilter.appendChild(flood1);
+overFilter.appendChild(overComposite1);
+overFilter.appendChild(off2);
+overFilter.appendChild(flood2);
+overFilter.appendChild(overComposite2);
+overFilter.appendChild(off3);
+overFilter.appendChild(flood3);
+overFilter.appendChild(overComposite3);
+overFilter.appendChild(merge);
+
+defsElement.appendChild(overFilter);
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "#408067");
+rect.setAttribute("filter", "url(#overFilter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "operator");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "5s");
+animate.setAttribute("values", "in;out;atop;xor;arithmetic");
+overComposite1.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(overComposite1.operator.animVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+ assert_equals(overComposite1.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+}
+
+function sample2() {
+ assert_equals(overComposite1.operator.animVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_IN);
+ assert_equals(overComposite1.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+}
+
+function sample3() {
+ assert_equals(overComposite1.operator.animVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OUT);
+ assert_equals(overComposite1.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+}
+
+function sample4() {
+ assert_equals(overComposite1.operator.animVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ATOP);
+ assert_equals(overComposite1.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+}
+
+function sample5() {
+ assert_equals(overComposite1.operator.animVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR);
+ assert_equals(overComposite1.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+}
+
+function sample6() {
+ assert_equals(overComposite1.operator.animVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
+ assert_equals(overComposite1.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 0.999, sample2],
+ ["animation", 1.001, sample3],
+ ["animation", 1.999, sample3],
+ ["animation", 2.001, sample4],
+ ["animation", 2.999, sample4],
+ ["animation", 3.001, sample5],
+ ["animation", 3.999, sample5],
+ ["animation", 4.001, sample6],
+ ["animation", 4.999, sample6],
+ ["animation", 5.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-5.html b/testing/web-platform/tests/svg/animations/svgenum-animation-5.html
new file mode 100644
index 0000000000..1487918bde
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-5.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test MorphologyOperatorType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var morphology = createSVGElement("feMorphology");
+morphology.setAttribute("in", "SourceAlpha");
+morphology.setAttribute("operator", "dilate");
+morphology.setAttribute("radius", "4");
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("filterUnits", "userSpaceOnUse");
+filter.setAttribute("x", "0");
+filter.setAttribute("y", "0");
+filter.setAttribute("width", "700");
+filter.setAttribute("height", "200");
+filter.appendChild(morphology);
+defs.appendChild(filter);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "#408067");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "operator");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "dilate");
+animate.setAttribute("to", "erode");
+morphology.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(morphology.operator.animVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+ assert_equals(morphology.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+}
+
+function sample2() {
+ assert_equals(morphology.operator.animVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_ERODE);
+ assert_equals(morphology.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-6.html b/testing/web-platform/tests/svg/animations/svgenum-animation-6.html
new file mode 100644
index 0000000000..e60c93bbbf
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-6.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test ColorMatrixType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var colorMatrix = createSVGElement("feColorMatrix");
+colorMatrix.setAttribute("in", "SourceGraphic");
+colorMatrix.setAttribute("type", "matrix");
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("filterUnits", "userSpaceOnUse");
+filter.setAttribute("x", "0");
+filter.setAttribute("y", "0");
+filter.setAttribute("width", "700");
+filter.setAttribute("height", "200");
+filter.appendChild(colorMatrix);
+defs.appendChild(filter);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "#408067");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "type");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("values", "matrix;saturate;hueRotate;luminanceToAlpha");
+colorMatrix.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(colorMatrix.type.animVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+ assert_equals(colorMatrix.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+}
+
+function sample2() {
+ assert_equals(colorMatrix.type.animVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE);
+ assert_equals(colorMatrix.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+}
+
+function sample3() {
+ assert_equals(colorMatrix.type.animVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_HUEROTATE);
+ assert_equals(colorMatrix.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+}
+
+function sample4() {
+ assert_equals(colorMatrix.type.animVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA);
+ assert_equals(colorMatrix.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.999, sample1],
+ ["animation", 1.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 2.999, sample3],
+ ["animation", 3.001, sample4],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-7.html b/testing/web-platform/tests/svg/animations/svgenum-animation-7.html
new file mode 100644
index 0000000000..4e2d27e581
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-7.html
@@ -0,0 +1,94 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGStitchOptions/TurbulenceType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("filterUnits", "userSpaceOnUse");
+filter.setAttribute("x", "0");
+filter.setAttribute("y", "0");
+filter.setAttribute("width", "700");
+filter.setAttribute("height", "200");
+defs.appendChild(filter);
+
+var turbulence = createSVGElement("feTurbulence");
+turbulence.setAttribute("in", "foo");
+turbulence.setAttribute("baseFrequency", "0.05");
+turbulence.setAttribute("numOctaves", "3");
+turbulence.setAttribute("seed", "5");
+turbulence.setAttribute("stitchTiles", "stitch");
+turbulence.setAttribute("type", "fractalNoise");
+filter.appendChild(turbulence);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "#408067");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "type");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "fractalNoise");
+animate1.setAttribute("to", "turbulence");
+turbulence.appendChild(animate1);
+
+var animate2 = createSVGElement("animate");
+animate2.setAttribute("attributeName", "stitchTiles");
+animate2.setAttribute("begin", "0s");
+animate2.setAttribute("dur", "4s");
+animate2.setAttribute("from", "stitch");
+animate2.setAttribute("to", "noStitch");
+turbulence.appendChild(animate2);
+
+// Setup animation test
+function sample1() {
+ assert_equals(turbulence.type.animVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE);
+ assert_equals(turbulence.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE);
+
+ assert_equals(turbulence.stitchTiles.animVal, SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH);
+ assert_equals(turbulence.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH);
+}
+
+function sample2() {
+ assert_equals(turbulence.type.animVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE);
+ assert_equals(turbulence.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE);
+
+ assert_equals(turbulence.stitchTiles.animVal, SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH);
+ assert_equals(turbulence.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-8.html b/testing/web-platform/tests/svg/animations/svgenum-animation-8.html
new file mode 100644
index 0000000000..cd00e46d56
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-8.html
@@ -0,0 +1,114 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test ComponentTransferType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var feRFunc = createSVGElement("feFuncR");
+feRFunc.setAttribute("type", "identity");
+feRFunc.setAttribute("amplitude", "10");
+
+var feGFunc = createSVGElement("feFuncG");
+feGFunc.setAttribute("type", "identity");
+feGFunc.setAttribute("amplitude", "10");
+
+var feBFunc = createSVGElement("feFuncB");
+feBFunc.setAttribute("type", "identity");
+feBFunc.setAttribute("amplitude", "110");
+
+var feAFunc = createSVGElement("feFuncA");
+feAFunc.setAttribute("type", "identity");
+feAFunc.setAttribute("amplitude", "110");
+
+var feComponentTransfer = createSVGElement("feComponentTransfer");
+feComponentTransfer.appendChild(feRFunc);
+feComponentTransfer.appendChild(feGFunc);
+feComponentTransfer.appendChild(feBFunc);
+feComponentTransfer.appendChild(feAFunc);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("filterUnits", "objectBoundingBox");
+filter.setAttribute("x", "0%");
+filter.setAttribute("y", "0%");
+filter.setAttribute("width", "100%");
+filter.setAttribute("height", "100%");
+filter.appendChild(feComponentTransfer);
+
+var defs = createSVGElement("defs");
+defs.appendChild(filter);
+rootSVGElement.appendChild(defs);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "#408067");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "type");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "5s");
+animate.setAttribute("values", "identity;table;discrete;linear;gamma");
+feRFunc.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(feRFunc.type.animVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+ assert_equals(feRFunc.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+}
+
+function sample2() {
+ assert_equals(feRFunc.type.animVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_TABLE);
+ assert_equals(feRFunc.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+}
+
+function sample3() {
+ assert_equals(feRFunc.type.animVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE);
+ assert_equals(feRFunc.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+}
+
+function sample4() {
+ assert_equals(feRFunc.type.animVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR);
+ assert_equals(feRFunc.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+}
+
+function sample5() {
+ assert_equals(feRFunc.type.animVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_GAMMA);
+ assert_equals(feRFunc.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.999, sample1],
+ ["animation", 1.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 2.999, sample3],
+ ["animation", 3.001, sample4],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample5],
+ ["animation", 4.999, sample5],
+ ["animation", 5.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgenum-animation-9.html b/testing/web-platform/tests/svg/animations/svgenum-animation-9.html
new file mode 100644
index 0000000000..8aa9d6a761
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-9.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGTextPathSpacingType/SVGTextPathMethodType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M 50 50 L 200 50");
+rootSVGElement.appendChild(path);
+
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var textPath = createSVGElement("textPath");
+textPath.setAttributeNS(xlinkNS, "xlink:href", "#path");
+textPath.setAttribute("spacing", "auto");
+textPath.setAttribute("method", "align");
+textPath.textContent = "test";
+text.appendChild(textPath);
+
+var animate1 = createSVGElement("animate");
+animate1.setAttribute("id", "animation");
+animate1.setAttribute("attributeName", "spacing");
+animate1.setAttribute("begin", "0s");
+animate1.setAttribute("dur", "4s");
+animate1.setAttribute("from", "auto");
+animate1.setAttribute("to", "exact");
+animate1.setAttribute("fill", "freeze");
+textPath.appendChild(animate1);
+
+var animate2 = createSVGElement("animate");
+animate2.setAttribute("attributeName", "method");
+animate2.setAttribute("begin", "0s");
+animate2.setAttribute("dur", "4s");
+animate2.setAttribute("from", "align");
+animate2.setAttribute("to", "stretch");
+animate2.setAttribute("fill", "freeze");
+textPath.appendChild(animate2);
+
+// Setup animation test
+function sample1() {
+ assert_equals(textPath.method.animVal, SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN);
+ assert_equals(textPath.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN);
+
+ assert_equals(textPath.spacing.animVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO);
+ assert_equals(textPath.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO);
+}
+
+function sample2() {
+ assert_equals(textPath.method.animVal, SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH);
+ assert_equals(textPath.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN);
+
+ assert_equals(textPath.spacing.animVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT);
+ assert_equals(textPath.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample2]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svginteger-animation-1.html b/testing/web-platform/tests/svg/animations/svginteger-animation-1.html
new file mode 100644
index 0000000000..7803541691
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svginteger-animation-1.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test animation of SVGInteger.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+defs.appendChild(filter);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var feConvolveMatrix = createSVGElement("feConvolveMatrix");
+feConvolveMatrix.setAttribute("id", "feConvlveMatrix");
+feConvolveMatrix.setAttribute("order", "3");
+feConvolveMatrix.setAttribute("kernelMatrix", "0 0 0 0 1 0 0 0 0");
+feConvolveMatrix.setAttribute("targetX", "0");
+filter.appendChild(feConvolveMatrix);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "targetX");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "2");
+feConvlveMatrix.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 0, epsilon);
+ assert_equals(feConvolveMatrix.targetX.baseVal, 0);
+}
+
+function sample2() {
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 1, epsilon);
+ assert_equals(feConvolveMatrix.targetX.baseVal, 0);
+}
+
+function sample3() {
+ assert_approx_equals(feConvolveMatrix.targetX.animVal, 2, epsilon);
+ assert_equals(feConvolveMatrix.targetX.baseVal, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svginteger-animation-2.html b/testing/web-platform/tests/svg/animations/svginteger-animation-2.html
new file mode 100644
index 0000000000..25ef7ff08e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svginteger-animation-2.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test animation of SVGInteger.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+defs.appendChild(filter);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var feConvolveMatrix = createSVGElement("feConvolveMatrix");
+feConvolveMatrix.setAttribute("id", "feConvlveMatrix");
+feConvolveMatrix.setAttribute("order", "3 1");
+feConvolveMatrix.setAttribute("kernelMatrix", "0 0 1");
+filter.appendChild(feConvolveMatrix);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "order");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "3 1");
+animate.setAttribute("to", "1 3");
+feConvlveMatrix.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 3, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 1, epsilon);
+ assert_equals(feConvolveMatrix.orderX.baseVal, 3);
+ assert_equals(feConvolveMatrix.orderY.baseVal, 1);
+}
+
+function sample2() {
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 2, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 2, epsilon);
+ assert_equals(feConvolveMatrix.orderX.baseVal, 3);
+ assert_equals(feConvolveMatrix.orderY.baseVal, 1);
+}
+
+function sample3() {
+ assert_approx_equals(feConvolveMatrix.orderX.animVal, 1, epsilon);
+ assert_approx_equals(feConvolveMatrix.orderY.animVal, 3, epsilon);
+ assert_equals(feConvolveMatrix.orderX.baseVal, 3);
+ assert_equals(feConvolveMatrix.orderY.baseVal, 1);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-1.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-1.html
new file mode 100644
index 0000000000..67549890cf
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-1.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 50 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="sum" fill="freeze" by="50" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 75, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 7.0, sample4],
+ ["an1", 9.0, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-2.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-2.html
new file mode 100644
index 0000000000..e08c99cb63
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-2.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 50 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="50" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 75, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 7.0, sample4],
+ ["an1", 9.0, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-3.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-3.html
new file mode 100644
index 0000000000..b5ac7a033e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-3.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s, then reset to 10. -->
+<!-- an2: Change width from 10 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="sum" fill="freeze" by="90" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-4.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-4.html
new file mode 100644
index 0000000000..10e8bd7b49
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-4.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s, then reset to 10. -->
+<!-- an2: Change width from 10 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="90" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-6.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-6.html
new file mode 100644
index 0000000000..43beafe220
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-6.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 10 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="90" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-7.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-7.html
new file mode 100644
index 0000000000..7c1dde4a7c
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-7.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 10 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="calc(5%)" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="calc(11.25%)" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-by-8.html b/testing/web-platform/tests/svg/animations/svglength-additive-by-8.html
new file mode 100644
index 0000000000..459fc7382a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-by-8.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 10 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="calc(4% + 8px)" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="calc(10% + 10px)" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 3.999, sample3],
+ ["an1", 4.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-from-by-1.html b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-1.html
new file mode 100644
index 0000000000..ce458e0266
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-1.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests from-by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 50 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" from="10" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="sum" fill="freeze" from="0" by="50" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 75, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 7.0, sample4],
+ ["an1", 9.0, sample5],
+ ["an1", 60.0, sample5]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-from-by-2.html b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-2.html
new file mode 100644
index 0000000000..1ac7eed4e1
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-2.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests from-by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 0 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" from="10" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" from="0" by="100" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 0, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 4.999, sample3],
+ ["an1", 5.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-from-by-3.html b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-3.html
new file mode 100644
index 0000000000..1c22f351da
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-3.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests from-by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 75 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" from="10" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="sum" fill="freeze" from="25" by="25" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 75, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 87.5, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 4.999, sample3],
+ ["an1", 5.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-additive-from-by-4.html b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-4.html
new file mode 100644
index 0000000000..998c37458f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-additive-from-by-4.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests from-by-animations adding to previous underlying values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width from 10 to 50 in 4s -->
+<!-- an2: Change width from 75 to 100 in 4s starting at 5s -->
+<rect width="10" height="100" fill="green">
+ <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" from="10" by="40" begin="0s" dur="4s"/>
+ <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" from="75" by="25" begin="5s" dur="4s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 30, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 50, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 75, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 87.5, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample6() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["an1", 0.0, sample1],
+ ["an1", 2.0, sample2],
+ ["an1", 4.0, sample3],
+ ["an1", 4.999, sample3],
+ ["an1", 5.001, sample4],
+ ["an1", 7.0, sample5],
+ ["an1", 9.0, sample6],
+ ["an1", 60.0, sample6]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeHeight.html b/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeHeight.html
new file mode 100644
index 0000000000..2bb409e8e1
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeHeight.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation on LengthModeHeight.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+rootSVGElement.setAttribute("width", "600");
+rootSVGElement.setAttribute("height", "400");
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("font-size", "10px");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "height");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "50%");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.height.animVal.value, 100, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.height.animVal.value, 150, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.height.animVal.value, 200, epsilon);
+ assert_equals(rect.height.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeOther.html b/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeOther.html
new file mode 100644
index 0000000000..1fd9e0a3b9
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeOther.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation on LengthModeOther.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+rootSVGElement.setAttribute("width", "600");
+rootSVGElement.setAttribute("height", "400");
+
+// Setup test document
+var circle = createSVGElement("circle");
+circle.setAttribute("id", "circle");
+circle.setAttribute("cx", "50");
+circle.setAttribute("cy", "50");
+circle.setAttribute("r", "10");
+circle.setAttribute("fill", "green");
+circle.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "r");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "10");
+animate.setAttribute("to", "50%");
+circle.appendChild(animate);
+rootSVGElement.appendChild(circle);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(circle.r.animVal.value, 10, epsilon);
+ assert_equals(circle.r.baseVal.value, 10);
+}
+
+function sample2() {
+ assert_approx_equals(circle.r.animVal.value, 132.5, epsilon);
+ assert_equals(circle.r.baseVal.value, 10);
+}
+
+function sample3() {
+ assert_approx_equals(circle.r.animVal.value, 254.9, epsilon);
+ assert_equals(circle.r.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeWidth.html b/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeWidth.html
new file mode 100644
index 0000000000..9481d434b9
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-LengthModeWidth.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation on LengthModeWidth.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+rootSVGElement.setAttribute("width", "600");
+rootSVGElement.setAttribute("height", "400");
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("font-size", "10px");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "50%");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 200, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 300, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-1.html b/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-1.html
new file mode 100644
index 0000000000..90a45efa32
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-1.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation with invalid value: No spaces between number and unit.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100 px");
+animate.setAttribute("to", "200 px");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+// Per https://www.w3.org/TR/2001/REC-smil-animation-20010904/#ToAttribute
+// If any values (i.e., the argument-values for from, to, by or values attributes) are not legal,
+// the animation will have no effect
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample1],
+ ["animation", 3.999, sample1],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-2.html b/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-2.html
new file mode 100644
index 0000000000..f9a6bcc40d
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-2.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation with invalid value: No spaces before value.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", " 100pxERROR");
+animate.setAttribute("to", " 200pxERROR");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+// Per https://www.w3.org/TR/2001/REC-smil-animation-20010904/#ToAttribute
+// If any values (i.e., the argument-values for from, to, by or values attributes) are not legal,
+// the animation will have no effect
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample1],
+ ["animation", 3.999, sample1],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-3.html b/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-3.html
new file mode 100644
index 0000000000..1e16245001
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-invalid-value-3.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation with invalid value: No spaces after number and unit.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px ERROR");
+animate.setAttribute("to", "200px ERROR");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+// Per https://www.w3.org/TR/2001/REC-smil-animation-20010904/#ToAttribute
+// If any values (i.e., the argument-values for from, to, by or values attributes) are not legal,
+// the animation will have no effect
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample1],
+ ["animation", 3.999, sample1],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-number-to-number.html b/testing/web-platform/tests/svg/animations/svglength-animation-number-to-number.html
new file mode 100644
index 0000000000..0b4fca52ec
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-number-to-number.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to cm.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "200");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 150, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 200, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-cm.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-cm.html
new file mode 100644
index 0000000000..f51beed02b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-cm.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to cm.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px");
+animate.setAttribute("to", "5cm");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 144.5, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 189, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-ems.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-ems.html
new file mode 100644
index 0000000000..e65125303e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-ems.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to ems.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("font-size", "10px");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px");
+animate.setAttribute("to", "20em");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 150, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 200, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-in.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-in.html
new file mode 100644
index 0000000000..a55b357187
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-in.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to inch.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px");
+animate.setAttribute("to", "2.5in");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 170, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 240, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-number.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-number.html
new file mode 100644
index 0000000000..8eab444caa
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-number.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to number.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px");
+animate.setAttribute("to", "200");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 150, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 200, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-pc.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-pc.html
new file mode 100644
index 0000000000..62d9d9964f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-pc.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to pc.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px");
+animate.setAttribute("to", "15pc");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 170, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 240, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-pt.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-pt.html
new file mode 100644
index 0000000000..d86e090757
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-pt.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to cm.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100pt");
+animate.setAttribute("to", "5cm");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 161.2, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 189, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-px-to-px.html b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-px.html
new file mode 100644
index 0000000000..fdeb773375
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-px-to-px.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation from px to cm.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100px");
+animate.setAttribute("to", "200px");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 150, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 200, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-unitType.html b/testing/web-platform/tests/svg/animations/svglength-animation-unitType.html
new file mode 100644
index 0000000000..4cd6d2d3af
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-unitType.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test change of unit type for SVGLength animation.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "100");
+animate.setAttribute("to", "200px");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_equals(rect.width.animVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER);
+ assert_equals(rect.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER);
+}
+
+function sample2() {
+ assert_equals(rect.width.animVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER);
+ assert_equals(rect.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER);
+}
+
+function sample3() {
+ assert_equals(rect.width.animVal.unitType, SVGLength.SVG_LENGTHTYPE_PX);
+ assert_equals(rect.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.5, sample2],
+ ["animation", 2.5, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglength-animation-values.html b/testing/web-platform/tests/svg/animations/svglength-animation-values.html
new file mode 100644
index 0000000000..a3e485320b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglength-animation-values.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGLength animation set with 'values', different units and different count of spaces.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "width");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("values", "100px; 130 ;4cm ;6in; 200pt");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rect.width.animVal.value, 130, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rect.width.animVal.value, 151.2, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample4() {
+ assert_approx_equals(rect.width.animVal.value, 576, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+function sample5() {
+ assert_approx_equals(rect.width.animVal.value, 267, epsilon);
+ assert_equals(rect.width.baseVal.value, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 1.0, sample2],
+ ["animation", 2.0, sample3],
+ ["animation", 3.0, sample4],
+ ["animation", 3.999, sample5],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglengthlist-animation-1.html b/testing/web-platform/tests/svg/animations/svglengthlist-animation-1.html
new file mode 100644
index 0000000000..198fc8a6fe
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglengthlist-animation-1.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGLengthList with LengthType number.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.textContent = "ABCD";
+text.setAttribute("x", "50 70 90 110");
+text.setAttribute("y", "50");
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "50 70 90 110");
+animate.setAttribute("to", "60 90 120 150");
+text.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 50, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 110, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 70);
+ assert_equals(text.x.baseVal.getItem(2).value, 90);
+ assert_equals(text.x.baseVal.getItem(3).value, 110);
+}
+
+function sample2() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 55, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 105, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 130, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 70);
+ assert_equals(text.x.baseVal.getItem(2).value, 90);
+ assert_equals(text.x.baseVal.getItem(3).value, 110);
+}
+
+function sample3() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 60, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 120, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 150, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 70);
+ assert_equals(text.x.baseVal.getItem(2).value, 90);
+ assert_equals(text.x.baseVal.getItem(3).value, 110);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglengthlist-animation-2.html b/testing/web-platform/tests/svg/animations/svglengthlist-animation-2.html
new file mode 100644
index 0000000000..c1c91b83f0
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglengthlist-animation-2.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGLengthList with different LengthTypes.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.textContent = "ABCD";
+text.setAttribute("x", "50 70 90 110");
+text.setAttribute("y", "50");
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "50 70px 5cm 8pt");
+animate.setAttribute("to", "3cm 80 100px 4in");
+text.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 50, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 110, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 70);
+ assert_equals(text.x.baseVal.getItem(2).value, 90);
+ assert_equals(text.x.baseVal.getItem(3).value, 110);
+}
+
+function sample2() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 81.7, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 75, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 144.5, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 197.3, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 70);
+ assert_equals(text.x.baseVal.getItem(2).value, 90);
+ assert_equals(text.x.baseVal.getItem(3).value, 110);
+}
+
+function sample3() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 113.4, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 100, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 384, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 70);
+ assert_equals(text.x.baseVal.getItem(2).value, 90);
+ assert_equals(text.x.baseVal.getItem(3).value, 110);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglengthlist-animation-3.html b/testing/web-platform/tests/svg/animations/svglengthlist-animation-3.html
new file mode 100644
index 0000000000..d26e67a8a0
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglengthlist-animation-3.html
@@ -0,0 +1,78 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<meta name="timeout" content="long">
+<title>Test 'to' animation of SVGLengthList with different count of items.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.textContent = "ABCD";
+text.setAttribute("x", "50");
+text.setAttribute("y", "50");
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "50");
+animate.setAttribute("to", "70 80 90 110");
+text.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.x.animVal.numberOfItems, 1);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 50, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 1);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+}
+
+function sample2() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 110, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 1);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+}
+
+function sample3() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 110, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 1);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svglengthlist-animation-4.html b/testing/web-platform/tests/svg/animations/svglengthlist-animation-4.html
new file mode 100644
index 0000000000..0e890ab5f5
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglengthlist-animation-4.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'by' animation of SVGLengthList.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.textContent = "ABCD";
+text.setAttribute("x", "50 60 70 80");
+text.setAttribute("y", "50");
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "50 60 70 80");
+animate.setAttribute("by", "20 20 20 20");
+text.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 50, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 60, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 80, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 60);
+ assert_equals(text.x.baseVal.getItem(2).value, 70);
+ assert_equals(text.x.baseVal.getItem(3).value, 80);
+}
+
+function sample2() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 60, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 90, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 60);
+ assert_equals(text.x.baseVal.getItem(2).value, 70);
+ assert_equals(text.x.baseVal.getItem(3).value, 80);
+}
+
+function sample3() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 100, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 60);
+ assert_equals(text.x.baseVal.getItem(2).value, 70);
+ assert_equals(text.x.baseVal.getItem(3).value, 80);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svglengthlist-animation-5.html b/testing/web-platform/tests/svg/animations/svglengthlist-animation-5.html
new file mode 100644
index 0000000000..5d0bc2b483
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svglengthlist-animation-5.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test additive='sum' animation of SVGLengthList.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.setAttribute("id", "text");
+text.textContent = "ABCD";
+text.setAttribute("x", "50 60 70 80");
+text.setAttribute("y", "50");
+text.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(text);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "x");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("additive", "sum");
+animate.setAttribute("from", "0 0 0 0");
+animate.setAttribute("to", "20 20 20 20");
+text.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 50, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 60, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 80, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 60);
+ assert_equals(text.x.baseVal.getItem(2).value, 70);
+ assert_equals(text.x.baseVal.getItem(3).value, 80);
+}
+
+function sample2() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 60, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 90, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 60);
+ assert_equals(text.x.baseVal.getItem(2).value, 70);
+ assert_equals(text.x.baseVal.getItem(3).value, 80);
+}
+
+function sample3() {
+ assert_equals(text.x.animVal.numberOfItems, 4);
+ assert_approx_equals(text.x.animVal.getItem(0).value, 70, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(1).value, 80, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.x.animVal.getItem(3).value, 100, epsilon);
+
+ assert_equals(text.x.baseVal.numberOfItems, 4);
+ assert_equals(text.x.baseVal.getItem(0).value, 50);
+ assert_equals(text.x.baseVal.getItem(1).value, 60);
+ assert_equals(text.x.baseVal.getItem(2).value, 70);
+ assert_equals(text.x.baseVal.getItem(3).value, 80);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumber-animation-1.html b/testing/web-platform/tests/svg/animations/svgnumber-animation-1.html
new file mode 100644
index 0000000000..72c2d73677
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumber-animation-1.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for SVGNumber animation.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("opacity", "0");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "opacity");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "1");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.5, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 1, epsilon);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumber-animation-2.html b/testing/web-platform/tests/svg/animations/svgnumber-animation-2.html
new file mode 100644
index 0000000000..1654480ffc
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumber-animation-2.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for SVGNumber animation with different exponents.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("opacity", "0");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "opacity");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0e10");
+animate.setAttribute("to", ".1e1");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0, epsilon);
+}
+
+function sample2() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 0.5, epsilon);
+}
+
+function sample3() {
+ assert_approx_equals(parseFloat(getComputedStyle(rect).opacity), 1, epsilon);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumber-animation-3.html b/testing/web-platform/tests/svg/animations/svgnumber-animation-3.html
new file mode 100644
index 0000000000..255eeb0a94
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumber-animation-3.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for SVGNumber animation with invalid units.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("opacity", "0");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "opacity");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0px");
+animate.setAttribute("to", "1px");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample() {
+ // Check initial/end conditions
+ assert_equals(getComputedStyle(rect).opacity, '0');
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample],
+ ["animation", 2.0, sample],
+ ["animation", 3.999, sample],
+ ["animation", 4.001, sample]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumber-animation-4.html b/testing/web-platform/tests/svg/animations/svgnumber-animation-4.html
new file mode 100644
index 0000000000..758138d667
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumber-animation-4.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test for SVGNumber animation on SVG DOM properties.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var gradient = createSVGElement("linearGradient");
+gradient.setAttribute("id", "gradient");
+
+var stop1 = createSVGElement("stop");
+stop1.setAttribute("offset", "0");
+stop1.setAttribute("stop-color", "green");
+gradient.appendChild(stop1);
+
+var stop2 = createSVGElement("stop");
+stop2.setAttribute("offset", "1");
+stop2.setAttribute("stop-color", "red");
+gradient.appendChild(stop2);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(gradient);
+rootSVGElement.appendChild(defsElement);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "0");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "url(#gradient)");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeType", "XML");
+animate.setAttribute("attributeName", "offset");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0");
+animate.setAttribute("to", "1");
+animate.setAttribute("fill", "freeze");
+stop1.appendChild(animate);
+
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(stop1.offset.animVal, 0, epsilon);
+ assert_equals(stop1.offset.baseVal, 0);
+}
+
+function sample2() {
+ assert_approx_equals(stop1.offset.animVal, 0.5, epsilon);
+ assert_equals(stop1.offset.baseVal, 0);
+}
+
+function sample3() {
+ assert_approx_equals(stop1.offset.animVal, 1, epsilon);
+ assert_equals(stop1.offset.baseVal, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 4.0, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumberlist-animation-1.html b/testing/web-platform/tests/svg/animations/svgnumberlist-animation-1.html
new file mode 100644
index 0000000000..aabb7d7daa
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumberlist-animation-1.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGNumberList animation on 'rotate' attribute of text.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.textContent = "ABCD";
+text.setAttribute("x", "40 60 80 100");
+text.setAttribute("y", "60");
+text.setAttribute("rotate", "15");
+text.setAttribute("fill", "green");
+text.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "rotate");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0 0 0 0");
+animate.setAttribute("to", "45 90 135 180");
+text.appendChild(animate);
+rootSVGElement.appendChild(text);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.rotate.animVal.numberOfItems, 1);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 15, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+function sample2() {
+ assert_equals(text.rotate.animVal.numberOfItems, 4);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 0, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(1).value, 0, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(2).value, 0, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(3).value, 0, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+function sample3() {
+ assert_equals(text.rotate.animVal.numberOfItems, 4);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 22.5, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(1).value, 45, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(2).value, 67.5, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(3).value, 90, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+function sample4() {
+ assert_equals(text.rotate.animVal.numberOfItems, 4);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 45, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(1).value, 90, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(2).value, 135, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(3).value, 180, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 2.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumberlist-animation-2.html b/testing/web-platform/tests/svg/animations/svgnumberlist-animation-2.html
new file mode 100644
index 0000000000..e62bbf6860
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumberlist-animation-2.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'by' animation of SVGNumberList on 'rotate' attribute of text.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var text = createSVGElement("text");
+text.textContent = "ABCD";
+text.setAttribute("x", "40 60 80 100");
+text.setAttribute("y", "60");
+text.setAttribute("rotate", "15");
+text.setAttribute("fill", "green");
+text.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "rotate");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0 45 90 135");
+animate.setAttribute("by", "45 45 45 45");
+text.appendChild(animate);
+rootSVGElement.appendChild(text);
+
+// Setup animation test
+function sample1() {
+ assert_equals(text.rotate.animVal.numberOfItems, 1);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 15, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+function sample2() {
+ assert_equals(text.rotate.animVal.numberOfItems, 4);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 0, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(1).value, 45, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(2).value, 90, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(3).value, 135, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+function sample3() {
+ assert_equals(text.rotate.animVal.numberOfItems, 4);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 22.5, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(1).value, 67.5, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(2).value, 112.5, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(3).value, 157.5, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+function sample4() {
+ assert_equals(text.rotate.animVal.numberOfItems, 4);
+ assert_approx_equals(text.rotate.animVal.getItem(0).value, 45, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(1).value, 90, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(2).value, 135, epsilon);
+ assert_approx_equals(text.rotate.animVal.getItem(3).value, 180, epsilon);
+
+ assert_equals(text.rotate.baseVal.numberOfItems, 1);
+ assert_equals(text.rotate.baseVal.getItem(0).value, 15);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 2.0, sample3],
+ ["animation", 3.999, sample4],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-1.html b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-1.html
new file mode 100644
index 0000000000..b20855140f
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-1.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGNumberOptionalNumber with optional number.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("x", "-30%");
+filter.setAttribute("y", "-30%");
+filter.setAttribute("width", "160%");
+filter.setAttribute("height", "160%");
+defs.appendChild(filter);
+
+var feGaussianBlur = createSVGElement("feGaussianBlur");
+feGaussianBlur.setAttribute("id", "blur");
+feGaussianBlur.setAttribute("stdDeviation", "5");
+filter.appendChild(feGaussianBlur);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "50");
+rect.setAttribute("y", "50");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "stdDeviation");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "5 5");
+animate.setAttribute("to", "40 10");
+feGaussianBlur.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+function sample2() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 22.5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 7.5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+function sample3() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 40, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 10, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 100;
+window.clickY = 100;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-2.html b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-2.html
new file mode 100644
index 0000000000..db2576533c
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-2.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGNumberOptionalNumber without optional number.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("x", "-30%");
+filter.setAttribute("y", "-30%");
+filter.setAttribute("width", "160%");
+filter.setAttribute("height", "160%");
+defs.appendChild(filter);
+
+var feGaussianBlur = createSVGElement("feGaussianBlur");
+feGaussianBlur.setAttribute("id", "blur");
+feGaussianBlur.setAttribute("stdDeviation", "5");
+filter.appendChild(feGaussianBlur);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "50");
+rect.setAttribute("y", "50");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "stdDeviation");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "5");
+animate.setAttribute("to", "40 10");
+feGaussianBlur.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+function sample2() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 22.5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 7.5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+function sample3() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 40, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 10, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 60;
+window.clickY = 60;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-3.html b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-3.html
new file mode 100644
index 0000000000..974c1d7034
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-3.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGNumberOptionalNumber without optional number.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("x", "-30%");
+filter.setAttribute("y", "-30%");
+filter.setAttribute("width", "160%");
+filter.setAttribute("height", "160%");
+defs.appendChild(filter);
+
+var feGaussianBlur = createSVGElement("feGaussianBlur");
+feGaussianBlur.setAttribute("id", "blur");
+feGaussianBlur.setAttribute("stdDeviation", "40 10");
+filter.appendChild(feGaussianBlur);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "50");
+rect.setAttribute("y", "50");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "stdDeviation");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "40 10");
+animate.setAttribute("to", "5");
+feGaussianBlur.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 40, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 10, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 40);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 10);
+}
+
+function sample2() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 22.5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 7.5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 40);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 10);
+}
+
+function sample3() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 40);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 10);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 60;
+window.clickY = 60;
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-4.html b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-4.html
new file mode 100644
index 0000000000..4c734b5373
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgnumberoptionalnumber-animation-4.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<html>
+<title>Test 'by' animation of SVGNumberOptionalNumber.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+filter.setAttribute("x", "-30%");
+filter.setAttribute("y", "-30%");
+filter.setAttribute("width", "160%");
+filter.setAttribute("height", "160%");
+defs.appendChild(filter);
+
+var feGaussianBlur = createSVGElement("feGaussianBlur");
+feGaussianBlur.setAttribute("id", "blur");
+feGaussianBlur.setAttribute("stdDeviation", "5");
+filter.appendChild(feGaussianBlur);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("x", "50");
+rect.setAttribute("y", "50");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "stdDeviation");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "5");
+animate.setAttribute("by", "10");
+feGaussianBlur.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 5, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 5, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+function sample2() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 10, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 10, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+function sample3() {
+ assert_approx_equals(feGaussianBlur.stdDeviationX.animVal, 15, epsilon);
+ assert_approx_equals(feGaussianBlur.stdDeviationY.animVal, 15, epsilon);
+
+ assert_equals(feGaussianBlur.stdDeviationX.baseVal, 5);
+ assert_equals(feGaussianBlur.stdDeviationY.baseVal, 5);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.clickX = 60;
+window.clickY = 60;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgpath-animation-1.tentative.html b/testing/web-platform/tests/svg/animations/svgpath-animation-1.tentative.html
new file mode 100644
index 0000000000..3df821d7c3
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgpath-animation-1.tentative.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<title>'by' path animation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+<script src="support/animated-path-helpers.js"></script>
+<svg></svg>
+<script>
+var rootSVGElement = document.querySelector("svg");
+
+// Setup test document
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M 40 40 L 60 40 L 60 60 L 40 60 z");
+path.setAttribute("fill", "green");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "d");
+animate.setAttribute("from", "M 40 40 L 60 40 L 60 60 L 40 60 z");
+animate.setAttribute("by", "M 0 0 L 100 0 L 100 100 L 0 100 z");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("fill", "freeze");
+animate.setAttribute("dur", "4s");
+path.appendChild(animate);
+rootSVGElement.appendChild(path);
+
+smil_async_test(t => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, () => {
+ assert_animated_path_equals(path,
+ "M 40 40 L 60 40 L 60 60 L 40 60 z");
+ }],
+ ["animation", 1.999, () => {
+ assert_animated_path_equals(path,
+ "M 40 40 L 109.975 40 L 109.975 109.975 L 40 109.975 Z");
+ }],
+ ["animation", 2.001, () => {
+ assert_animated_path_equals(path,
+ "M 40 40 L 110.025 40 L 110.025 110.025 L 40 110.025 Z");
+ }],
+ ["animation", 3.999, () => {
+ assert_animated_path_equals(path,
+ "M 40 40 L 159.975 40 L 159.975 159.975 L 40 159.975 Z");
+ }],
+ ["animation", 4.001, () => {
+ assert_animated_path_equals(path,
+ "M 40 40 L 160 40 L 160 160 L 40 160 Z");
+ }]
+ ];
+ runAnimationTest(t, expectedValues);
+});
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgpointlist-animation-1.html b/testing/web-platform/tests/svg/animations/svgpointlist-animation-1.html
new file mode 100644
index 0000000000..a3340ba83a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgpointlist-animation-1.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<title>Tests from-to animation of points on polygons.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var poly = createSVGElement("polygon");
+poly.setAttribute("id", "poly");
+poly.setAttribute("fill", "green");
+poly.setAttribute("points", "0,0 200,0 200,200 0,200");
+poly.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "points");
+animate.setAttribute("from", "0,0 200,0 200,200 0,200");
+animate.setAttribute("to", "0,0 100,0 100,100 0,100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+poly.appendChild(animate);
+rootSVGElement.appendChild(poly);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(poly.animatedPoints.getItem(2).x, 200, epsilon);
+ assert_approx_equals(poly.animatedPoints.getItem(2).y, 200, epsilon);
+
+ assert_equals(poly.points.getItem(2).x, 200);
+ assert_equals(poly.points.getItem(2).y, 200);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(poly.animatedPoints.getItem(2).x, 150, epsilon);
+ assert_approx_equals(poly.animatedPoints.getItem(2).y, 150, epsilon);
+
+ assert_equals(poly.points.getItem(2).x, 200);
+ assert_equals(poly.points.getItem(2).y, 200);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(poly.animatedPoints.getItem(2).x, 100, epsilon);
+ assert_approx_equals(poly.animatedPoints.getItem(2).y, 100, epsilon);
+
+ assert_equals(poly.points.getItem(2).x, 200);
+ assert_equals(poly.points.getItem(2).y, 200);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgpointlist-animation-2.html b/testing/web-platform/tests/svg/animations/svgpointlist-animation-2.html
new file mode 100644
index 0000000000..e0819cd519
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgpointlist-animation-2.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<title>Tests from-by animation of points on polygons.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var poly = createSVGElement("polygon");
+poly.setAttribute("id", "poly");
+poly.setAttribute("fill", "green");
+poly.setAttribute("points", "0,0 200,0 200,200 0,200");
+poly.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "points");
+animate.setAttribute("from", "0,0 200,0 200,200 0,200");
+animate.setAttribute("by", "0,0 100,0 100,100 0,100");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+poly.appendChild(animate);
+rootSVGElement.appendChild(poly);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(poly.animatedPoints.getItem(2).x, 200, epsilon);
+ assert_approx_equals(poly.animatedPoints.getItem(2).y, 200, epsilon);
+
+ assert_equals(poly.points.getItem(2).x, 200);
+ assert_equals(poly.points.getItem(2).y, 200);
+}
+
+function sample2() {
+ // Check half-time conditions
+ assert_approx_equals(poly.animatedPoints.getItem(2).x, 250, epsilon);
+ assert_approx_equals(poly.animatedPoints.getItem(2).y, 250, epsilon);
+
+ assert_equals(poly.points.getItem(2).x, 200);
+ assert_equals(poly.points.getItem(2).y, 200);
+}
+
+function sample3() {
+ // Check just before-end conditions
+ assert_approx_equals(poly.animatedPoints.getItem(2).x, 300, epsilon);
+ assert_approx_equals(poly.animatedPoints.getItem(2).y, 300, epsilon);
+
+ assert_equals(poly.points.getItem(2).x, 200);
+ assert_equals(poly.points.getItem(2).y, 200);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgrect-animation-1.html b/testing/web-platform/tests/svg/animations/svgrect-animation-1.html
new file mode 100644
index 0000000000..d13ccff418
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgrect-animation-1.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+<title>Test from-to SVGRect animation.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+rootSVGElement.setAttribute("id", "svg");
+rootSVGElement.setAttribute("viewBox", "0 0 100 100");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "viewBox");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0 0 100 100");
+animate.setAttribute("to", "50 50 50 50");
+rootSVGElement.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rootSVGElement.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.width, 100, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.height, 100, epsilon);
+
+ assert_equals(rootSVGElement.viewBox.baseVal.x, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.y, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.width, 100);
+ assert_equals(rootSVGElement.viewBox.baseVal.height, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.viewBox.animVal.x, 25, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.y, 25, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.width, 75, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.height, 75, epsilon);
+
+ assert_equals(rootSVGElement.viewBox.baseVal.x, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.y, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.width, 100);
+ assert_equals(rootSVGElement.viewBox.baseVal.height, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.viewBox.animVal.x, 50, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.y, 50, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.width, 50, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.height, 50, epsilon);
+
+ assert_equals(rootSVGElement.viewBox.baseVal.x, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.y, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.width, 100);
+ assert_equals(rootSVGElement.viewBox.baseVal.height, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgrect-animation-2.html b/testing/web-platform/tests/svg/animations/svgrect-animation-2.html
new file mode 100644
index 0000000000..86f5368a3a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgrect-animation-2.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+<title>Tests from-by SVGRect animation.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+rootSVGElement.setAttribute("id", "svg");
+rootSVGElement.setAttribute("viewBox", "0 0 100 100");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "viewBox");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0 0 100 100");
+animate.setAttribute("by", "50 50 50 50");
+rootSVGElement.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_approx_equals(rootSVGElement.viewBox.animVal.x, 0, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.y, 0, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.width, 100, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.height, 100, epsilon);
+
+ assert_equals(rootSVGElement.viewBox.baseVal.x, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.y, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.width, 100);
+ assert_equals(rootSVGElement.viewBox.baseVal.height, 100);
+}
+
+function sample2() {
+ assert_approx_equals(rootSVGElement.viewBox.animVal.x, 25, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.y, 25, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.width, 125, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.height, 125, epsilon);
+
+ assert_equals(rootSVGElement.viewBox.baseVal.x, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.y, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.width, 100);
+ assert_equals(rootSVGElement.viewBox.baseVal.height, 100);
+}
+
+function sample3() {
+ assert_approx_equals(rootSVGElement.viewBox.animVal.x, 50, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.y, 50, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.width, 150, epsilon);
+ assert_approx_equals(rootSVGElement.viewBox.animVal.height, 150, epsilon);
+
+ assert_equals(rootSVGElement.viewBox.baseVal.x, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.y, 0);
+ assert_equals(rootSVGElement.viewBox.baseVal.width, 100);
+ assert_equals(rootSVGElement.viewBox.baseVal.height, 100);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgstring-animation-1.html b/testing/web-platform/tests/svg/animations/svgstring-animation-1.html
new file mode 100644
index 0000000000..259dfbd27a
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgstring-animation-1.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+<title>Test animVal support for SVGAnimatedString animations.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var aElement = createSVGElement("a");
+aElement.setAttribute("target", "base");
+
+var textElement = createSVGElement("text");
+textElement.setAttribute("id", "text");
+textElement.setAttribute("y", "50");
+textElement.textContent = "Test";
+aElement.appendChild(textElement);
+rootSVGElement.appendChild(aElement);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "target");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("values", "a;b");
+aElement.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+ assert_equals(aElement.target.animVal, "base");
+ assert_equals(aElement.target.baseVal, "base");
+}
+
+function sample2() {
+ assert_equals(aElement.target.animVal, "a");
+ assert_equals(aElement.target.baseVal, "base");
+}
+
+function sample3() {
+ assert_equals(aElement.target.animVal, "b");
+ assert_equals(aElement.target.baseVal, "base");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.0, sample1],
+ ["animation", 0.001, sample2],
+ ["animation", 1.999, sample2],
+ ["animation", 2.001, sample3],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgstring-animation-fallback-to-discrete.html b/testing/web-platform/tests/svg/animations/svgstring-animation-fallback-to-discrete.html
new file mode 100644
index 0000000000..8cf6c34af0
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgstring-animation-fallback-to-discrete.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+<title>Tests fallback to calcMode='discrete' on animation of SVGString with 'values'.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "visibility");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "6s");
+animate.setAttribute("calcMode", "linear");
+animate.setAttribute("values", "visible ; hidden ; visible");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_equals(getComputedStyle(rect).visibility, 'visible');
+ assert_equals(rect.style.visibility, "");
+}
+
+function sample2() {
+ assert_equals(getComputedStyle(rect).visibility, 'hidden');
+ assert_equals(rect.style.visibility, "");
+}
+
+function sample3() {
+ assert_equals(getComputedStyle(rect).visibility, 'visible');
+ assert_equals(rect.style.visibility, "");
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 5.999, sample3],
+ ["animation", 6.001, sample1]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgtransform-animation-1.html b/testing/web-platform/tests/svg/animations/svgtransform-animation-1.html
new file mode 100644
index 0000000000..618ba9a31c
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgtransform-animation-1.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+<title>Test accumulate=sum animation on SVGAnimateTransform.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animateTransform");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "transform");
+animate.setAttribute("type", "scale");
+animate.setAttribute("from", "0,0");
+animate.setAttribute("to", "2,2");
+animate.setAttribute("type", "scale");
+animate.setAttribute("fill", "freeze");
+animate.setAttribute("accumulate", "sum");
+animate.setAttribute("repeatCount", "3");
+animate.setAttribute("additive", "sum");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 0, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 0, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample2() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 1, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 1, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample3() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 2, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 2, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample4() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 3, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 3, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample5() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 4, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 4, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample6() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 5, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 5, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample7() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_SCALE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.a, 6, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.d, 6, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.001, sample1],
+ ["animation", 2.0, sample2],
+ ["animation", 3.999, sample3],
+ ["animation", 4.001, sample3],
+ ["animation", 6.0, sample4],
+ ["animation", 7.999, sample5],
+ ["animation", 8.001, sample5],
+ ["animation", 10.0, sample6],
+ ["animation", 11.999, sample7],
+ ["animation", 12.001, sample7],
+ ["animation", 14.0, sample7],
+ ["animation", 60.0, sample7]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/svgtransform-animation-discrete.html b/testing/web-platform/tests/svg/animations/svgtransform-animation-discrete.html
new file mode 100644
index 0000000000..17b78a2787
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgtransform-animation-discrete.html
@@ -0,0 +1,74 @@
+<!doctype html>
+<html>
+<title>Test calcMode=discrete animation on SVGAnimateTransform.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("x", "0");
+rect.setAttribute("y", "0");
+rect.setAttribute("fill", "green");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animateTransform");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "transform");
+animate.setAttribute("type", "translate");
+animate.setAttribute("from", "100,100");
+animate.setAttribute("to", "0,0");
+animate.setAttribute("type", "translate");
+animate.setAttribute("calcMode", "discrete");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+ // Check initial/end conditions
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.e, 100, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.f, 100, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample2() {
+ assert_equals(rect.transform.animVal.numberOfItems, 1);
+ assert_equals(rect.transform.animVal.getItem(0).type, SVGTransform.SVG_TRANSFORM_TRANSLATE);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.e, 0, epsilon);
+ assert_approx_equals(rect.transform.animVal.getItem(0).matrix.f, 0, epsilon);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+function sample3() {
+ assert_equals(rect.transform.animVal.numberOfItems, 0);
+ assert_equals(rect.transform.baseVal.numberOfItems, 0);
+}
+
+smil_async_test((t) => {
+ const expectedValues = [
+ // [animationId, time, sampleCallback]
+ ["animation", 0.001, sample1],
+ ["animation", 1.999, sample1],
+ ["animation", 2.001, sample2],
+ ["animation", 3.999, sample2],
+ ["animation", 4.001, sample3]
+ ];
+
+ runAnimationTest(t, expectedValues);
+});
+
+</script>
diff --git a/testing/web-platform/tests/svg/animations/switching-animated-target-to-unknown-element.html b/testing/web-platform/tests/svg/animations/switching-animated-target-to-unknown-element.html
new file mode 100644
index 0000000000..fef86a723e
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/switching-animated-target-to-unknown-element.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Switching animated target to an unknown element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<svg height="0">
+ <path id="path">
+ <animateMotion/>
+ </path>
+ <unknown id="unknown"></unknown>
+</svg>
+<script>
+ async_test(t => {
+ let path = document.getElementById("path");
+ let anim = path.firstElementChild;
+ t.step_timeout(() => {
+ path.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'animateMotion'));
+ anim.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#unknown');
+ requestAnimationFrame(t.step_func(() => {
+ requestAnimationFrame(t.step_func_done());
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/syncbase-remove-add-while-running.html b/testing/web-platform/tests/svg/animations/syncbase-remove-add-while-running.html
new file mode 100644
index 0000000000..61b9604a7b
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/syncbase-remove-add-while-running.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Remove/Add syncbase while animation is running</title>
+<link rel="help" href="https://www.w3.org/TR/SMIL3/smil-timing.html#q26">
+<link rel="author" title="Edvard Thörnros" href="mailto:edvardt@opera.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<svg>
+ <animate id="anim" attributeName="visibility" to="visible" begin="10s" dur="2s"/>
+ <rect x="0" y="0" width="0" height="100" fill="#0F0">
+ <set attributeName="width" fill="freeze" to="100" begin="anim.begin"/>
+ </rect>
+</svg>
+
+<script>
+ async_test(function(t) {
+ window.onload = t.step_func(function() {
+ let svg = document.querySelector("svg");
+ let rect = document.querySelector("rect");
+
+ window.requestAnimationFrame(t.step_func(function() {
+ window.requestAnimationFrame(t.step_func(function() {
+ var anim1 = document.getElementById("anim");
+ anim1.parentNode.removeChild(anim1);
+
+ var anim2 = document.createElementNS("http://www.w3.org/2000/svg", "animate");
+ anim2.setAttribute("id", "anim");
+ anim2.setAttribute("attributeName", "visibility");
+ anim2.setAttribute("to", "visible");
+ anim2.setAttribute("begin", "0s");
+ anim2.setAttribute("dur", "2s");
+ svg.appendChild(anim2);
+
+ window.requestAnimationFrame(t.step_func(function() {
+ window.requestAnimationFrame(t.step_func_done(function() {
+ svg.pauseAnimations();
+ assert_equals(rect.width.animVal.value, 100, "Sync base triggered");
+ }));
+ }));
+ }));
+ }));
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/svg/animations/use-animate-display-none-symbol.html b/testing/web-platform/tests/svg/animations/use-animate-display-none-symbol.html
new file mode 100644
index 0000000000..6ae10ca873
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/use-animate-display-none-symbol.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Animate a symbol in a display: none subtree</title>
+<link rel="match" href="../struct/reftests/reference/green-100x100.html">
+<script src="/common/reftest-wait.js"></script>
+<svg>
+ <use href="#hidden"/>
+</svg>
+<svg style="display: none">
+ <symbol id="hidden">
+ <rect width="100" height="100" fill="red">
+ <animate attributeName="fill" values="red; green" calcMode="discrete"
+ dur="1ms" fill="freeze" onend="takeScreenshot()"/>
+ </rect>
+ </symbol>
+</svg>