1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/smil/test/test_smilTimeEvents.xhtml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,291 @@ 1.4 +<html xmlns="http://www.w3.org/1999/xhtml"> 1.5 +<!-- 1.6 +https://bugzilla.mozilla.org/show_bug.cgi?id=572270 1.7 +--> 1.8 +<head> 1.9 + <title>Test TimeEvents dispatching</title> 1.10 + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.11 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 1.12 +</head> 1.13 +<body> 1.14 +<a target="_blank" 1.15 + href="https://bugzilla.mozilla.org/show_bug.cgi?id=572270">Mozilla Bug 1.16 + 572270</a> 1.17 +<p id="display"></p> 1.18 +<div id="content" style="display: none"> 1.19 +<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px"> 1.20 + <g font-size="10px"> 1.21 + <circle cx="0" cy="0" r="15" fill="blue" id="circle" 1.22 + onbegin="parentHandler(evt)" onrepeat="parentHandler(evt)" 1.23 + onend="parentHandler(evt)"> 1.24 + <animate attributeName="cy" from="0" to="100" dur="60s" begin="2s" 1.25 + id="anim" repeatCount="2" 1.26 + onbegin="handleOnBegin(evt)" onrepeat="handleOnRepeat(evt)" 1.27 + onend="handleOnEnd(evt)"/> 1.28 + </circle> 1.29 + </g> 1.30 +</svg> 1.31 +</div> 1.32 +<pre id="test"> 1.33 +<script class="testbody" type="text/javascript"> 1.34 +<![CDATA[ 1.35 +/** Test SMIL TimeEvents dispatching **/ 1.36 + 1.37 +/* Global Variables */ 1.38 +const gTimeoutDur = 5000; // Time until we give up waiting for events in ms 1.39 +var gSvg = document.getElementById("svg"); 1.40 +var gAnim = document.getElementById('anim'); 1.41 +var gCircle = document.getElementById('circle'); 1.42 +var gExpectedEvents = new Array(); 1.43 +var gTimeoutID; 1.44 +var gTestStages = 1.45 + [ testPlaybackBegin, 1.46 + testPlaybackRepeat, 1.47 + testPlaybackEnd, 1.48 + testForwardsSeekToMid, 1.49 + testForwardsSeekToNextInterval, 1.50 + testForwardsSeekPastEnd, 1.51 + testBackwardsSeekToMid, 1.52 + testBackwardsSeekToStart, 1.53 + testCreateEvent, 1.54 + testRegistration 1.55 + ]; 1.56 + 1.57 +SimpleTest.waitForExplicitFinish(); 1.58 + 1.59 +function continueTest() 1.60 +{ 1.61 + if (gTestStages.length == 0) { 1.62 + SimpleTest.finish(); 1.63 + return; 1.64 + } 1.65 + gTestStages.shift()(); 1.66 +} 1.67 + 1.68 +function testPlaybackBegin() 1.69 +{ 1.70 + // Test events are dispatched through normal playback 1.71 + gSvg.pauseAnimations(); 1.72 + gSvg.setCurrentTime(1.99); 1.73 + gExpectedEvents.push("beginEvent", "beginEvent"); // Two registered handlers 1.74 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.75 + gSvg.unpauseAnimations(); 1.76 +} 1.77 + 1.78 +function testPlaybackRepeat() 1.79 +{ 1.80 + gSvg.pauseAnimations(); 1.81 + gSvg.setCurrentTime(61.99); 1.82 + gExpectedEvents.push(["repeatEvent", 1], ["repeatEvent", 1]); 1.83 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.84 + gSvg.unpauseAnimations(); 1.85 +} 1.86 + 1.87 +function testPlaybackEnd() 1.88 +{ 1.89 + gSvg.pauseAnimations(); 1.90 + gSvg.setCurrentTime(121.99); 1.91 + gExpectedEvents.push("endEvent", "endEvent"); 1.92 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.93 + gSvg.unpauseAnimations(); 1.94 +} 1.95 + 1.96 +function testForwardsSeekToMid() 1.97 +{ 1.98 + gSvg.pauseAnimations(); 1.99 + // Set animation parameters to something that repeats a lot 1.100 + gSvg.setCurrentTime(0); 1.101 + gAnim.setAttribute('begin', '2s; 102s'); 1.102 + gAnim.setAttribute('dur', '15s'); 1.103 + gAnim.setAttribute('repeatCount', '6'); 1.104 + gSvg.setCurrentTime(46.99); 1.105 + gExpectedEvents.push("beginEvent", "beginEvent", 1.106 + ["repeatEvent", 3], ["repeatEvent", 3]); 1.107 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.108 + gSvg.unpauseAnimations(); 1.109 +} 1.110 + 1.111 +function testForwardsSeekToNextInterval() 1.112 +{ 1.113 + // Skip to next interval -- we shouldn't get any additional begin or end 1.114 + // events in between 1.115 + gSvg.pauseAnimations(); 1.116 + gSvg.setCurrentTime(131.99); 1.117 + gExpectedEvents.push(["repeatEvent", 2], ["repeatEvent", 2]); 1.118 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.119 + gSvg.unpauseAnimations(); 1.120 +} 1.121 + 1.122 +function testForwardsSeekPastEnd() 1.123 +{ 1.124 + gSvg.pauseAnimations(); 1.125 + gSvg.setCurrentTime(200); 1.126 + gExpectedEvents.push("endEvent", "endEvent"); 1.127 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.128 + gSvg.unpauseAnimations(); 1.129 +} 1.130 + 1.131 +function testBackwardsSeekToMid() 1.132 +{ 1.133 + gSvg.pauseAnimations(); 1.134 + gSvg.setCurrentTime(31.99); 1.135 + gExpectedEvents.push("beginEvent", "beginEvent", 1.136 + ["repeatEvent", 2], ["repeatEvent", 2]); 1.137 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.138 + gSvg.unpauseAnimations(); 1.139 +} 1.140 + 1.141 +function testBackwardsSeekToStart() 1.142 +{ 1.143 + gSvg.pauseAnimations(); 1.144 + gExpectedEvents.push("endEvent", "endEvent"); 1.145 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.146 + gSvg.setCurrentTime(0); 1.147 +} 1.148 + 1.149 +function testCreateEvent() 1.150 +{ 1.151 + var evt; 1.152 + try { 1.153 + evt = document.createEvent("TimeEvents"); 1.154 + } catch (e) { 1.155 + ok(false, "Failed to create TimeEvent via script: " + e); 1.156 + return; 1.157 + } 1.158 + evt.initTimeEvent("repeatEvent", null, 3); 1.159 + is(evt.type, "repeatEvent", "Unexpected type for user-generated event"); 1.160 + is(evt.detail, 3, "Unexpected detail for user-generated event"); 1.161 + is(evt.target, null, "Unexpected event target"); 1.162 + is(evt.currentTarget, null, "Unexpected event current target"); 1.163 + is(evt.eventPhase, evt.NONE); 1.164 + is(evt.bubbles, false, "Event should not bubble"); 1.165 + is(evt.cancelable, false, "Event should not be cancelable"); 1.166 + is(evt.view, null, "Event view should be null"); 1.167 + 1.168 + // Prior to dispatch we should be able to change the event type 1.169 + evt.initTimeEvent("beginEvent", document.defaultView, 0); 1.170 + is(evt.type, "beginEvent", "Failed to update event type before dispatch"); 1.171 + is(evt.detail, 0, "Failed to update event detail before dispatch"); 1.172 + is(evt.view, document.defaultView, "Event view should be set"); 1.173 + 1.174 + // But not directly as it's readonly 1.175 + try { 1.176 + evt.type = "endEvent"; 1.177 + } catch(e) { } 1.178 + is(evt.type, "beginEvent", "Event type should be readonly"); 1.179 + 1.180 + // Likewise the detail field should be readonly 1.181 + try { 1.182 + evt.detail = "8"; 1.183 + } catch(e) { } 1.184 + is(evt.detail, 0, "Event detail should be readonly"); 1.185 + 1.186 + // Dispatch 1.187 + gExpectedEvents.push("beginEvent", "beginEvent"); 1.188 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.189 + gAnim.dispatchEvent(evt); 1.190 +} 1.191 + 1.192 +function testRegistration() 1.193 +{ 1.194 + gSvg.pauseAnimations(); 1.195 + // Reset animation to something simple 1.196 + gSvg.setCurrentTime(0); 1.197 + gAnim.setAttribute('begin', '2s'); 1.198 + gAnim.setAttribute('dur', '50s'); 1.199 + 1.200 + // Remove attribute handler 1.201 + gAnim.removeAttribute('onbegin'); 1.202 + 1.203 + // Add bogus handlers 1.204 + gAnim.setAttribute('onbeginElement', 'handleOnBegin(evt)'); 1.205 + gAnim.addEventListener("begin", handleOnBegin, false); 1.206 + gAnim.addEventListener("onbegin", handleOnBegin, false); 1.207 + 1.208 + // We should now have just one legitimate listener: the one registered to 1.209 + // handle 'beginElement' 1.210 + gSvg.setCurrentTime(1.99); 1.211 + gExpectedEvents.push("beginEvent"); 1.212 + gTimeoutID = setTimeout(timeoutFail, gTimeoutDur); 1.213 + gSvg.unpauseAnimations(); 1.214 +} 1.215 + 1.216 +function handleOnBegin(evt) 1.217 +{ 1.218 + is(evt.type, "beginEvent", "Expected begin event but got " + evt.type); 1.219 + checkExpectedEvent(evt); 1.220 +} 1.221 + 1.222 +function handleOnRepeat(evt) 1.223 +{ 1.224 + is(evt.type, "repeatEvent", "Expected repeat event but got " + evt.type); 1.225 + checkExpectedEvent(evt); 1.226 +} 1.227 + 1.228 +function handleOnEnd(evt) 1.229 +{ 1.230 + is(evt.type, "endEvent", "Expected end event but got " + evt.type); 1.231 + checkExpectedEvent(evt); 1.232 +} 1.233 + 1.234 +function sanityCheckEvent(evt) 1.235 +{ 1.236 + is(evt.target, gAnim, "Unexpected event target"); 1.237 + is(evt.currentTarget, gAnim, "Unexpected event current target"); 1.238 + is(evt.eventPhase, evt.AT_TARGET); 1.239 + is(evt.bubbles, false, "Event should not bubble"); 1.240 + is(evt.cancelable, false, "Event should not be cancelable"); 1.241 + // Currently we set event timestamps to 0 which DOM 2 allows. This isn't 1.242 + // correct since SMIL uses this field to avoid synchronisation slew but first 1.243 + // we need to fix bug 323039 and bug 77992 which involve storing timestamps as 1.244 + // 64-bit integers and deciding whether those timestamps should be related to 1.245 + // the epoch or system start. 1.246 + is(evt.timeStamp, 0, "Event timeStamp should be 0"); 1.247 + ok(evt.view !== null, "Event view not set"); 1.248 +} 1.249 + 1.250 +function checkExpectedEvent(evt) 1.251 +{ 1.252 + sanityCheckEvent(evt); 1.253 + ok(gExpectedEvents.length > 0, "Unexpected event: " + evt.type); 1.254 + if (gExpectedEvents.length == 0) return; 1.255 + 1.256 + var expected = gExpectedEvents.shift(); 1.257 + if (typeof expected == 'string') { 1.258 + is(evt.type, expected, "Unexpected event type"); 1.259 + is(evt.detail, 0, "Unexpected event detail (repeat iteration)"); 1.260 + } else { 1.261 + is(evt.type, expected[0], "Unexpected event type"); 1.262 + is(evt.detail, expected[1], "Unexpected event detail (repeat iteration)"); 1.263 + } 1.264 + if (gExpectedEvents.length == 0) { 1.265 + clearTimeout(gTimeoutID); 1.266 + continueTest(); 1.267 + } 1.268 +} 1.269 + 1.270 +function timeoutFail() 1.271 +{ 1.272 + ok(false, "Timed out waiting for events: " + gExpectedEvents.join(', ')); 1.273 + SimpleTest.finish(); // No point continuing 1.274 +} 1.275 + 1.276 +function parentHandler(evt) 1.277 +{ 1.278 + ok(false, "Handler on parent got called but event shouldn't bubble."); 1.279 +} 1.280 + 1.281 +window.addEventListener("load", continueTest, false); 1.282 + 1.283 +// Register event handlers *in addition* to the handlers already added via the 1.284 +// "onbegin", "onend", "onrepeat" attributes on the <animate> and <circle> 1.285 +// elements. This is to test that both types of registration work. 1.286 +gAnim.addEventListener("beginEvent", handleOnBegin, false); 1.287 +gAnim.addEventListener("repeatEvent", handleOnRepeat, false); 1.288 +gAnim.addEventListener("endEvent", handleOnEnd, false); 1.289 +gCircle.addEventListener("beginEvent", parentHandler, false); 1.290 +]]> 1.291 +</script> 1.292 +</pre> 1.293 +</body> 1.294 +</html>