dom/smil/test/test_smilAccessKey.xhtml

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 <html xmlns="http://www.w3.org/1999/xhtml">
     2 <head>
     3   <title>Test for SMIL accessKey support</title>
     4   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
     5   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
     6 </head>
     7 <body>
     8 <a target="_blank"
     9   href="https://bugzilla.mozilla.org/show_bug.cgi?id=587910">Mozilla Bug
    10   587910</a>
    11 <p id="display"></p>
    12 <div id="content" style="display: none">
    13 <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
    14   <circle cx="20" cy="20" r="15" fill="blue" id="circle"/>
    15 </svg>
    16 </div>
    17 <pre id="test">
    18 <script class="testbody" type="text/javascript">
    19 <![CDATA[
    20 /** Test for SMIL accessKey support **/
    22 const gSvgns = "http://www.w3.org/2000/svg";
    23 var gSvg = document.getElementById("svg");
    24 SimpleTest.waitForExplicitFinish();
    26 function main()
    27 {
    28   gSvg.pauseAnimations();
    30   // Basic syntax
    31   testOk('accessKey(a)', 'a');
    32   testOk(' accessKey(a)  ', 'a');
    33   testNotOk('accessKey (a)', 'a');
    34   testNotOk('accessKey( a)', 'a');
    35   testNotOk('accessKey(a )', 'a');
    36   testNotOk('accessKey(a)', 'b');
    37   testNotOk('accessKey()', ' ');
    39   // Test the test framework itself
    40   testOk('accessKey(a)', 97);
    42   // Allow for either accessKey (SVG / SMIL Animation) or accesskey (SMIL2+)
    43   testOk('accesskey(a)', 'a');
    45   // Offset
    46   testOk('accessKey(a)+0s', 'a');
    47   testOk('accessKey(a) + 0min', 'a');
    48   testOk('accessKey(a) -0h', 'a');
    49   testOk('accessKey(a)+100ms', 'a', 0, 0.1);
    50   testOk('accessKey(a)-0.1s', 'a', 0, -0.1);
    52   // Id references are not allowed
    53   testNotOk('svg.accessKey(a)', 'a');
    54   testNotOk('window.accessKey(a)', 'a');
    56   // Case sensitivity
    57   testOk('accessKey(A)', 'A');
    58   testNotOk('accessKey(a)', 'A');
    59   testNotOk('accessKey(A)', 'a');
    61   // Test unusual characters
    62   testOk('accessKey(-)', '-');
    63   testOk('accessKey(\\)', '\\');
    64   testOk('accessKey( )', ' ');
    65   testOk('accessKey(\x0D)', 0, KeyboardEvent.DOM_VK_RETURN);
    66   testOk('accessKey(\n)', 0, KeyboardEvent.DOM_VK_RETURN); // New line
    67   testOk('accessKey(\r)', 0, KeyboardEvent.DOM_VK_RETURN); // Carriage return
    68   testOk('accessKey(\x08)', 0, KeyboardEvent.DOM_VK_BACK_SPACE);
    69   testOk('accessKey(\x1B)', 0, KeyboardEvent.DOM_VK_ESCAPE);
    70   testOk('accessKey(\x7F)', 0, KeyboardEvent.DOM_VK_DELETE);
    72   // Check some disallowed keys
    73   // -- For now we don't allow tab since the interaction with focus causes
    74   //    confusing results
    75   testNotOk('accessKey(\x09)', 0, 9);  // Tab
    77   // Test setting the keyCode field
    78   testNotOk('accessKey(a)', 0, 97);
    79   testOk('accessKey(a)', 97, 66); // Give priority to charCode field
    80   testNotOk('accessKey(a)', 98, 97); // Give priority to charCode field
    82   // Test unicode
    83   testOk("accessKey(\u20AC)", 8364); // euro-symbol
    85   // Test an astral character just to make sure we don't crash
    86   testOk("accessKey(\uD835\uDC00)", 119808); // mathematical bold capital A
    87                                              // 0x1D400
    88   // Test bad surrogate pairs don't confuse us either
    89   testNotOk("accessKey(\uD800\uD800)", 97);
    90   testNotOk("accessKey(\uD80020)", 97);
    91   testNotOk("accessKey(\uD800)", 97);
    93   // Test modifiers
    94   // -- When matching on charCode ignore shift and alt
    95   testNotOk('accessKey(a)', 'a', 0, 0, { ctrl: true });
    96   testNotOk('accessKey(a)', 'a', 0, 0, { meta: true });
    97   testOk('accessKey(a)', 'a', 0, 0, { alt: true });
    98   testOk('accessKey(a)', 'a', 0, 0, { shift: true });
    99   testNotOk('accessKey(a)', 'a', 0, 0, { shift: true, ctrl: true });
   100   testNotOk('accessKey(a)', 'a', 0, 0, { alt: true, meta: true });
   101   // -- When matching on keyCode ignore all
   102   testNotOk('accessKey(\x0D)', 0, 13, 0, { ctrl: true });
   103   testNotOk('accessKey(\x0D)', 0, 13, 0, { meta: true });
   104   testNotOk('accessKey(\x0D)', 0, 13, 0, { alt: true });
   105   testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true });
   106   testNotOk('accessKey(\x0D)', 0, 13, 0, { shift: true, ctrl: true });
   108   testOpenEnd();
   109   testPreventDefault();
   110   testDispatchToWindow();
   111   testAdoptNode();
   112   testFauxEvent();
   114   SimpleTest.finish();
   115 }
   117 function testOk(spec, charCode, keyCode, offset, modifiers)
   118 {
   119   if (typeof offset == 'undefined') offset = 0;
   120   var msg = "No interval created for '" + spec +
   121     "' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" +
   122     getModifiersDescr(modifiers);
   123   ok(test(spec, charCode, keyCode, offset, modifiers), msg);
   124 }
   126 function testNotOk(spec, charCode, keyCode, offset, modifiers)
   127 {
   128   if (typeof offset == 'undefined') offset = 0;
   129   var msg = "Interval unexpectedly created for '" + spec +
   130     "' with input [charCode: " + charCode + "; keyCode: " + keyCode + "]" +
   131     getModifiersDescr(modifiers);
   132   ok(!test(spec, charCode, keyCode, offset, modifiers), msg);
   133 }
   135 function getModifiersDescr(modifiers)
   136 {
   137   if (typeof modifiers != 'object')
   138     return '';
   139   var str = ' modifiers set:';
   140   for (var key in modifiers) {
   141     if (modifiers[key]) str += ' ' + key;
   142   }
   143   return str;
   144 }
   146 function test(spec, charCode, keyCode, offset, modifiers)
   147 {
   148   gSvg.setCurrentTime(1);
   149   ok(gSvg.animationsPaused(), "Expected animations to be paused");
   151   var anim = createAnim(spec);
   152   var evt = createEvent(charCode, keyCode, modifiers);
   154   document.getElementById('circle').dispatchEvent(evt);
   156   var gotStartTimeOk = true;
   157   try {
   158     var start = anim.getStartTime();
   159     if (offset) {
   160       var expected = gSvg.getCurrentTime() + offset;
   161       ok(Math.abs(expected - start) <= 0.00001,
   162         "Unexpected start time for animation with begin: " + spec +
   163           " got " + start + ", expected " + expected);
   164     } else {
   165       is(start, gSvg.getCurrentTime() + offset,
   166          "Unexpected start time for animation with begin: " + spec);
   167     }
   168   } catch(e) {
   169     is(e.name, "InvalidStateError",
   170        "Unexpected exception: " + e.name);
   171     is(e.code, DOMException.INVALID_STATE_ERR,
   172        "Unexpected exception code: " + e.code);
   173     gotStartTimeOk = false;
   174   }
   176   anim.parentNode.removeChild(anim);
   178   return gotStartTimeOk;
   179 }
   181 function createAnim(beginSpec)
   182 {
   183   var anim = document.createElementNS(gSvgns, 'animate');
   184   anim.setAttribute('attributeName', 'cx');
   185   anim.setAttribute('values', '0; 100');
   186   anim.setAttribute('dur', '10s');
   187   anim.setAttribute('begin', beginSpec);
   188   return document.getElementById('circle').appendChild(anim);
   189 }
   191 function createEvent(charCode, keyCode, modifiers)
   192 {
   193   if (typeof charCode == 'string') {
   194     is(charCode.length, 1,
   195        "If charCode is a string it should be 1 character long");
   196     charCode = charCode.charCodeAt(0);
   197   } else if (typeof charCode == 'undefined') {
   198     charCode = 0;
   199   }
   200   args = { ctrl: false, alt: false, shift: false, meta: false };
   201   if (typeof modifiers == 'object') {
   202     for (var key in modifiers)
   203       args[key] = modifiers[key];
   204   }
   205   if (typeof keyCode == 'undefined') keyCode = 0;
   206   var evt = document.createEvent("KeyboardEvent");
   207   evt.initKeyEvent("keypress", true, true, window,
   208                    args['ctrl'],
   209                    args['alt'],
   210                    args['shift'],
   211                    args['meta'],
   212                    keyCode,
   213                    charCode);
   214   return evt;
   215 }
   217 function testOpenEnd()
   218 {
   219   // Test that an end specification with an accesskey value is treated as open
   220   // ended
   221   gSvg.setCurrentTime(0);
   222   ok(gSvg.animationsPaused(), "Expected animations to be paused");
   224   var anim = createAnim('0s; 2s');
   225   anim.setAttribute('end', '1s; accessKey(a)');
   227   gSvg.setCurrentTime(2);
   229   try {
   230     is(anim.getStartTime(), 2,
   231        "Unexpected start time for second interval of open-ended animation");
   232   } catch(e) {
   233     is(e.name, "InvalidStateError",
   234        "Unexpected exception:" + e.name);
   235     is(e.code, DOMException.INVALID_STATE_ERR,
   236        "Unexpected exception code:" + e.code);
   237     ok(false, "Failed to recognise accessKey as qualifying for creating an " +
   238               "open-ended interval");
   239   }
   241   anim.parentNode.removeChild(anim);
   242 }
   244 function testPreventDefault()
   245 {
   246   // SVG/SMIL don't specify what should happen if preventDefault is called on
   247   // the keypress event. For now, for consistency with event timing we ignore
   248   // it.
   249   gSvg.setCurrentTime(1);
   250   ok(gSvg.animationsPaused(), "Expected animations to be paused");
   252   var anim = createAnim('accessKey(a)');
   253   var evt = createEvent('a');
   255   var circle = document.getElementById('circle');
   256   var func = function(evt) { evt.preventDefault(); }
   257   circle.addEventListener('keypress', func, false);
   258   circle.dispatchEvent(evt);
   260   try {
   261     var start = anim.getStartTime();
   262   } catch(e) {
   263     ok(false, "preventDefault() cancelled accessKey handling");
   264   }
   266   circle.removeEventListener('keypress', func, false);
   267   anim.parentNode.removeChild(anim);
   268 }
   270 function testDispatchToWindow()
   271 {
   272   gSvg.setCurrentTime(1);
   273   ok(gSvg.animationsPaused(), "Expected animations to be paused");
   275   var anim = createAnim('accessKey(a)');
   276   var evt = createEvent('a');
   278   window.dispatchEvent(evt);
   280   try {
   281     var start = anim.getStartTime();
   282   } catch(e) {
   283     ok(false, "Key event dispatched to the window failed to trigger " +
   284               "accesskey handling");
   285   }
   287   anim.parentNode.removeChild(anim);
   288 }
   290 function testAdoptNode()
   291 {
   292   gSvg.setCurrentTime(1);
   293   ok(gSvg.animationsPaused(), "Expected animations to be paused");
   295   // Create a new document with an animation element
   296   var newdoc = document.implementation.createDocument(gSvgns, 'svg', null);
   297   var anim = newdoc.createElementNS(gSvgns, 'animate');
   298   anim.setAttribute('attributeName', 'cx');
   299   anim.setAttribute('values', '0; 100');
   300   anim.setAttribute('dur', '10s');
   301   anim.setAttribute('begin', 'accesskey(a)');
   302   newdoc.documentElement.appendChild(anim);
   304   // Adopt
   305   ok(anim.ownerDocument !== document,
   306      "Expected newly created animation to belong to a different doc");
   307   document.adoptNode(anim);
   308   document.getElementById('circle').appendChild(anim);
   309   ok(anim.ownerDocument === document,
   310      "Expected newly created animation to belong to the same doc");
   312   var evt = createEvent('a');
   314   // Now fire an event at the original window and check nothing happens
   315   newdoc.dispatchEvent(evt);
   316   try {
   317     var start = anim.getStartTime();
   318     ok(false, "Adopted node still receiving accesskey events from old doc");
   319   } catch(e) {
   320     // Ok
   321   }
   323   // And then fire at our window
   324   document.dispatchEvent(evt);
   325   try {
   326     var start = anim.getStartTime();
   327   } catch(e) {
   328     ok(false, "Adopted node failed to catch accesskey event");
   329   }
   331   anim.parentNode.removeChild(anim);
   332 }
   334 function testFauxEvent()
   335 {
   336   // Test a non-KeyEvent labelled as a key event
   337   gSvg.setCurrentTime(0);
   338   ok(gSvg.animationsPaused(), "Expected animations to be paused");
   340   var anim = createAnim('accessKey(a)');
   341   var evt = document.createEvent("SVGEvents");
   342   evt.initEvent("keypress", true, true);
   343   document.getElementById('circle').dispatchEvent(evt);
   345   // We're really just testing that the above didn't crash us, but while we're
   346   // at it, just do a sanity check that we didn't also create an interval
   347   try {
   348     var start = anim.getStartTime();
   349     ok(false, "Faux event generated interval");
   350   } catch(e) {
   351     // All is well
   352   }
   354   anim.parentNode.removeChild(anim);
   355 }
   357 window.addEventListener("load", main, false);
   358 ]]>
   359 </script>
   360 </pre>
   361 </body>
   362 </html>

mercurial