summaryrefslogtreecommitdiffstats
path: root/dom/smil/test/test_smilTimeEvents.xhtml
diff options
context:
space:
mode:
Diffstat (limited to 'dom/smil/test/test_smilTimeEvents.xhtml')
-rw-r--r--dom/smil/test/test_smilTimeEvents.xhtml337
1 files changed, 337 insertions, 0 deletions
diff --git a/dom/smil/test/test_smilTimeEvents.xhtml b/dom/smil/test/test_smilTimeEvents.xhtml
new file mode 100644
index 000000000..bf6924ddb
--- /dev/null
+++ b/dom/smil/test/test_smilTimeEvents.xhtml
@@ -0,0 +1,337 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=572270
+-->
+<head>
+ <title>Test TimeEvents dispatching</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=572270">Mozilla Bug
+ 572270</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">
+ <g font-size="10px">
+ <circle cx="0" cy="0" r="15" fill="blue" id="circle"
+ onbegin="parentHandler(evt)" onrepeat="parentHandler(evt)"
+ onend="parentHandler(evt)">
+ <animate attributeName="cy" from="0" to="100" dur="60s" begin="2s"
+ id="anim" repeatCount="2"
+ onbegin="handleOnBegin(evt)" onrepeat="handleOnRepeat(evt)"
+ onend="handleOnEnd(evt)"/>
+ </circle>
+ </g>
+</svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+/** Test SMIL TimeEvents dispatching **/
+
+/* Global Variables */
+const gTimeoutDur = 60000; // Time until we give up waiting for events in ms
+var gSvg = document.getElementById("svg");
+var gAnim = document.getElementById('anim');
+var gCircle = document.getElementById('circle');
+var gExpectedEvents = new Array();
+var gTimeoutID;
+var gTestStages =
+ [ testPlaybackBegin,
+ testPlaybackRepeat,
+ testPlaybackEnd,
+ testForwardsSeekToMid,
+ testForwardsSeekToNextInterval,
+ testForwardsSeekPastEnd,
+ testBackwardsSeekToMid,
+ testBackwardsSeekToStart,
+ testCreateEvent,
+ testRegistration
+ ];
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+function continueTest()
+{
+ if (gTestStages.length == 0) {
+ SimpleTest.finish();
+ return;
+ }
+ gTestStages.shift()();
+}
+
+function testPlaybackBegin()
+{
+ // Test events are dispatched through normal playback
+ gSvg.pauseAnimations();
+ gSvg.setCurrentTime(1.99);
+ gExpectedEvents.push("beginEvent", "beginEvent"); // Two registered handlers
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testPlaybackRepeat()
+{
+ gSvg.pauseAnimations();
+ gSvg.setCurrentTime(61.99);
+ gExpectedEvents.push(["repeatEvent", 1], ["repeatEvent", 1]);
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testPlaybackEnd()
+{
+ gSvg.pauseAnimations();
+ gSvg.setCurrentTime(121.99);
+ gExpectedEvents.push("endEvent", "endEvent");
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testForwardsSeekToMid()
+{
+ gSvg.pauseAnimations();
+ // Set animation parameters to something that repeats a lot
+ gSvg.setCurrentTime(0);
+ gAnim.setAttribute('begin', '2s; 102s');
+ gAnim.setAttribute('dur', '15s');
+ gAnim.setAttribute('repeatCount', '6');
+ gSvg.setCurrentTime(46.99);
+ gExpectedEvents.push("beginEvent", "beginEvent",
+ ["repeatEvent", 3], ["repeatEvent", 3]);
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testForwardsSeekToNextInterval()
+{
+ // Skip to next interval -- we shouldn't get any additional begin or end
+ // events in between
+ gSvg.pauseAnimations();
+ gSvg.setCurrentTime(131.99);
+ gExpectedEvents.push(["repeatEvent", 2], ["repeatEvent", 2]);
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testForwardsSeekPastEnd()
+{
+ gSvg.pauseAnimations();
+ gSvg.setCurrentTime(200);
+ gExpectedEvents.push("endEvent", "endEvent");
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testBackwardsSeekToMid()
+{
+ gSvg.pauseAnimations();
+ gSvg.setCurrentTime(31.99);
+ gExpectedEvents.push("beginEvent", "beginEvent",
+ ["repeatEvent", 2], ["repeatEvent", 2]);
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function testBackwardsSeekToStart()
+{
+ gSvg.pauseAnimations();
+ gExpectedEvents.push("endEvent", "endEvent");
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.setCurrentTime(0);
+}
+
+function testCreateEvent()
+{
+ var evt;
+ try {
+ evt = document.createEvent("TimeEvents");
+ } catch (e) {
+ ok(false, "Failed to create TimeEvent via script: " + e);
+ return;
+ }
+ evt.initTimeEvent("repeatEvent", null, 3);
+ is(evt.type, "repeatEvent", "Unexpected type for user-generated event");
+ is(evt.detail, 3, "Unexpected detail for user-generated event");
+ is(evt.target, null, "Unexpected event target");
+ is(evt.currentTarget, null, "Unexpected event current target");
+ is(evt.eventPhase, evt.NONE);
+ is(evt.bubbles, false, "Event should not bubble");
+ is(evt.cancelable, false, "Event should not be cancelable");
+ is(evt.view, null, "Event view should be null");
+
+ // Prior to dispatch we should be able to change the event type
+ evt.initTimeEvent("beginEvent", document.defaultView, 0);
+ is(evt.type, "beginEvent", "Failed to update event type before dispatch");
+ is(evt.detail, 0, "Failed to update event detail before dispatch");
+ is(evt.view, document.defaultView, "Event view should be set");
+
+ // But not directly as it's readonly
+ try {
+ evt.type = "endEvent";
+ } catch(e) { }
+ is(evt.type, "beginEvent", "Event type should be readonly");
+
+ // Likewise the detail field should be readonly
+ try {
+ evt.detail = "8";
+ } catch(e) { }
+ is(evt.detail, 0, "Event detail should be readonly");
+
+ // Dispatch
+ gExpectedEvents.push("beginEvent", "beginEvent");
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gAnim.dispatchEvent(evt);
+}
+
+function testRegistration()
+{
+ gSvg.pauseAnimations();
+ // Reset animation to something simple
+ gSvg.setCurrentTime(0);
+ gAnim.setAttribute('begin', '2s');
+ gAnim.setAttribute('dur', '50s');
+
+ // Remove attribute handler
+ gAnim.removeAttribute('onbegin');
+
+ // Add bogus handlers
+ gAnim.setAttribute('onbeginElement', 'handleOnBegin(evt)');
+ gAnim.addEventListener("begin", handleOnBegin, false);
+ gAnim.addEventListener("onbegin", handleOnBegin, false);
+
+ // We should now have just one legitimate listener: the one registered to
+ // handle 'beginElement'
+ gSvg.setCurrentTime(1.99);
+ gExpectedEvents.push("beginEvent");
+ gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
+ gSvg.unpauseAnimations();
+}
+
+function handleOnBegin(evt)
+{
+ is(evt.type, "beginEvent", "Expected begin event but got " + evt.type);
+ checkExpectedEvent(evt);
+}
+
+function handleOnRepeat(evt)
+{
+ is(evt.type, "repeatEvent", "Expected repeat event but got " + evt.type);
+ checkExpectedEvent(evt);
+}
+
+function handleOnEnd(evt)
+{
+ is(evt.type, "endEvent", "Expected end event but got " + evt.type);
+ checkExpectedEvent(evt);
+}
+
+function sanityCheckEvent(evt)
+{
+ is(evt.target, gAnim, "Unexpected event target");
+ is(evt.currentTarget, gAnim, "Unexpected event current target");
+ is(evt.eventPhase, evt.AT_TARGET);
+ is(evt.bubbles, false, "Event should not bubble");
+ is(evt.cancelable, false, "Event should not be cancelable");
+ if (SpecialPowers.getBoolPref("dom.event.highrestimestamp.enabled")) {
+ var now = window.performance.now();
+ ok(evt.timeStamp > 0 && evt.timeStamp < now,
+ "Event timeStamp (" + evt.timeStamp + ") should be > 0 but " +
+ "before the current time (" + now + ")");
+ } else {
+ is(evt.timeStamp, 0, "Event timeStamp should be 0");
+ }
+ ok(evt.view !== null, "Event view not set");
+}
+
+function checkExpectedEvent(evt)
+{
+ sanityCheckEvent(evt);
+ ok(gExpectedEvents.length > 0, "Unexpected event: " + evt.type);
+ if (gExpectedEvents.length == 0) return;
+
+ var expected = gExpectedEvents.shift();
+ if (typeof expected == 'string') {
+ is(evt.type, expected, "Unexpected event type");
+ is(evt.detail, 0, "Unexpected event detail (repeat iteration)");
+ } else {
+ is(evt.type, expected[0], "Unexpected event type");
+ is(evt.detail, expected[1], "Unexpected event detail (repeat iteration)");
+ }
+ if (gExpectedEvents.length == 0) {
+ clearTimeout(gTimeoutID);
+ continueTest();
+ }
+}
+
+function timeoutFail()
+{
+ ok(false, "Timed out waiting for events: " + gExpectedEvents.join(', '));
+ SimpleTest.finish(); // No point continuing
+}
+
+function parentHandler(evt)
+{
+ ok(false, "Handler on parent got called but event shouldn't bubble.");
+}
+
+window.addEventListener("load", continueTest, false);
+
+// Register event handlers *in addition* to the handlers already added via the
+// "onbegin", "onend", "onrepeat" attributes on the <animate> and <circle>
+// elements. This is to test that both types of registration work.
+gAnim.addEventListener("beginEvent", handleOnBegin, false);
+gAnim.addEventListener("repeatEvent", handleOnRepeat, false);
+gAnim.addEventListener("endEvent", handleOnEnd, false);
+gCircle.addEventListener("beginEvent", parentHandler, false);
+
+var expectedEvents =
+ ["begin", "beginEvent", "repeat", "repeatEvent", "end", "endEvent", "SVGZoom", "zoom"];
+
+for (var i = 0; i < expectedEvents.length; ++i) {
+ is((new Event(expectedEvents[i])).type, expectedEvents[i], "Unexpected event type!");
+}
+
+var timeEvents = ["begin", "repeat", "end"];
+var expectedEvents = ["begin", "beginEvent", "repeat", "repeatEvent", "end", "endEvent"];
+var d = document.createElement("div");
+for (var i = 0; i < timeEvents.length; ++i) {
+ d.addEventListener(timeEvents[i], function(e) {
+ is(e.type, expectedEvents[0], "Got the expected event type.");
+ expectedEvents.shift();
+ });
+
+ // Without "Event" suffix.
+ var e = document.createEvent("timeevent");
+ e.initEvent(timeEvents[i], true, true);
+ d.dispatchEvent(e);
+
+ // With "Event" suffix.
+ e = document.createEvent("timeevent");
+ e.initEvent(timeEvents[i] + "Event", true, true);
+ d.dispatchEvent(e);
+}
+is(expectedEvents.length, 0, "Got all the expected events.");
+
+expectedEvents = ["zoom", "SVGZoom"];
+d.addEventListener("zoom", function(e) {
+ is(e.type, expectedEvents[0]);
+ expectedEvents.shift();
+});
+
+var zoomEvent = document.createEvent("svgzoomevent");
+zoomEvent.initEvent("zoom", true, true);
+d.dispatchEvent(zoomEvent);
+zoomEvent = document.createEvent("svgzoomevent");
+zoomEvent.initEvent("SVGZoom", true, true);
+d.dispatchEvent(zoomEvent);
+is(expectedEvents.length, 0, "Got all the expected events.");
+
+]]>
+</script>
+</pre>
+</body>
+</html>