toolkit/components/passwordmgr/test/test_basic_form_autocomplete.html
author dolske@mozilla.com
Tue, 18 Mar 2008 13:19:15 -0700
changeset 13262 0d12c9237e016368e296dd37057dc5fe991b22c8
parent 11855 c2925228a4b212f07411a682c12d90dbfe5e8805
child 15083 7e035f571c708194dbf03665e08c73ed4d5fa5cf
permissions -rw-r--r--
Revert logging added when debugging bug 399852.

<!DOCTYPE HTML>
<html>
<head>
  <title>Test for Login Manager</title>
  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>  
  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="text/javascript" src="pwmgr_common.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
Login Manager test: multiple login autocomplete
<p id="display"></p>

<!-- we presumably can't hide the content for this test. -->
<div id="content">

  <form id="form1" action="http://autocomplete:8888/formtest.js" onsubmit="return false;">
    <input  type="text"       name="uname">
    <input  type="password"   name="pword">

    <button type="submit">Submit</button>
    <button type="reset"> Reset </button>
  </form>

</div>

<pre id="test">
<script class="testbody" type="text/javascript">

/** Test for Login Manager: multiple login autocomplete. **/

netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

var uname = $_(1, "uname");
var pword = $_(1, "pword");
const shiftModifier = Components.interfaces.nsIDOMNSEvent.SHIFT_MASK;

// Window utils for sending fake sey events.
var wutils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                      getInterface(Components.interfaces.nsIDOMWindowUtils);

// Get the pwmgr service
var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
            .getService(Components.interfaces.nsILoginManager);
ok(pwmgr != null, "nsLoginManager service");

// Create some logins just for this form, since we'll be deleting them.
var nsLoginInfo =
Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
                       Components.interfaces.nsILoginInfo, "init");
ok(nsLoginInfo != null, "nsLoginInfo constructor");


var login1 = new nsLoginInfo(
    "http://localhost:8888", "http://autocomplete:8888", null,
    "tempuser1", "temppass1", "uname", "pword");

var login2 = new nsLoginInfo(
    "http://localhost:8888", "http://autocomplete:8888", null,
    "testuser2", "testpass2", "uname", "pword");

var login3 = new nsLoginInfo(
    "http://localhost:8888", "http://autocomplete:8888", null,
    "testuser3", "testpass3", "uname", "pword");

var login4 = new nsLoginInfo(
    "http://localhost:8888", "http://autocomplete:8888", null,
    "zzzuser4", "zzzpass4", "uname", "pword");

// try/catch in case someone runs the tests manually, twice.
try {
    pwmgr.addLogin(login1);
    pwmgr.addLogin(login2);
    pwmgr.addLogin(login3);
    pwmgr.addLogin(login4);
} catch (e) {
    ok(false, "addLogin threw: " + e);
}


// Restore the form to the default state.
function restoreForm() {
    uname.value = "";
    pword.value = "";
    uname.focus();
}


// Check for expected username/password in form.
function checkACForm(expectedUsername, expectedPassword) {
  is(uname.value, expectedUsername, "Checking form username");
  is(pword.value, expectedPassword, "Checking form password");
}


// Mochitest gives us a sendKey(), but it's targeted to a specific element.
// This basically sends an untargeted key event, to whatever's focused.
function doKey(aKey, modifier) {
    // Seems we need to enable this again, or sendKeyEvent() complaints.
    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

    var keyName = "DOM_VK_" + aKey.toUpperCase();
    var key = Components.interfaces.nsIDOMKeyEvent[keyName];

    // undefined --> null
    if (!modifier)
        modifier = null;

    wutils.sendKeyEvent("keydown",  key, 0, modifier);
    wutils.sendKeyEvent("keypress", key, 0, modifier);
    wutils.sendKeyEvent("keyup",    key, 0, modifier);
}



/*
 * Main section of test...
 *
 * This is a bit hacky, because the events are either being sent or
 * processes asynchronously, so we need to interrupt our flow with lots of
 * setTimeout() calls. The case statements are executed in order, one per
 * timeout.
 */
function runTest(testNum) {
  // Seems we need to enable this again, or sendKeyEvent() complaints.
  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
  ok(true, "Starting test #" + testNum);

  switch(testNum) {
    case 1:
        // Make sure initial form is empty.
        checkACForm("", "");
        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 2:
        // Check first entry
        doKey("down");
        checkACForm("", ""); // value shouldn't update
        doKey("return"); // not "enter"!
        checkACForm("tempuser1", "temppass1");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 3:
        // Check second entry
        doKey("down");
        doKey("down");
        doKey("return"); // not "enter"!
        checkACForm("testuser2", "testpass2");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 4:
        // Check third entry
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("return");
        checkACForm("testuser3", "testpass3");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 5:
        // Check fourth entry
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("return");
        checkACForm("zzzuser4", "zzzpass4");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 6:
        // Check first entry (wraparound)
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("down");
        doKey("down"); // deselects
        doKey("down");
        doKey("return");
        checkACForm("tempuser1", "temppass1");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 7:
        // Check the last entry via arrow-up
        doKey("up");
        doKey("return");
        checkACForm("zzzuser4", "zzzpass4");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 8:
        // Check the last entry via arrow-up
        doKey("down"); // select first entry
        doKey("up");   // selects nothing!
        doKey("up");   // select last entry
        doKey("return");
        checkACForm("zzzuser4", "zzzpass4");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 9:
        // Check the last entry via arrow-up (wraparound)
        doKey("down");
        doKey("up"); // deselects
        doKey("up"); // last entry
        doKey("up");
        doKey("up");
        doKey("up"); // first entry
        doKey("up"); // deselects
        doKey("up"); // last entry
        doKey("return");
        checkACForm("zzzuser4", "zzzpass4");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 10:
        // Set first entry w/o triggering autocomplete
        doKey("down");
        doKey("right");
        checkACForm("tempuser1", ""); // empty password

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 11:
        // Set first entry w/o triggering autocomplete
        doKey("down");
        doKey("left");
        checkACForm("tempuser1", ""); // empty password

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 12:
        // Check first entry (page up)
        doKey("down");
        doKey("down");
        doKey("page_up");
        doKey("return");
        checkACForm("tempuser1", "temppass1");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 13:
        // Check last entry (page down)
        doKey("down");
        doKey("page_down");
        doKey("return");
        checkACForm("zzzuser4", "zzzpass4");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        testNum = 49;
        break;

    case 14:
        // Abort with ESC
// XXX This isn't working in the test suite, seems to fubar any later tests.
//        doKey("down");
//        doKey("down");
//        doKey("escape");
//        checkACForm("", "");

        // Trigger autocomplete popup
//        restoreForm();
//        doKey("down");
        break;

    // XXX tried sending character "t" before/during dropdown to test
    // filtering, but had no luck. Seemed like the character was getting lost.
    // Setting uname.value didn't seem to work either. This works with a human
    // driver, so I'm not sure what's up.


    case 50:
        // Delete the first entry (of 4), "tempuser1"
        doKey("down");
        var numLogins;
        numLogins = pwmgr.countLogins("http://localhost:8888", "http://autocomplete:8888", null);
        is(numLogins, 4, "Correct number of logins before deleting one");

        // On OS X, shift-backspace and shift-delete work, just delete does not.
        // On Win/Linux, shift-backspace does not work, delete and shift-delete do.
        doKey("delete", shiftModifier);

        checkACForm("zzzuser4", ""); // why does a value get set here?
        numLogins = pwmgr.countLogins("http://localhost:8888", "http://autocomplete:8888", null);
        is(numLogins, 3, "Correct number of logins after deleting one");
        doKey("return");
        checkACForm("testuser2", "testpass2");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 51:
        // Check the new first entry (of 3)
        doKey("down");
        doKey("return");
        checkACForm("testuser2", "testpass2");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 52:
        // Delete the second entry (of 3), "testuser3"
        doKey("down");
        doKey("down");
        doKey("delete", shiftModifier);
        checkACForm("testuser2", ""); // XXX why does a value get set here?
        numLogins = pwmgr.countLogins("http://localhost:8888", "http://autocomplete:8888", null);
        is(numLogins, 2, "Correct number of logins after deleting one");
        doKey("return");
        checkACForm("zzzuser4", "zzzpass4");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 53:
        // Check the new second entry (of 2)
        doKey("down");
        doKey("return");
        checkACForm("testuser2", "testpass2");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 54:
        // Delete the last entry (of 2), "zzzuser4"
        doKey("down");
        doKey("down");
        doKey("delete", shiftModifier);
        checkACForm("testuser2", ""); // XXX why does a value get set here?
        numLogins = pwmgr.countLogins("http://localhost:8888", "http://autocomplete:8888", null);
        is(numLogins, 1, "Correct number of logins after deleting one");
        doKey("return");
        checkACForm("testuser2", "testpass2");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 55:
        // Check the new second entry (of 2)
        doKey("down");
        doKey("return");
        checkACForm("testuser2", "testpass2");

        // Trigger autocomplete popup
        restoreForm();
        doKey("down");
        break;

    case 56:
        // Delete the only remaining entry, "testuser2"
        doKey("down");
        doKey("delete", shiftModifier);
        //doKey("return");
        checkACForm("", "");
        numLogins = pwmgr.countLogins("http://localhost:8888", "http://autocomplete:8888", null);
        is(numLogins, 0, "Correct number of logins after deleting one");

    default:
        SimpleTest.finish();
        return;
  }

  setTimeout(runTest, 50, testNum + 1); // XXX 40ms was too slow, why?
}


function startTest() {
    runTest(1);
}

window.onload = startTest;

SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>