Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 /**
5 * Make sure that the variables view is keyboard accessible.
6 */
8 let gTab, gDebuggee, gPanel, gDebugger;
9 let gVariablesView;
11 function test() {
12 initDebugger("about:blank").then(([aTab, aDebuggee, aPanel]) => {
13 gTab = aTab;
14 gDebuggee = aDebuggee;
15 gPanel = aPanel;
16 gDebugger = gPanel.panelWin;
17 gVariablesView = gDebugger.DebuggerView.Variables;
19 performTest().then(null, aError => {
20 ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
21 });
22 });
23 }
25 function performTest() {
26 let arr = [
27 42,
28 true,
29 "nasu",
30 undefined,
31 null,
32 [0, 1, 2],
33 { prop1: 9, prop2: 8 }
34 ];
36 let obj = {
37 p0: 42,
38 p1: true,
39 p2: "nasu",
40 p3: undefined,
41 p4: null,
42 p5: [3, 4, 5],
43 p6: { prop1: 7, prop2: 6 },
44 get p7() { return arr; },
45 set p8(value) { arr[0] = value }
46 };
48 let test = {
49 someProp0: 42,
50 someProp1: true,
51 someProp2: "nasu",
52 someProp3: undefined,
53 someProp4: null,
54 someProp5: arr,
55 someProp6: obj,
56 get someProp7() { return arr; },
57 set someProp7(value) { arr[0] = value }
58 };
60 gVariablesView.eval = function() {};
61 gVariablesView.switch = function() {};
62 gVariablesView.delete = function() {};
63 gVariablesView.rawObject = test;
64 gVariablesView.scrollPageSize = 5;
66 return Task.spawn(function() {
67 yield waitForTick();
69 // Part 0: Test generic focus methods on the variables view.
71 gVariablesView.focusFirstVisibleItem();
72 is(gVariablesView.getFocusedItem().name, "someProp0",
73 "The 'someProp0' item should be focused.");
75 gVariablesView.focusNextItem();
76 is(gVariablesView.getFocusedItem().name, "someProp1",
77 "The 'someProp1' item should be focused.");
79 gVariablesView.focusPrevItem();
80 is(gVariablesView.getFocusedItem().name, "someProp0",
81 "The 'someProp0' item should be focused.");
83 // Part 1: Make sure that UP/DOWN keys don't scroll the variables view.
85 yield synthesizeKeyAndWaitForTick("VK_DOWN", {});
86 is(gVariablesView._parent.scrollTop, 0,
87 "The 'variables' view shouldn't scroll when pressing the DOWN key.");
89 yield synthesizeKeyAndWaitForTick("VK_UP", {});
90 is(gVariablesView._parent.scrollTop, 0,
91 "The 'variables' view shouldn't scroll when pressing the UP key.");
93 // Part 2: Make sure that RETURN/ESCAPE toggle input elements.
95 yield synthesizeKeyAndWaitForElement("VK_RETURN", {}, ".element-value-input", true);
96 yield synthesizeKeyAndWaitForElement("VK_ESCAPE", {}, ".element-value-input", false);
97 yield synthesizeKeyAndWaitForElement("VK_RETURN", { shiftKey: true }, ".element-name-input", true);
98 yield synthesizeKeyAndWaitForElement("VK_ESCAPE", {}, ".element-name-input", false);
100 // Part 3: Test simple navigation.
102 EventUtils.sendKey("DOWN", gDebugger);
103 is(gVariablesView.getFocusedItem().name, "someProp1",
104 "The 'someProp1' item should be focused.");
106 EventUtils.sendKey("UP", gDebugger);
107 is(gVariablesView.getFocusedItem().name, "someProp0",
108 "The 'someProp0' item should be focused.");
110 EventUtils.sendKey("PAGE_DOWN", gDebugger);
111 is(gVariablesView.getFocusedItem().name, "someProp5",
112 "The 'someProp5' item should be focused.");
114 EventUtils.sendKey("PAGE_UP", gDebugger);
115 is(gVariablesView.getFocusedItem().name, "someProp0",
116 "The 'someProp0' item should be focused.");
118 EventUtils.sendKey("END", gDebugger);
119 is(gVariablesView.getFocusedItem().name, "__proto__",
120 "The '__proto__' item should be focused.");
122 EventUtils.sendKey("HOME", gDebugger);
123 is(gVariablesView.getFocusedItem().name, "someProp0",
124 "The 'someProp0' item should be focused.");
126 // Part 4: Test if pressing the same navigation key twice works as expected.
128 EventUtils.sendKey("DOWN", gDebugger);
129 is(gVariablesView.getFocusedItem().name, "someProp1",
130 "The 'someProp1' item should be focused.");
132 EventUtils.sendKey("DOWN", gDebugger);
133 is(gVariablesView.getFocusedItem().name, "someProp2",
134 "The 'someProp2' item should be focused.");
136 EventUtils.sendKey("UP", gDebugger);
137 is(gVariablesView.getFocusedItem().name, "someProp1",
138 "The 'someProp1' item should be focused.");
140 EventUtils.sendKey("UP", gDebugger);
141 is(gVariablesView.getFocusedItem().name, "someProp0",
142 "The 'someProp0' item should be focused.");
144 EventUtils.sendKey("PAGE_DOWN", gDebugger);
145 is(gVariablesView.getFocusedItem().name, "someProp5",
146 "The 'someProp5' item should be focused.");
148 EventUtils.sendKey("PAGE_DOWN", gDebugger);
149 is(gVariablesView.getFocusedItem().name, "__proto__",
150 "The '__proto__' item should be focused.");
152 EventUtils.sendKey("PAGE_UP", gDebugger);
153 is(gVariablesView.getFocusedItem().name, "someProp5",
154 "The 'someProp5' item should be focused.");
156 EventUtils.sendKey("PAGE_UP", gDebugger);
157 is(gVariablesView.getFocusedItem().name, "someProp0",
158 "The 'someProp0' item should be focused.");
160 // Part 5: Test that HOME/PAGE_UP/PAGE_DOWN are symmetrical.
162 EventUtils.sendKey("HOME", gDebugger);
163 is(gVariablesView.getFocusedItem().name, "someProp0",
164 "The 'someProp0' item should be focused.");
166 EventUtils.sendKey("HOME", gDebugger);
167 is(gVariablesView.getFocusedItem().name, "someProp0",
168 "The 'someProp0' item should be focused.");
170 EventUtils.sendKey("PAGE_UP", gDebugger);
171 is(gVariablesView.getFocusedItem().name, "someProp0",
172 "The 'someProp0' item should be focused.");
174 EventUtils.sendKey("HOME", gDebugger);
175 is(gVariablesView.getFocusedItem().name, "someProp0",
176 "The 'someProp0' item should be focused.");
178 EventUtils.sendKey("END", gDebugger);
179 is(gVariablesView.getFocusedItem().name, "__proto__",
180 "The '__proto__' item should be focused.");
182 EventUtils.sendKey("END", gDebugger);
183 is(gVariablesView.getFocusedItem().name, "__proto__",
184 "The '__proto__' item should be focused.");
186 EventUtils.sendKey("PAGE_DOWN", gDebugger);
187 is(gVariablesView.getFocusedItem().name, "__proto__",
188 "The '__proto__' item should be focused.");
190 EventUtils.sendKey("END", gDebugger);
191 is(gVariablesView.getFocusedItem().name, "__proto__",
192 "The '__proto__' item should be focused.");
194 // Part 6: Test that focus doesn't leave the variables view.
196 EventUtils.sendKey("PAGE_UP", gDebugger);
197 is(gVariablesView.getFocusedItem().name, "someProp5",
198 "The 'someProp5' item should be focused.");
200 EventUtils.sendKey("PAGE_UP", gDebugger);
201 is(gVariablesView.getFocusedItem().name, "someProp0",
202 "The 'someProp0' item should be focused.");
204 EventUtils.sendKey("UP", gDebugger);
205 is(gVariablesView.getFocusedItem().name, "someProp0",
206 "The 'someProp0' item should be focused.");
208 EventUtils.sendKey("UP", gDebugger);
209 is(gVariablesView.getFocusedItem().name, "someProp0",
210 "The 'someProp0' item should be focused.");
212 EventUtils.sendKey("PAGE_DOWN", gDebugger);
213 is(gVariablesView.getFocusedItem().name, "someProp5",
214 "The 'someProp5' item should be focused.");
216 EventUtils.sendKey("PAGE_DOWN", gDebugger);
217 is(gVariablesView.getFocusedItem().name, "__proto__",
218 "The '__proto__' item should be focused.");
220 EventUtils.sendKey("PAGE_DOWN", gDebugger);
221 is(gVariablesView.getFocusedItem().name, "__proto__",
222 "The '__proto__' item should be focused.");
224 EventUtils.sendKey("PAGE_DOWN", gDebugger);
225 is(gVariablesView.getFocusedItem().name, "__proto__",
226 "The '__proto__' item should be focused.");
228 // Part 7: Test that random offsets don't occur in tandem with HOME/END.
230 EventUtils.sendKey("HOME", gDebugger);
231 is(gVariablesView.getFocusedItem().name, "someProp0",
232 "The 'someProp0' item should be focused.");
234 EventUtils.sendKey("DOWN", gDebugger);
235 is(gVariablesView.getFocusedItem().name, "someProp1",
236 "The 'someProp1' item should be focused.");
238 EventUtils.sendKey("END", gDebugger);
239 is(gVariablesView.getFocusedItem().name, "__proto__",
240 "The '__proto__' item should be focused.");
242 EventUtils.sendKey("DOWN", gDebugger);
243 is(gVariablesView.getFocusedItem().name, "__proto__",
244 "The '__proto__' item should be focused.");
246 // Part 8: Test that the RIGHT key expands elements as intended.
248 EventUtils.sendKey("PAGE_UP", gDebugger);
249 is(gVariablesView.getFocusedItem().name, "someProp5",
250 "The 'someProp5' item should be focused.");
251 is(gVariablesView.getFocusedItem().expanded, false,
252 "The 'someProp5' item should not be expanded yet.");
254 yield synthesizeKeyAndWaitForTick("VK_RIGHT", {});
255 is(gVariablesView.getFocusedItem().name, "someProp5",
256 "The 'someProp5' item should be focused.");
257 is(gVariablesView.getFocusedItem().expanded, true,
258 "The 'someProp5' item should now be expanded.");
259 is(gVariablesView.getFocusedItem()._store.size, 9,
260 "There should be 9 properties in the selected variable.");
261 is(gVariablesView.getFocusedItem()._enumItems.length, 7,
262 "There should be 7 enumerable properties in the selected variable.");
263 is(gVariablesView.getFocusedItem()._nonEnumItems.length, 2,
264 "There should be 2 non-enumerable properties in the selected variable.");
266 yield waitForChildNodes(gVariablesView.getFocusedItem()._enum, 7);
267 yield waitForChildNodes(gVariablesView.getFocusedItem()._nonenum, 2);
269 EventUtils.sendKey("RIGHT", gDebugger);
270 is(gVariablesView.getFocusedItem().name, "0",
271 "The '0' item should be focused.");
273 EventUtils.sendKey("RIGHT", gDebugger);
274 is(gVariablesView.getFocusedItem().name, "0",
275 "The '0' item should still be focused.");
277 EventUtils.sendKey("PAGE_DOWN", gDebugger);
278 is(gVariablesView.getFocusedItem().name, "5",
279 "The '5' item should be focused.");
280 is(gVariablesView.getFocusedItem().expanded, false,
281 "The '5' item should not be expanded yet.");
283 yield synthesizeKeyAndWaitForTick("VK_RIGHT", {});
284 is(gVariablesView.getFocusedItem().name, "5",
285 "The '5' item should be focused.");
286 is(gVariablesView.getFocusedItem().expanded, true,
287 "The '5' item should now be expanded.");
288 is(gVariablesView.getFocusedItem()._store.size, 5,
289 "There should be 5 properties in the selected variable.");
290 is(gVariablesView.getFocusedItem()._enumItems.length, 3,
291 "There should be 3 enumerable properties in the selected variable.");
292 is(gVariablesView.getFocusedItem()._nonEnumItems.length, 2,
293 "There should be 2 non-enumerable properties in the selected variable.");
295 yield waitForChildNodes(gVariablesView.getFocusedItem()._enum, 3);
296 yield waitForChildNodes(gVariablesView.getFocusedItem()._nonenum, 2);
298 EventUtils.sendKey("RIGHT", gDebugger);
299 is(gVariablesView.getFocusedItem().name, "0",
300 "The '0' item should be focused.");
302 EventUtils.sendKey("RIGHT", gDebugger);
303 is(gVariablesView.getFocusedItem().name, "0",
304 "The '0' item should still be focused.");
306 EventUtils.sendKey("PAGE_DOWN", gDebugger);
307 is(gVariablesView.getFocusedItem().name, "6",
308 "The '6' item should be focused.");
309 is(gVariablesView.getFocusedItem().expanded, false,
310 "The '6' item should not be expanded yet.");
312 yield synthesizeKeyAndWaitForTick("VK_RIGHT", {});
313 is(gVariablesView.getFocusedItem().name, "6",
314 "The '6' item should be focused.");
315 is(gVariablesView.getFocusedItem().expanded, true,
316 "The '6' item should now be expanded.");
317 is(gVariablesView.getFocusedItem()._store.size, 3,
318 "There should be 3 properties in the selected variable.");
319 is(gVariablesView.getFocusedItem()._enumItems.length, 2,
320 "There should be 2 enumerable properties in the selected variable.");
321 is(gVariablesView.getFocusedItem()._nonEnumItems.length, 1,
322 "There should be 1 non-enumerable properties in the selected variable.");
324 yield waitForChildNodes(gVariablesView.getFocusedItem()._enum, 2);
325 yield waitForChildNodes(gVariablesView.getFocusedItem()._nonenum, 1);
327 EventUtils.sendKey("RIGHT", gDebugger);
328 is(gVariablesView.getFocusedItem().name, "prop1",
329 "The 'prop1' item should be focused.");
331 EventUtils.sendKey("RIGHT", gDebugger);
332 is(gVariablesView.getFocusedItem().name, "prop1",
333 "The 'prop1' item should still be focused.");
335 EventUtils.sendKey("PAGE_DOWN", gDebugger);
336 is(gVariablesView.getFocusedItem().name, "someProp6",
337 "The 'someProp6' item should be focused.");
338 is(gVariablesView.getFocusedItem().expanded, false,
339 "The 'someProp6' item should not be expanded yet.");
341 // Part 9: Test that the RIGHT key collapses elements as intended.
343 EventUtils.sendKey("LEFT", gDebugger);
344 is(gVariablesView.getFocusedItem().name, "someProp6",
345 "The 'someProp6' item should be focused.");
347 EventUtils.sendKey("UP", gDebugger);
348 is(gVariablesView.getFocusedItem().name, "__proto__",
349 "The '__proto__' item should be focused.");
351 EventUtils.sendKey("LEFT", gDebugger);
352 is(gVariablesView.getFocusedItem().name, "someProp5",
353 "The 'someProp5' item should be focused.");
354 is(gVariablesView.getFocusedItem().expanded, true,
355 "The '6' item should still be expanded.");
357 EventUtils.sendKey("LEFT", gDebugger);
358 is(gVariablesView.getFocusedItem().name, "someProp5",
359 "The 'someProp5' item should still be focused.");
360 is(gVariablesView.getFocusedItem().expanded, false,
361 "The '6' item should still not be expanded anymore.");
363 EventUtils.sendKey("LEFT", gDebugger);
364 is(gVariablesView.getFocusedItem().name, "someProp5",
365 "The 'someProp5' item should still be focused.");
367 // Part 9: Test continuous navigation.
369 EventUtils.sendKey("UP", gDebugger);
370 is(gVariablesView.getFocusedItem().name, "someProp4",
371 "The 'someProp4' item should be focused.");
373 EventUtils.sendKey("UP", gDebugger);
374 is(gVariablesView.getFocusedItem().name, "someProp3",
375 "The 'someProp3' item should be focused.");
377 EventUtils.sendKey("UP", gDebugger);
378 is(gVariablesView.getFocusedItem().name, "someProp2",
379 "The 'someProp2' item should be focused.");
381 EventUtils.sendKey("UP", gDebugger);
382 is(gVariablesView.getFocusedItem().name, "someProp1",
383 "The 'someProp1' item should be focused.");
385 EventUtils.sendKey("UP", gDebugger);
386 is(gVariablesView.getFocusedItem().name, "someProp0",
387 "The 'someProp0' item should be focused.");
389 EventUtils.sendKey("PAGE_UP", gDebugger);
390 is(gVariablesView.getFocusedItem().name, "someProp0",
391 "The 'someProp0' item should be focused.");
393 EventUtils.sendKey("PAGE_DOWN", gDebugger);
394 is(gVariablesView.getFocusedItem().name, "someProp5",
395 "The 'someProp5' item should be focused.");
397 EventUtils.sendKey("DOWN", gDebugger);
398 is(gVariablesView.getFocusedItem().name, "someProp6",
399 "The 'someProp6' item should be focused.");
401 EventUtils.sendKey("DOWN", gDebugger);
402 is(gVariablesView.getFocusedItem().name, "someProp7",
403 "The 'someProp7' item should be focused.");
405 EventUtils.sendKey("DOWN", gDebugger);
406 is(gVariablesView.getFocusedItem().name, "get",
407 "The 'get' item should be focused.");
409 EventUtils.sendKey("DOWN", gDebugger);
410 is(gVariablesView.getFocusedItem().name, "set",
411 "The 'set' item should be focused.");
413 EventUtils.sendKey("DOWN", gDebugger);
414 is(gVariablesView.getFocusedItem().name, "__proto__",
415 "The '__proto__' item should be focused.");
417 // Part 10: Test that BACKSPACE deletes items in the variables view.
419 EventUtils.sendKey("BACK_SPACE", gDebugger);
420 is(gVariablesView.getFocusedItem().name, "__proto__",
421 "The '__proto__' variable should still be focused.");
422 is(gVariablesView.getFocusedItem().value, "[object Object]",
423 "The '__proto__' variable should not have an empty value.");
424 is(gVariablesView.getFocusedItem().visible, false,
425 "The '__proto__' variable should be hidden.");
427 EventUtils.sendKey("UP", gDebugger);
428 is(gVariablesView.getFocusedItem().name, "set",
429 "The 'set' item should be focused.");
430 is(gVariablesView.getFocusedItem().value, "[object Object]",
431 "The 'set' item should not have an empty value.");
432 is(gVariablesView.getFocusedItem().visible, true,
433 "The 'set' item should be visible.");
435 EventUtils.sendKey("BACK_SPACE", gDebugger);
436 is(gVariablesView.getFocusedItem().name, "set",
437 "The 'set' item should still be focused.");
438 is(gVariablesView.getFocusedItem().value, "[object Object]",
439 "The 'set' item should not have an empty value.");
440 is(gVariablesView.getFocusedItem().visible, true,
441 "The 'set' item should be visible.");
442 is(gVariablesView.getFocusedItem().twisty, false,
443 "The 'set' item should be disabled and have a hidden twisty.");
445 EventUtils.sendKey("UP", gDebugger);
446 is(gVariablesView.getFocusedItem().name, "get",
447 "The 'get' item should be focused.");
448 is(gVariablesView.getFocusedItem().value, "[object Object]",
449 "The 'get' item should not have an empty value.");
450 is(gVariablesView.getFocusedItem().visible, true,
451 "The 'get' item should be visible.");
453 EventUtils.sendKey("BACK_SPACE", gDebugger);
454 is(gVariablesView.getFocusedItem().name, "get",
455 "The 'get' item should still be focused.");
456 is(gVariablesView.getFocusedItem().value, "[object Object]",
457 "The 'get' item should not have an empty value.");
458 is(gVariablesView.getFocusedItem().visible, true,
459 "The 'get' item should be visible.");
460 is(gVariablesView.getFocusedItem().twisty, false,
461 "The 'get' item should be disabled and have a hidden twisty.");
463 EventUtils.sendKey("UP", gDebugger);
464 is(gVariablesView.getFocusedItem().name, "someProp7",
465 "The 'someProp7' item should be focused.");
466 is(gVariablesView.getFocusedItem().value, undefined,
467 "The 'someProp7' variable should have an empty value.");
468 is(gVariablesView.getFocusedItem().visible, true,
469 "The 'someProp7' variable should be visible.");
471 EventUtils.sendKey("BACK_SPACE", gDebugger);
472 is(gVariablesView.getFocusedItem().name, "someProp7",
473 "The 'someProp7' variable should still be focused.");
474 is(gVariablesView.getFocusedItem().value, undefined,
475 "The 'someProp7' variable should have an empty value.");
476 is(gVariablesView.getFocusedItem().visible, false,
477 "The 'someProp7' variable should be hidden.");
479 // Part 11: Test that Ctrl-C copies the current item to the system clipboard
481 gVariablesView.focusFirstVisibleItem();
482 let copied = promise.defer();
483 let expectedValue = gVariablesView.getFocusedItem().name
484 + gVariablesView.getFocusedItem().separatorStr
485 + gVariablesView.getFocusedItem().value;
487 waitForClipboard(expectedValue, function setup() {
488 EventUtils.synthesizeKey("C", { metaKey: true }, gDebugger);
489 }, copied.resolve, copied.reject
490 );
492 try {
493 yield copied.promise;
494 ok(true,
495 "Ctrl-C copied the selected item to the clipboard.");
496 } catch (e) {
497 ok(false,
498 "Ctrl-C didn't copy the selected item to the clipboard.");
499 }
501 yield closeDebuggerAndFinish(gPanel);
502 });
503 }
505 registerCleanupFunction(function() {
506 gTab = null;
507 gDebuggee = null;
508 gPanel = null;
509 gDebugger = null;
510 gVariablesView = null;
511 });
513 function synthesizeKeyAndWaitForElement(aKey, aModifiers, aSelector, aExistence) {
514 EventUtils.synthesizeKey(aKey, aModifiers, gDebugger);
515 return waitForElement(aSelector, aExistence);
516 }
518 function synthesizeKeyAndWaitForTick(aKey, aModifiers) {
519 EventUtils.synthesizeKey(aKey, aModifiers, gDebugger);
520 return waitForTick();
521 }
523 function waitForElement(aSelector, aExistence) {
524 return waitForPredicate(() => {
525 return !!gVariablesView._list.querySelector(aSelector) == aExistence;
526 });
527 }
529 function waitForChildNodes(aTarget, aCount) {
530 return waitForPredicate(() => {
531 return aTarget.childNodes.length == aCount;
532 });
533 }
535 function waitForPredicate(aPredicate, aInterval = 10) {
536 let deferred = promise.defer();
538 // Poll every few milliseconds until the element is retrieved.
539 let count = 0;
540 let intervalID = window.setInterval(() => {
541 // Make sure we don't wait for too long.
542 if (++count > 1000) {
543 deferred.reject("Timed out while polling for the element.");
544 window.clearInterval(intervalID);
545 return;
546 }
547 // Check if the predicate condition is fulfilled.
548 if (!aPredicate()) {
549 return;
550 }
551 // We got the element, it's safe to callback.
552 window.clearInterval(intervalID);
553 deferred.resolve();
554 }, aInterval);
556 return deferred.promise;
557 }