gecko/content/smil/test/test_smilTimeEvents.xhtml

293 lines
8.8 KiB
HTML

<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="/MochiKit/packed.js"></script>
<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 = 5000; // 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();
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.AT_TARGET);
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");
// Currently we set event timestamps to 0 which DOM 2 allows. This isn't
// correct since SMIL uses this field to avoid synchronisation slew but first
// we need to fix bug 323039 and bug 77992 which involve storing timestamps as
// 64-bit integers and deciding whether those timestamps should be related to
// the epoch or system start.
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);
]]>
</script>
</pre>
</body>
</html>