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 <!DOCTYPE HTML>
2 <html>
3 <head>
4 <title>Test for Login Manager</title>
5 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
6 <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
7 <script type="text/javascript" src="pwmgr_common.js"></script>
8 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
9 </head>
10 <body>
11 Login Manager test: multiple login autocomplete
13 <script>
14 commonInit();
15 SimpleTest.waitForExplicitFinish();
17 // Get the pwmgr service
18 var pwmgr = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
19 .getService(SpecialPowers.Ci.nsILoginManager);
20 ok(pwmgr != null, "nsLoginManager service");
22 // Create some logins just for this form, since we'll be deleting them.
23 var nsLoginInfo =
24 SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1",
25 SpecialPowers.Ci.nsILoginInfo, "init");
26 ok(nsLoginInfo != null, "nsLoginInfo constructor");
29 // login0 has no username, so should be filtered out from the autocomplete list.
30 var login0 = new nsLoginInfo(
31 "http://mochi.test:8888", "http://autocomplete:8888", null,
32 "", "user0pass", "", "pword");
34 var login1 = new nsLoginInfo(
35 "http://mochi.test:8888", "http://autocomplete:8888", null,
36 "tempuser1", "temppass1", "uname", "pword");
38 var login2 = new nsLoginInfo(
39 "http://mochi.test:8888", "http://autocomplete:8888", null,
40 "testuser2", "testpass2", "uname", "pword");
42 var login3 = new nsLoginInfo(
43 "http://mochi.test:8888", "http://autocomplete:8888", null,
44 "testuser3", "testpass3", "uname", "pword");
46 var login4 = new nsLoginInfo(
47 "http://mochi.test:8888", "http://autocomplete:8888", null,
48 "zzzuser4", "zzzpass4", "uname", "pword");
50 // login 5 only used in the single-user forms
51 var login5 = new nsLoginInfo(
52 "http://mochi.test:8888", "http://autocomplete2", null,
53 "singleuser5", "singlepass5", "uname", "pword");
55 var login6A = new nsLoginInfo(
56 "http://mochi.test:8888", "http://autocomplete3", null,
57 "form7user1", "form7pass1", "uname", "pword");
58 var login6B = new nsLoginInfo(
59 "http://mochi.test:8888", "http://autocomplete3", null,
60 "form7user2", "form7pass2", "uname", "pword");
62 var login7 = new nsLoginInfo(
63 "http://mochi.test:8888", "http://autocomplete4", null,
64 "form8user", "form8pass", "uname", "pword");
66 var login8A = new nsLoginInfo(
67 "http://mochi.test:8888", "http://autocomplete5", null,
68 "form9userAB", "form9pass", "uname", "pword");
70 var login8B = new nsLoginInfo(
71 "http://mochi.test:8888", "http://autocomplete5", null,
72 "form9userAAB", "form9pass", "uname", "pword");
74 // login8C is added later
75 var login8C = new nsLoginInfo(
76 "http://mochi.test:8888", "http://autocomplete5", null,
77 "form9userAABz", "form9pass", "uname", "pword");
78 // try/catch in case someone runs the tests manually, twice.
79 try {
80 pwmgr.addLogin(login0);
81 pwmgr.addLogin(login1);
82 pwmgr.addLogin(login2);
83 pwmgr.addLogin(login3);
84 pwmgr.addLogin(login4);
85 pwmgr.addLogin(login5);
86 pwmgr.addLogin(login6A);
87 pwmgr.addLogin(login6B);
88 pwmgr.addLogin(login7);
89 pwmgr.addLogin(login8A);
90 pwmgr.addLogin(login8B);
91 } catch (e) {
92 ok(false, "addLogin threw: " + e);
93 }
95 </script>
96 <p id="display"></p>
98 <!-- we presumably can't hide the content for this test. -->
99 <div id="content">
101 <!-- form1 tests multiple matching logins -->
102 <form id="form1" action="http://autocomplete:8888/formtest.js" onsubmit="return false;">
103 <input type="text" name="uname">
104 <input type="password" name="pword">
105 <button type="submit">Submit</button>
106 </form>
108 <!-- other forms test single logins, with autocomplete=off set -->
109 <form id="form2" action="http://autocomplete2" onsubmit="return false;">
110 <input type="text" name="uname">
111 <input type="password" name="pword" autocomplete="off">
112 <button type="submit">Submit</button>
113 </form>
115 <form id="form3" action="http://autocomplete2" onsubmit="return false;">
116 <input type="text" name="uname" autocomplete="off">
117 <input type="password" name="pword">
118 <button type="submit">Submit</button>
119 </form>
121 <form id="form4" action="http://autocomplete2" onsubmit="return false;" autocomplete="off">
122 <input type="text" name="uname">
123 <input type="password" name="pword">
124 <button type="submit">Submit</button>
125 </form>
127 <form id="form5" action="http://autocomplete2" onsubmit="return false;">
128 <input type="text" name="uname" autocomplete="off">
129 <input type="password" name="pword" autocomplete="off">
130 <button type="submit">Submit</button>
131 </form>
133 <!-- control -->
134 <form id="form6" action="http://autocomplete2" onsubmit="return false;">
135 <input type="text" name="uname">
136 <input type="password" name="pword">
137 <button type="submit">Submit</button>
138 </form>
140 <!-- This form will be manipulated to insert a different username field. -->
141 <form id="form7" action="http://autocomplete3" onsubmit="return false;">
142 <input type="text" name="uname">
143 <input type="password" name="pword">
144 <button type="submit">Submit</button>
145 </form>
147 <!-- test for no autofill after onblur with blank username -->
148 <form id="form8" action="http://autocomplete4" onsubmit="return false;">
149 <input type="text" name="uname">
150 <input type="password" name="pword">
151 <button type="submit">Submit</button>
152 </form>
154 <!-- test autocomplete dropdown -->
155 <form id="form9" action="http://autocomplete5" onsubmit="return false;">
156 <input type="text" name="uname">
157 <input type="password" name="pword">
158 <button type="submit">Submit</button>
159 </form>
160 </div>
162 <pre id="test">
163 <script class="testbody" type="text/javascript">
165 /** Test for Login Manager: multiple login autocomplete. **/
168 var uname = $_(1, "uname");
169 var pword = $_(1, "pword");
170 const shiftModifier = SpecialPowers.Ci.nsIDOMEvent.SHIFT_MASK;
172 // Restore the form to the default state.
173 function restoreForm() {
174 uname.value = "";
175 pword.value = "";
176 uname.focus();
177 }
180 // Check for expected username/password in form.
181 function checkACForm(expectedUsername, expectedPassword) {
182 var formID = uname.parentNode.id;
183 is(uname.value, expectedUsername, "Checking " + formID + " username");
184 is(pword.value, expectedPassword, "Checking " + formID + " password");
185 }
188 function sendFakeAutocompleteEvent(element) {
189 var acEvent = document.createEvent("HTMLEvents");
190 acEvent.initEvent("DOMAutoComplete", true, false);
191 element.dispatchEvent(acEvent);
192 }
194 function hitEventLoop(func, times) {
195 if (times > 0) {
196 setTimeout(hitEventLoop, 0, func, times - 1);
197 } else {
198 setTimeout(func, 0);
199 }
200 }
202 var gNextTestWillOpenPopup = true;
203 var gLastTest = 704;
205 function addPopupListener(eventName, func, capture) {
206 autocompletePopup.addEventListener(eventName, func, capture);
207 }
209 function removePopupListener(eventName, func, capture) {
210 autocompletePopup.removeEventListener(eventName, func, capture);
211 }
213 /*
214 * Main section of test...
215 *
216 * This is a bit hacky, because the events are either being sent or
217 * processes asynchronously, so we need to interrupt our flow with lots of
218 * setTimeout() calls. The case statements are executed in order, one per
219 * timeout.
220 */
221 function runTest(testNum) {
222 ok(true, "Starting test #" + testNum);
224 if (gNextTestWillOpenPopup) {
225 addPopupListener("popupshown", function() {
226 removePopupListener("popupshown", arguments.callee, false);
228 if (testNum != gLastTest) {
229 window.setTimeout(runTest, 0, testNum + 1);
230 }
231 }, false);
232 } else {
233 var unexpectedPopup = function() {
234 removePopupListener("popupshown", arguments.callee, false);
236 ok(false, "Test " + testNum + " should not show a popup");
237 };
238 addPopupListener("popupshown", unexpectedPopup, false);
239 if (testNum == gLastTest) {
240 removePopupListener("popupshown", unexpectedPopup, false);
241 } else {
242 hitEventLoop(function() {
243 removePopupListener("popupshown", unexpectedPopup, false);
244 runTest(testNum + 1);
245 }, 100);
246 }
247 }
249 switch(testNum) {
250 case 1:
251 // Make sure initial form is empty.
252 checkACForm("", "");
253 // Trigger autocomplete popup
254 restoreForm();
255 doKey("down");
256 break;
258 case 2:
259 // Check first entry
260 doKey("down");
261 checkACForm("", ""); // value shouldn't update
262 doKey("return"); // not "enter"!
263 checkACForm("tempuser1", "temppass1");
265 // Trigger autocomplete popup
266 restoreForm();
267 doKey("down");
268 break;
270 case 3:
271 // Check second entry
272 doKey("down");
273 doKey("down");
274 doKey("return"); // not "enter"!
275 checkACForm("testuser2", "testpass2");
277 // Trigger autocomplete popup
278 restoreForm();
279 doKey("down");
280 break;
282 case 4:
283 // Check third entry
284 doKey("down");
285 doKey("down");
286 doKey("down");
287 doKey("return");
288 checkACForm("testuser3", "testpass3");
290 // Trigger autocomplete popup
291 restoreForm();
292 doKey("down");
293 break;
295 case 5:
296 // Check fourth entry
297 doKey("down");
298 doKey("down");
299 doKey("down");
300 doKey("down");
301 doKey("return");
302 checkACForm("zzzuser4", "zzzpass4");
304 // Trigger autocomplete popup
305 restoreForm();
306 doKey("down");
307 break;
309 case 6:
310 // Check first entry (wraparound)
311 doKey("down");
312 doKey("down");
313 doKey("down");
314 doKey("down");
315 doKey("down"); // deselects
316 doKey("down");
317 doKey("return");
318 checkACForm("tempuser1", "temppass1");
320 // Trigger autocomplete popup
321 restoreForm();
322 doKey("down");
323 break;
325 case 7:
326 // Check the last entry via arrow-up
327 doKey("up");
328 doKey("return");
329 checkACForm("zzzuser4", "zzzpass4");
331 // Trigger autocomplete popup
332 restoreForm();
333 doKey("down");
334 break;
336 case 8:
337 // Check the last entry via arrow-up
338 doKey("down"); // select first entry
339 doKey("up"); // selects nothing!
340 doKey("up"); // select last entry
341 doKey("return");
342 checkACForm("zzzuser4", "zzzpass4");
344 // Trigger autocomplete popup
345 restoreForm();
346 doKey("down");
347 break;
349 case 9:
350 // Check the last entry via arrow-up (wraparound)
351 doKey("down");
352 doKey("up"); // deselects
353 doKey("up"); // last entry
354 doKey("up");
355 doKey("up");
356 doKey("up"); // first entry
357 doKey("up"); // deselects
358 doKey("up"); // last entry
359 doKey("return");
360 checkACForm("zzzuser4", "zzzpass4");
362 // Trigger autocomplete popup
363 restoreForm();
364 doKey("down");
365 break;
367 case 10:
368 // Set first entry w/o triggering autocomplete
369 doKey("down");
370 doKey("right");
371 checkACForm("tempuser1", ""); // empty password
373 // Trigger autocomplete popup
374 restoreForm();
375 doKey("down");
376 break;
378 case 11:
379 // Set first entry w/o triggering autocomplete
380 doKey("down");
381 doKey("left");
382 checkACForm("tempuser1", ""); // empty password
384 // Trigger autocomplete popup
385 restoreForm();
386 doKey("down");
387 break;
389 case 12:
390 // Check first entry (page up)
391 doKey("down");
392 doKey("down");
393 doKey("page_up");
394 doKey("return");
395 checkACForm("tempuser1", "temppass1");
397 // Trigger autocomplete popup
398 restoreForm();
399 doKey("down");
400 gNextTestWillOpenPopup = false;
401 break;
403 case 13:
404 // Check last entry (page down)
405 doKey("down");
406 doKey("page_down");
407 doKey("return");
408 checkACForm("zzzuser4", "zzzpass4");
409 restoreForm();
410 gNextTestWillOpenPopup = false;
411 break;
413 case 14:
414 // Send a fake (untrusted) event.
415 checkACForm("", "");
416 uname.value = "zzzuser4";
417 sendFakeAutocompleteEvent(uname);
418 checkACForm("zzzuser4", "");
419 gNextTestWillOpenPopup = true;
420 break;
422 case 15:
423 //checkACForm("zzzuser4", "");
425 // Trigger autocomplete popup
426 restoreForm();
427 doKey("down");
428 testNum = 49;
429 break;
431 // XXX tried sending character "t" before/during dropdown to test
432 // filtering, but had no luck. Seemed like the character was getting lost.
433 // Setting uname.value didn't seem to work either. This works with a human
434 // driver, so I'm not sure what's up.
437 case 50:
438 // Delete the first entry (of 4), "tempuser1"
439 doKey("down");
440 var numLogins;
441 numLogins = pwmgr.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
442 is(numLogins, 5, "Correct number of logins before deleting one");
444 // On OS X, shift-backspace and shift-delete work, just delete does not.
445 // On Win/Linux, shift-backspace does not work, delete and shift-delete do.
446 doKey("delete", shiftModifier);
448 checkACForm("", "");
449 numLogins = pwmgr.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
450 is(numLogins, 4, "Correct number of logins after deleting one");
451 doKey("return");
452 checkACForm("testuser2", "testpass2");
454 // Trigger autocomplete popup
455 restoreForm();
456 doKey("down");
457 break;
459 case 51:
460 // Check the new first entry (of 3)
461 doKey("down");
462 doKey("return");
463 checkACForm("testuser2", "testpass2");
465 // Trigger autocomplete popup
466 restoreForm();
467 doKey("down");
468 break;
470 case 52:
471 // Delete the second entry (of 3), "testuser3"
472 doKey("down");
473 doKey("down");
474 doKey("delete", shiftModifier);
475 checkACForm("", "");
476 numLogins = pwmgr.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
477 is(numLogins, 3, "Correct number of logins after deleting one");
478 doKey("return");
479 checkACForm("zzzuser4", "zzzpass4");
481 // Trigger autocomplete popup
482 restoreForm();
483 doKey("down");
484 break;
486 case 53:
487 // Check the new second entry (of 2)
488 doKey("down");
489 doKey("return");
490 checkACForm("testuser2", "testpass2");
492 // Trigger autocomplete popup
493 restoreForm();
494 doKey("down");
495 break;
497 case 54:
498 // Delete the last entry (of 2), "zzzuser4"
499 doKey("down");
500 doKey("down");
501 doKey("delete", shiftModifier);
502 checkACForm("", "");
503 numLogins = pwmgr.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
504 is(numLogins, 2, "Correct number of logins after deleting one");
505 doKey("return");
506 checkACForm("testuser2", "testpass2");
508 // Trigger autocomplete popup
509 restoreForm();
510 doKey("down");
511 break;
513 case 55:
514 // Check the new second entry (of 2)
515 doKey("down");
516 doKey("return");
517 checkACForm("testuser2", "testpass2");
519 // Trigger autocomplete popup
520 restoreForm();
521 doKey("down");
522 gNextTestWillOpenPopup = false;
523 break;
525 case 56:
526 // Delete the only remaining entry, "testuser2"
527 doKey("down");
528 doKey("delete", shiftModifier);
529 //doKey("return");
530 checkACForm("", "");
531 numLogins = pwmgr.countLogins("http://mochi.test:8888", "http://autocomplete:8888", null);
532 is(numLogins, 1, "Correct number of logins after deleting one");
533 pwmgr.removeLogin(login0); // remove the login that's not shown in the list.
534 testNum = 99;
535 gNextTestWillOpenPopup = true;
536 break;
539 /* Tests for single-user forms with autocomplete=off */
541 case 100:
542 // Turn our attention to form2
543 uname = $_(2, "uname");
544 pword = $_(2, "pword");
545 checkACForm("", "");
547 // Trigger autocomplete popup
548 restoreForm();
549 doKey("down");
550 gNextTestWillOpenPopup = false;
551 break;
553 case 101:
554 // Check first entry
555 doKey("down");
556 checkACForm("", ""); // value shouldn't update
557 doKey("return"); // not "enter"!
558 checkACForm("singleuser5", "singlepass5");
559 restoreForm(); // clear field, so reloading test doesn't fail
560 gNextTestWillOpenPopup = true;
561 break;
563 case 102:
564 // Turn our attention to form3
565 uname = $_(3, "uname");
566 pword = $_(3, "pword");
567 checkACForm("", "");
569 // Trigger autocomplete popup
570 restoreForm();
571 doKey("down");
572 gNextTestWillOpenPopup = false;
573 break;
575 case 103:
576 // Check first entry
577 doKey("down");
578 checkACForm("", ""); // value shouldn't update
579 doKey("return"); // not "enter"!
580 checkACForm("singleuser5", "singlepass5");
581 gNextTestWillOpenPopup = true;
582 break;
584 case 104:
585 // Turn our attention to form4
586 uname = $_(4, "uname");
587 pword = $_(4, "pword");
588 checkACForm("", "");
590 // Trigger autocomplete popup
591 restoreForm();
592 doKey("down");
593 gNextTestWillOpenPopup = false;
594 break;
596 case 105:
597 // Check first entry
598 doKey("down");
599 checkACForm("", ""); // value shouldn't update
600 doKey("return"); // not "enter"!
601 checkACForm("singleuser5", "singlepass5");
602 gNextTestWillOpenPopup = true;
603 break;
605 case 106:
606 // Turn our attention to form5
607 uname = $_(5, "uname");
608 pword = $_(5, "pword");
609 checkACForm("", "");
611 // Trigger autocomplete popup
612 restoreForm();
613 doKey("down");
614 gNextTestWillOpenPopup = false;
615 break;
617 case 107:
618 // Check first entry
619 doKey("down");
620 checkACForm("", ""); // value shouldn't update
621 doKey("return"); // not "enter"!
622 checkACForm("singleuser5", "singlepass5");
623 gNextTestWillOpenPopup = false;
624 break;
626 case 108:
627 // Turn our attention to form6
628 // (this is a control, w/o autocomplete=off, to ensure the login
629 // that was being suppressed would have been filled in otherwise)
630 uname = $_(6, "uname");
631 pword = $_(6, "pword");
632 checkACForm("singleuser5", "singlepass5");
633 gNextTestWillOpenPopup = false;
634 break;
636 case 109:
637 // Test that the password field remains filled in after changing
638 // the username.
639 uname.focus();
640 doKey("right");
641 sendChar("X");
642 // Trigger the 'blur' event on uname
643 pword.focus();
644 checkACForm("sXingleuser5", "singlepass5");
646 pwmgr.removeLogin(login5);
647 testNum = 499;
648 gNextTestWillOpenPopup = true;
649 break;
651 case 500:
652 // Turn our attention to form7
653 uname = $_(7, "uname");
654 pword = $_(7, "pword");
655 checkACForm("", "");
657 // Insert a new username field into the form. We'll then make sure
658 // that invoking the autocomplete doesn't try to fill the form.
659 var newField = document.createElement("input");
660 newField.setAttribute("type", "text");
661 newField.setAttribute("name", "uname2");
662 pword.parentNode.insertBefore(newField, pword);
663 is($_(7, "uname2").value, "", "Verifying empty uname2");;
665 // Delete login6B. It was created just to prevent filling in a login
666 // automatically, removing it makes it more likely that we'll catch a
667 // future regression with form filling here.
668 pwmgr.removeLogin(login6B);
670 // Trigger autocomplete popup
671 restoreForm();
672 doKey("down");
673 gNextTestWillOpenPopup = false;
674 break;
676 case 501:
677 // Check first entry
678 doKey("down");
679 checkACForm("", ""); // value shouldn't update
680 doKey("return"); // not "enter"!
681 // The form changes, so we expect the old username field to get the
682 // selected autocomplete value, but neither the new username field nor
683 // the password field should have any values filled in.
684 checkACForm("form7user1", "");
685 is($_(7, "uname2").value, "", "Verifying empty uname2");;
686 restoreForm(); // clear field, so reloading test doesn't fail
688 pwmgr.removeLogin(login6A);
689 testNum = 599;
690 gNextTestWillOpenPopup = false;
691 break;
693 case 600:
694 // Turn our attention to form8
695 uname = $_(8, "uname");
696 pword = $_(8, "pword");
697 checkACForm("form8user", "form8pass");
698 restoreForm();
699 gNextTestWillOpenPopup = false;
700 break;
702 case 601:
703 checkACForm("", "");
704 // Focus the previous form to trigger a blur.
705 $_(7, "uname").focus();
706 gNextTestWillOpenPopup = false;
707 break;
709 case 602:
710 checkACForm("", "");
711 restoreForm();
712 gNextTestWillOpenPopup = false;
713 break;
715 case 603:
716 checkACForm("", "");
717 pwmgr.removeLogin(login7);
719 testNum = 699;
720 gNextTestWillOpenPopup = true;
721 break;
723 case 700:
724 // Turn our attention to form9 to test the dropdown - bug 497541
725 uname = $_(9, "uname");
726 pword = $_(9, "pword");
727 uname.focus();
728 sendString("form9userAB");
729 gNextTestWillOpenPopup = true;
730 break;
732 case 701:
733 checkACForm("form9userAB", "");
734 uname.focus();
735 doKey("left");
736 sendChar("A");
737 gNextTestWillOpenPopup = false;
738 break;
740 case 702:
741 // check dropdown is updated after inserting "A"
742 checkACForm("form9userAAB", "");
743 checkMenuEntries(["form9userAAB"]);
744 doKey("down");
745 doKey("return");
746 checkACForm("form9userAAB", "form9pass");
747 gNextTestWillOpenPopup = false;
748 break;
750 case 703:
751 pwmgr.addLogin(login8C);
752 uname.focus();
753 sendChar("z");
754 gNextTestWillOpenPopup = false;
755 break;
757 case 704:
758 // check that empty results are cached - bug 496466
759 checkMenuEntries([]);
761 SimpleTest.finish();
762 return;
764 default:
765 ok(false, "Unexpected invocation of test #" + testNum);
766 SimpleTest.finish();
767 return;
768 }
769 }
772 function checkMenuEntries(expectedValues) {
773 var actualValues = getMenuEntries();
774 is(actualValues.length, expectedValues.length, "Checking length of expected menu");
775 for (var i = 0; i < expectedValues.length; i++)
776 is(actualValues[i], expectedValues[i], "Checking menu entry #"+i);
777 }
779 var autocompletePopup;
780 function getMenuEntries() {
781 var entries = [];
783 // Could perhaps pull values directly from the controller, but it seems
784 // more reliable to test the values that are actually in the tree?
785 var column = autocompletePopup.tree.columns[0];
786 var numRows = autocompletePopup.tree.view.rowCount;
787 for (var i = 0; i < numRows; i++) {
788 entries.push(autocompletePopup.tree.view.getValueAt(i, column));
789 }
790 return entries;
791 }
793 function startTest() {
794 var Ci = SpecialPowers.Ci;
795 chromeWin = SpecialPowers.wrap(window)
796 .QueryInterface(Ci.nsIInterfaceRequestor)
797 .getInterface(Ci.nsIWebNavigation)
798 .QueryInterface(Ci.nsIDocShellTreeItem)
799 .rootTreeItem
800 .QueryInterface(Ci.nsIInterfaceRequestor)
801 .getInterface(Ci.nsIDOMWindow)
802 .QueryInterface(Ci.nsIDOMChromeWindow);
803 // shouldn't reach into browser internals like this and
804 // shouldn't assume ID is consistent across products
805 autocompletePopup = chromeWin.document.getElementById("PopupAutoComplete");
806 ok(autocompletePopup, "Got autocomplete popup");
807 runTest(1);
808 }
810 window.onload = startTest;
811 </script>
812 </pre>
813 </body>
814 </html>