Bug 1573150 [wpt PR 18387] - Translate svg/animation tests to WPT (Commit 4), a=testonly
authorEdvard Thörnros <edvardt@opera.com>
Wed, 14 Aug 2019 10:56:19 +0000
changeset 488110 1e63e0974c28c5978d9953285edda9a2cb5e1f7c
parent 488109 3eef760ffbf7f87d44ef3b65ce610a3f135fbaed
child 488111 d66154dc0b98284caa2fa5daff853eafc3066bad
push id36435
push usercbrindusan@mozilla.com
push dateThu, 15 Aug 2019 09:46:49 +0000
treeherdermozilla-central@0db07ff50ab5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1573150, 18387, 985335, 1746004, 685981
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1573150 [wpt PR 18387] - Translate svg/animation tests to WPT (Commit 4), a=testonly Automatic update from web-platform-tests Translate svg/animation tests to WPT (Commit 4) This is the forth commit in the series of updating all the old svg animation tests. The usage of testharness has replaced the older SVGAnimationTest.js for all where it's suitable. No functionality should have changed and the tests should cover almost the same. In all of the animations where there is a sampling at T=0, where it was assumed that no animations had started. Which didn't work flawlessly when moved to the new system, it has thus been removed. Bug: 985335 Change-Id: I1ac61d1fda2cc3de76e1a23cda06e76e8819d307 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1746004 Auto-Submit: Edvard Thörnros <edvardt@opera.com> Commit-Queue: Stephen Chenney <schenney@chromium.org> Reviewed-by: Stephen Chenney <schenney@chromium.org> Cr-Commit-Position: refs/heads/master@{#685981} -- wpt-commits: 732186f624aac2ccfe1c82cc304fd91ee10f2418 wpt-pr: 18387
testing/web-platform/tests/svg/animations/animVal-basics.html
testing/web-platform/tests/svg/animations/animate-marker-orient-from-angle-to-auto.html
testing/web-platform/tests/svg/animations/animate-marker-orient-from-auto-to-auto-start-reverse.html
testing/web-platform/tests/svg/animations/animate-marker-orient-to-angle.html
testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete-keyTimes.html
testing/web-platform/tests/svg/animations/animate-number-calcMode-discrete.html
testing/web-platform/tests/svg/animations/animate-path-animation-Cc-Ss.html
testing/web-platform/tests/svg/animations/animate-path-animation-Ll-Vv-Hh.html
testing/web-platform/tests/svg/animations/animate-path-animation-Mm-Aa-Z.html
testing/web-platform/tests/svg/animations/animate-path-animation-Qq-Tt.html
testing/web-platform/tests/svg/animations/animate-path-animation-cC-sS-inverse.html
testing/web-platform/tests/svg/animations/animate-path-animation-lL-vV-hH-inverse.html
testing/web-platform/tests/svg/animations/animate-path-animation-mM-aA-Z-inverse.html
testing/web-platform/tests/svg/animations/animate-path-animation-qQ-tT-inverse.html
testing/web-platform/tests/svg/animations/animate-path-to-animation.html
testing/web-platform/tests/svg/animations/animateMotion-fill-freeze.html
testing/web-platform/tests/svg/animations/animateMotion-fill-remove.html
testing/web-platform/tests/svg/animations/animateMotion-multiple.html
testing/web-platform/tests/svg/animations/animateMotion-still.html
testing/web-platform/tests/svg/animations/animateTransform-pattern-transform.html
testing/web-platform/tests/svg/animations/attributeTypes.html
testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-freeze.html
testing/web-platform/tests/svg/animations/change-css-property-while-animating-fill-remove.html
testing/web-platform/tests/svg/animations/change-target-while-animating-SVG-property.html
testing/web-platform/tests/svg/animations/cyclic-syncbase.html
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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_UNKNOWN);
+    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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Cc-Ss.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('d'), "M -20 -20 C 20 -20 20 -20 20 20 S 20 40 -20 20 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M -20 -20 C 10 -10 10 -10 20 20 S 30 35 -10 10 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "M -20 -20 c 10 30 10 30 40 40 s 30 5 -10 -30 Z");
+}
+
+function sample4() {
+    assert_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Ll-Vv-Hh.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('d'), "M -30 -30 L 30 0 V 30 H 0 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M -15 -15 L 15 0 V 15 H 0 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "M 15 15 l -30 -15 v -15 h 15 Z");
+}
+
+function sample4() {
+    assert_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Mm-Aa-Z.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('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");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "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 sample3() {
+    assert_equals(path.getAttribute('d'), "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_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-Qq-Tt.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('d'), "M -30 -30 Q 30 -30 30 0 T -30 30 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M -30 -30 Q 22.5 -30 22.5 0 T -30 30 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "M -30 -30 q 37.5 0 37.5 30 t -37.5 30 Z");
+}
+
+function sample4() {
+    assert_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-cC-sS-inverse.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('d'), "M -20 -20 c 0 40 0 40 40 40 s 40 0 0 -40 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M -20 -20 c 10 30 10 30 40 40 s 30 5 -10 -30 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "M -20 -20 C 10 -10 10 -10 20 20 S 30 35 -10 10 Z");
+}
+
+function sample4() {
+    assert_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-lL-vV-hH-inverse.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('d'), "M 30 30 l -60 -30 v -30 h 30 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M 15 15 l -30 -15 v -15 h 15 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "M -15 -15 L 15 0 V 15 H 0 Z");
+}
+
+function sample4() {
+    assert_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-mM-aA-Z-inverse.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('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");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "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 sample3() {
+    assert_equals(path.getAttribute('d'), "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_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-animation-qQ-tT-inverse.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test path animation where coordinate modes of start and end differ. You should see 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 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("onclick", "executeTest()");
+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_equals(path.getAttribute('d'), "M -30 -30 q 30 0 30 30 t -30 30 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M -30 -30 q 37.5 0 37.5 30 t -37.5 30 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "M -30 -30 Q 22.5 -30 22.5 0 T -30 30 Z");
+}
+
+function sample4() {
+    assert_equals(path.getAttribute('d'), "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);
+});
+
+window.clickX = 40;
+window.clickY = 70;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/animate-path-to-animation.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test calcMode spline with to animation. You should see a green 100x100 path 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 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("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_equals(path.getAttribute('d'), "M 40 40 L 60 40 L 60 60 L 40 60 Z");
+}
+
+function sample2() {
+    assert_equals(path.getAttribute('d'), "M 20 20 L 80 20 L 80 80 L 20 80 Z");
+}
+
+function sample3() {
+    assert_equals(path.getAttribute('d'), "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>
\ No newline at end of file
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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
new file mode 100644
--- /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