diff options
Diffstat (limited to 'dom/smil/test/test_smilAccessKey.xhtml')
-rw-r--r-- | dom/smil/test/test_smilAccessKey.xhtml | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/dom/smil/test/test_smilAccessKey.xhtml b/dom/smil/test/test_smilAccessKey.xhtml new file mode 100644 index 000000000..ef7e1b73d --- /dev/null +++ b/dom/smil/test/test_smilAccessKey.xhtml @@ -0,0 +1,362 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Test for SMIL accessKey support</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=587910">Mozilla Bug + 587910</a> +<p id="display"></p> +<div id="content" style="display: none"> +<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px"> + <circle cx="20" cy="20" r="15" fill="blue" id="circle"/> +</svg> +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> +<![CDATA[ +/** Test for SMIL accessKey support **/ + +const gSvgns = "http://www.w3.org/2000/svg"; +var gSvg = document.getElementById("svg"); +SimpleTest.waitForExplicitFinish(); + +function main() +{ + gSvg.pauseAnimations(); + + // Basic syntax + testOk('accessKey(a)', 'a'); + testOk(' accessKey(a) ', 'a'); + testNotOk('accessKey (a)', 'a'); + testNotOk('accessKey( a)', 'a'); + testNotOk('accessKey(a )', 'a'); + testNotOk('accessKey(a)', 'b'); + testNotOk('accessKey()', ' '); + + // Test the test framework itself + testOk('accessKey(a)', 97); + + // Allow for either accessKey (SVG / SMIL Animation) or accesskey (SMIL2+) + testOk('accesskey(a)', 'a'); + + // Offset + testOk('accessKey(a)+0s', 'a'); + testOk('accessKey(a) + 0min', 'a'); + testOk('accessKey(a) -0h', 'a'); + testOk('accessKey(a)+100ms', 'a', 0, 0.1); + testOk('accessKey(a)-0.1s', 'a', 0, -0.1); + + // Id references are not allowed + testNotOk('svg.accessKey(a)', 'a'); + testNotOk('window.accessKey(a)', 'a'); + + // Case sensitivity + testOk('accessKey(A)', 'A'); + testNotOk('accessKey(a)', 'A'); + testNotOk('accessKey(A)', 'a'); + + // Test unusual characters + testOk('accessKey(-)', '-'); + testOk('accessKey(\\)', '\\'); + testOk('accessKey( )', ' '); + testOk('accessKey(\x0D)', 0, KeyboardEvent.DOM_VK_RETURN); + testOk('accessKey(\n)', 0, KeyboardEvent.DOM_VK_RETURN); // New line + testOk('accessKey(\r)', 0, KeyboardEvent.DOM_VK_RETURN); // Carriage return + testOk('accessKey(\x08)', 0, KeyboardEvent.DOM_VK_BACK_SPACE); + testOk('accessKey(\x1B)', 0, KeyboardEvent.DOM_VK_ESCAPE); + testOk('accessKey(\x7F)', 0, KeyboardEvent.DOM_VK_DELETE); + + // Check some disallowed keys + // -- For now we don't allow tab since the interaction with focus causes + // confusing results + testNotOk('accessKey(\x09)', 0, 9); // Tab + + // Test setting the keyCode field + testNotOk('accessKey(a)', 0, 97); + testOk('accessKey(a)', 97, 66); // Give priority to charCode field + testNotOk('accessKey(a)', 98, 97); // Give priority to charCode field + + // Test unicode + testOk("accessKey(\u20AC)", 8364); // euro-symbol + + // Test an astral character just to make sure we don't crash + testOk("accessKey(\uD835\uDC00)", 119808); // mathematical bold capital A + // 0x1D400 + // Test bad surrogate pairs don't confuse us either + testNotOk("accessKey(\uD800\uD800)", 97); + testNotOk("accessKey(\uD80020)", 97); + testNotOk("accessKey(\uD800)", 97); + + // Test modifiers + // -- When matching on charCode ignore shift and alt + testNotOk('accessKey(a)', 'a', 0, 0, { ctrl: true }); + testNotOk('accessKey(a)', 'a', 0, 0, { meta: true }); + testOk('accessKey(a)', 'a', 0, 0, { alt: true }); + testOk('accessKey(a)', 'a', 0, 0, { shift: true }); + testNotOk('accessKey(a)', 'a', 0, 0, { shift: true, ctrl: true }); + testNotOk('accessKey(a)', 'a', 0, 0, { alt: true, meta: true }); + // -- When matching on keyCode ignore all + testNotOk('accessKey(\x0D)', 0, 13, 0, { ctrl: true }); + testNotOk('accessKey(\x0D)', 0, 13, 0, { meta: true }); + testNotOk('accessKey(\x0D)', 0, 13, 0, { alt: true }); + testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true }); + testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true, ctrl: true }); + + testOpenEnd(); + testPreventDefault(); + testDispatchToWindow(); + testAdoptNode(); + testFauxEvent(); + + SimpleTest.finish(); +} + +function testOk(spec, charCode, keyCode, offset, modifiers) +{ + if (typeof offset == 'undefined') offset = 0; + var msg = "No interval created for '" + spec + + "' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" + + getModifiersDescr(modifiers); + ok(test(spec, charCode, keyCode, offset, modifiers), msg); +} + +function testNotOk(spec, charCode, keyCode, offset, modifiers) +{ + if (typeof offset == 'undefined') offset = 0; + var msg = "Interval unexpectedly created for '" + spec + + "' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" + + getModifiersDescr(modifiers); + ok(!test(spec, charCode, keyCode, offset, modifiers), msg); +} + +function getModifiersDescr(modifiers) +{ + if (typeof modifiers != 'object') + return ''; + var str = ' modifiers set:'; + for (var key in modifiers) { + if (modifiers[key]) str += ' ' + key; + } + return str; +} + +function test(spec, charCode, keyCode, offset, modifiers) +{ + gSvg.setCurrentTime(1); + ok(gSvg.animationsPaused(), "Expected animations to be paused"); + + var anim = createAnim(spec); + var evt = createEvent(charCode, keyCode, modifiers); + + document.getElementById('circle').dispatchEvent(evt); + + var gotStartTimeOk = true; + try { + var start = anim.getStartTime(); + if (offset) { + var expected = gSvg.getCurrentTime() + offset; + ok(Math.abs(expected - start) <= 0.00001, + "Unexpected start time for animation with begin: " + spec + + " got " + start + ", expected " + expected); + } else { + is(start, gSvg.getCurrentTime() + offset, + "Unexpected start time for animation with begin: " + spec); + } + } catch(e) { + is(e.name, "InvalidStateError", + "Unexpected exception: " + e.name); + is(e.code, DOMException.INVALID_STATE_ERR, + "Unexpected exception code: " + e.code); + gotStartTimeOk = false; + } + + anim.parentNode.removeChild(anim); + + return gotStartTimeOk; +} + +function createAnim(beginSpec) +{ + var anim = document.createElementNS(gSvgns, 'animate'); + anim.setAttribute('attributeName', 'cx'); + anim.setAttribute('values', '0; 100'); + anim.setAttribute('dur', '10s'); + anim.setAttribute('begin', beginSpec); + return document.getElementById('circle').appendChild(anim); +} + +function createEvent(charCode, keyCode, modifiers) +{ + if (typeof charCode == 'string') { + is(charCode.length, 1, + "If charCode is a string it should be 1 character long"); + charCode = charCode.charCodeAt(0); + } else if (typeof charCode == 'undefined') { + charCode = 0; + } + args = { ctrl: false, alt: false, shift: false, meta: false }; + if (typeof modifiers == 'object') { + for (var key in modifiers) + args[key] = modifiers[key]; + } + if (typeof keyCode == 'undefined') keyCode = 0; + var evt = document.createEvent("KeyboardEvent"); + evt.initKeyEvent("keypress", true, true, window, + args['ctrl'], + args['alt'], + args['shift'], + args['meta'], + keyCode, + charCode); + return evt; +} + +function testOpenEnd() +{ + // Test that an end specification with an accesskey value is treated as open + // ended + gSvg.setCurrentTime(0); + ok(gSvg.animationsPaused(), "Expected animations to be paused"); + + var anim = createAnim('0s; 2s'); + anim.setAttribute('end', '1s; accessKey(a)'); + + gSvg.setCurrentTime(2); + + try { + is(anim.getStartTime(), 2, + "Unexpected start time for second interval of open-ended animation"); + } catch(e) { + is(e.name, "InvalidStateError", + "Unexpected exception:" + e.name); + is(e.code, DOMException.INVALID_STATE_ERR, + "Unexpected exception code:" + e.code); + ok(false, "Failed to recognise accessKey as qualifying for creating an " + + "open-ended interval"); + } + + anim.parentNode.removeChild(anim); +} + +function testPreventDefault() +{ + // SVG/SMIL don't specify what should happen if preventDefault is called on + // the keypress event. For now, for consistency with event timing we ignore + // it. + gSvg.setCurrentTime(1); + ok(gSvg.animationsPaused(), "Expected animations to be paused"); + + var anim = createAnim('accessKey(a)'); + var evt = createEvent('a'); + + var circle = document.getElementById('circle'); + var func = function(evt) { evt.preventDefault(); } + circle.addEventListener('keypress', func, false); + circle.dispatchEvent(evt); + + try { + var start = anim.getStartTime(); + } catch(e) { + ok(false, "preventDefault() cancelled accessKey handling"); + } + + circle.removeEventListener('keypress', func, false); + anim.parentNode.removeChild(anim); +} + +function testDispatchToWindow() +{ + gSvg.setCurrentTime(1); + ok(gSvg.animationsPaused(), "Expected animations to be paused"); + + var anim = createAnim('accessKey(a)'); + var evt = createEvent('a'); + + window.dispatchEvent(evt); + + try { + var start = anim.getStartTime(); + } catch(e) { + ok(false, "Key event dispatched to the window failed to trigger " + + "accesskey handling"); + } + + anim.parentNode.removeChild(anim); +} + +function testAdoptNode() +{ + gSvg.setCurrentTime(1); + ok(gSvg.animationsPaused(), "Expected animations to be paused"); + + // Create a new document with an animation element + var newdoc = document.implementation.createDocument(gSvgns, 'svg', null); + var anim = newdoc.createElementNS(gSvgns, 'animate'); + anim.setAttribute('attributeName', 'cx'); + anim.setAttribute('values', '0; 100'); + anim.setAttribute('dur', '10s'); + anim.setAttribute('begin', 'accesskey(a)'); + newdoc.documentElement.appendChild(anim); + + // Adopt + ok(anim.ownerDocument !== document, + "Expected newly created animation to belong to a different doc"); + document.adoptNode(anim); + document.getElementById('circle').appendChild(anim); + ok(anim.ownerDocument === document, + "Expected newly created animation to belong to the same doc"); + + var evt = createEvent('a'); + + // Now fire an event at the original window and check nothing happens + newdoc.dispatchEvent(evt); + try { + var start = anim.getStartTime(); + ok(false, "Adopted node still receiving accesskey events from old doc"); + } catch(e) { + // Ok + } + + // And then fire at our window + document.dispatchEvent(evt); + try { + var start = anim.getStartTime(); + } catch(e) { + ok(false, "Adopted node failed to catch accesskey event"); + } + + anim.parentNode.removeChild(anim); +} + +function testFauxEvent() +{ + // Test a non-KeyEvent labelled as a key event + gSvg.setCurrentTime(0); + ok(gSvg.animationsPaused(), "Expected animations to be paused"); + + var anim = createAnim('accessKey(a)'); + var evt = document.createEvent("SVGEvents"); + evt.initEvent("keypress", true, true); + document.getElementById('circle').dispatchEvent(evt); + + // We're really just testing that the above didn't crash us, but while we're + // at it, just do a sanity check that we didn't also create an interval + try { + var start = anim.getStartTime(); + ok(false, "Faux event generated interval"); + } catch(e) { + // All is well + } + + anim.parentNode.removeChild(anim); +} + +window.addEventListener("load", main, false); +]]> +</script> +</pre> +</body> +</html> |