<html xmlns="http://www.w3.org/1999/xhtml"> <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=506856 --> <head> <title>Test for read-only times of SVG animated lengths</title> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=506856">Mozilla Bug 506856</a> <p id="display"></p> <div id="content" style="display: none"> <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px" viewBox="0 0 100 100" onload="this.pauseAnimations()"> <!-- Note: Need a viewBox on the SVG element, or else our percent-length basis will be '0' (based off of the viewport width, which is 0 in this case since we're in a display:none iframe. We use viewport width because the lack of a viewbox forces us into the not-mViewBox::IsValid() case of SVGSVGElement::GetLength). And we don't want a percent-length basis of 0, because then when we call convertToSpecifiedUnits to convert out of percent units, we divide by 0 and get unexpected results. --> <circle cx="-100" cy="-100" r="15" fill="blue" id="circle"> <animate attributeName="cx" from="0" to="100" dur="4s" begin="1s; 10s" fill="freeze" id="animate"/> <animate attributeName="cy" from="-100" to="-100" dur="4s" begin="1s; 10s" fill="remove"/> </circle> </svg> </div> <pre id="test"> <script class="testbody" type="text/javascript"> <![CDATA[ /** Test read-only times of animated lengths **/ /* Global Variables */ const svgns="http://www.w3.org/2000/svg"; var svg = document.getElementById("svg"); var circle = document.getElementById('circle'); SimpleTest.waitForExplicitFinish(); function main() { ok(svg.animationsPaused(), "should be paused by <svg> load handler"); is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler"); // Sanity check: check initial values is(circle.cx.baseVal.value, -100); is(circle.cx.animVal.value, -100); is(circle.cy.baseVal.value, -100); is(circle.cy.animVal.value, -100); // (1): Check before animation that animVal's are readonly ok(checkReadOnly(circle.cx), "(1) animVal cx is editable when not animated"); ok(checkReadOnly(circle.cy), "(1) animVal cy is editable when not animated"); // Skip to mid-way through the animation svg.setCurrentTime(4); // (2): Check that whilst animations are active the animVal's are readonly ok(checkReadOnly(circle.cx), "(2) animVal cx is editable when animated"); ok(checkReadOnly(circle.cy), "(2) animVal cy is editable when animated"); // Skip to past end svg.setCurrentTime(6); // (3): Check that frozen animations are readonly and have different values ok(checkReadOnly(circle.cx), "(3) animVal cx is editable when frozen"); checkDiffValue(circle.cx); // (4): Check that finished animations are readonly and have same values ok(checkReadOnly(circle.cy), "(4) animVal cy is editable when inactive"); checkSameValue(circle.cy); SimpleTest.finish(); } function checkReadOnly(animLength) { var exceptionCaught = false; var oldAnimValue = animLength.animVal.value; // Try changing value try { animLength.animVal.value = (animLength.animVal.value == 77) ? 88 : 77; } catch (e) { if (e.name == "NoModificationAllowedError" && e.code == DOMException.NO_MODIFICATION_ALLOWED_ERR) { exceptionCaught = true; } else { ok(false, "Got unexpected exception " + e); return false; } } is(animLength.animVal.value, oldAnimValue, "No exception thrown, but animVal was changed."); if (animLength.animVal.value != oldAnimValue) return false; // valueInSpecifiedUnits try { exceptionCaught = false; animLength.animVal.valueInSpecifiedUnits = -100; } catch (e) { exceptionCaught = true; } ok(exceptionCaught, "animVal.valueInSpecifiedUnits failed to throw."); if (!exceptionCaught) return false; // valueAsString try { exceptionCaught = false; animLength.animVal.valueAsString = "-100px"; } catch (e) { exceptionCaught = true; } ok(exceptionCaught, "animVal.valueAsString failed to throw."); if (!exceptionCaught) return false; // newValueSpecifiedUnits try { exceptionCaught = false; animLength.animVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PX,-100); } catch (e) { exceptionCaught = true; } ok(exceptionCaught, "animVal.newValueSpecifiedUnits failed to throw."); if (!exceptionCaught) return false; // convertToSpecifiedUnits try { exceptionCaught = false; animLength.animVal.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_NUMBER); } catch (e) { exceptionCaught = true; } ok(exceptionCaught, "animVal.convertToSpecifiedUnits failed to throw."); return exceptionCaught; } function checkSameValue(animLength) { // value animLength.baseVal.value = 1; is(animLength.animVal.value, 1, "un-animated animVal.value not changed after setting baseValue.value"); // valueInSpecifiedUnits animLength.baseVal.valueInSpecifiedUnits = 2; is(animLength.animVal.value, 2, "un-animated animVal.value not changed after setting " + "baseValue.valueInSpecifiedUnits"); // valueAsString animLength.baseVal.valueAsString = "3"; is(animLength.animVal.value, 3, "un-animated animVal.value not changed after setting " + "baseValue.valueAsString"); // newValueSpecifiedUnits animLength.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_CM, 4); is(animLength.animVal.valueInSpecifiedUnits, 4, "un-animated animVal.value not changed after setting " + "baseValue.newValueSpecifiedUnits"); // convertToSpecifiedUnits animLength.baseVal.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_MM); is(animLength.animVal.valueInSpecifiedUnits, 40, "un-animated animVal.value not changed after calling " + "baseValue.convertToSpecifiedUnits"); } function checkDiffValue(animLength) { // We assume here that the animation is not additive and hence changing the // baseValue will not be reflected in the animValue var origValue = animLength.animVal.value; // value animLength.baseVal.value = 1; is(animLength.animVal.value, origValue, "animated animVal.value changed after setting baseValue.value"); // valueInSpecifiedUnits animLength.baseVal.valueInSpecifiedUnits = 2; is(animLength.animVal.value, origValue, "animated animVal.value changed after setting " + "baseValue.valueInSpecifiedUnits"); // valueAsString animLength.baseVal.valueAsString = "3"; is(animLength.animVal.value, origValue, "animated animVal.value changed after setting baseValue.valueAsString"); // newValueSpecifiedUnits // (Note: we'd like to convert to MM here and CM in the next step for // consistency with the other tests. However, internally that will cause the // animVal to be converted to MM and back again which, given certain dpi // values such as we get in Linux, this may lead to rounding errors so that // 100 becomes 99.99999237060547. So instead we convert to something // independent of dpi) animLength.baseVal.newValueSpecifiedUnits( SVGLength.SVG_LENGTHTYPE_PERCENTAGE, 40); is(animLength.animVal.value, origValue, "animated animVal.value changed after setting " + "baseValue.newValueSpecifiedUnits"); // convertToSpecifiedUnits animLength.baseVal.convertToSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PX); is(animLength.animVal.value, origValue, "animated animVal.value changed after calling " + "baseValue.convertToSpecifiedUnits"); } window.addEventListener("load", main, false); ]]> </script> </pre> </body> </html>