dom/smil/test/test_smilAccessKey.xhtml

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:27dcdc1abfe5
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 **/
21
22 const gSvgns = "http://www.w3.org/2000/svg";
23 var gSvg = document.getElementById("svg");
24 SimpleTest.waitForExplicitFinish();
25
26 function main()
27 {
28 gSvg.pauseAnimations();
29
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()', ' ');
38
39 // Test the test framework itself
40 testOk('accessKey(a)', 97);
41
42 // Allow for either accessKey (SVG / SMIL Animation) or accesskey (SMIL2+)
43 testOk('accesskey(a)', 'a');
44
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);
51
52 // Id references are not allowed
53 testNotOk('svg.accessKey(a)', 'a');
54 testNotOk('window.accessKey(a)', 'a');
55
56 // Case sensitivity
57 testOk('accessKey(A)', 'A');
58 testNotOk('accessKey(a)', 'A');
59 testNotOk('accessKey(A)', 'a');
60
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);
71
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
76
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
81
82 // Test unicode
83 testOk("accessKey(\u20AC)", 8364); // euro-symbol
84
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);
92
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 });
107
108 testOpenEnd();
109 testPreventDefault();
110 testDispatchToWindow();
111 testAdoptNode();
112 testFauxEvent();
113
114 SimpleTest.finish();
115 }
116
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 }
125
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 }
134
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 }
145
146 function test(spec, charCode, keyCode, offset, modifiers)
147 {
148 gSvg.setCurrentTime(1);
149 ok(gSvg.animationsPaused(), "Expected animations to be paused");
150
151 var anim = createAnim(spec);
152 var evt = createEvent(charCode, keyCode, modifiers);
153
154 document.getElementById('circle').dispatchEvent(evt);
155
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 }
175
176 anim.parentNode.removeChild(anim);
177
178 return gotStartTimeOk;
179 }
180
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 }
190
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 }
216
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");
223
224 var anim = createAnim('0s; 2s');
225 anim.setAttribute('end', '1s; accessKey(a)');
226
227 gSvg.setCurrentTime(2);
228
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 }
240
241 anim.parentNode.removeChild(anim);
242 }
243
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");
251
252 var anim = createAnim('accessKey(a)');
253 var evt = createEvent('a');
254
255 var circle = document.getElementById('circle');
256 var func = function(evt) { evt.preventDefault(); }
257 circle.addEventListener('keypress', func, false);
258 circle.dispatchEvent(evt);
259
260 try {
261 var start = anim.getStartTime();
262 } catch(e) {
263 ok(false, "preventDefault() cancelled accessKey handling");
264 }
265
266 circle.removeEventListener('keypress', func, false);
267 anim.parentNode.removeChild(anim);
268 }
269
270 function testDispatchToWindow()
271 {
272 gSvg.setCurrentTime(1);
273 ok(gSvg.animationsPaused(), "Expected animations to be paused");
274
275 var anim = createAnim('accessKey(a)');
276 var evt = createEvent('a');
277
278 window.dispatchEvent(evt);
279
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 }
286
287 anim.parentNode.removeChild(anim);
288 }
289
290 function testAdoptNode()
291 {
292 gSvg.setCurrentTime(1);
293 ok(gSvg.animationsPaused(), "Expected animations to be paused");
294
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);
303
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");
311
312 var evt = createEvent('a');
313
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 }
322
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 }
330
331 anim.parentNode.removeChild(anim);
332 }
333
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");
339
340 var anim = createAnim('accessKey(a)');
341 var evt = document.createEvent("SVGEvents");
342 evt.initEvent("keypress", true, true);
343 document.getElementById('circle').dispatchEvent(evt);
344
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 }
353
354 anim.parentNode.removeChild(anim);
355 }
356
357 window.addEventListener("load", main, false);
358 ]]>
359 </script>
360 </pre>
361 </body>
362 </html>

mercurial