Bug 1269039 - Use add_task in test_master_password.html. r=dolske draft
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 29 Apr 2016 15:49:23 -0700
changeset 358043 22ed31b7c519ddc9c9235c62a1c1afcae08def38
parent 358042 7355f4de5d4fbeefa0aa9027db95e52489a267f5
child 358044 fd936cefcdd19c45a3d84ccbe905dd7da6902eb0
push id16913
push usermozilla@noorenberghe.ca
push dateSat, 30 Apr 2016 00:27:41 +0000
reviewersdolske
bugs1269039
milestone49.0a1
Bug 1269039 - Use add_task in test_master_password.html. r=dolske MozReview-Commit-ID: 8Ac0LtrO95X
toolkit/components/passwordmgr/test/mochitest.ini
toolkit/components/passwordmgr/test/mochitest/mochitest.ini
toolkit/components/passwordmgr/test/mochitest/subtst_master_pass.html
toolkit/components/passwordmgr/test/mochitest/test_master_password.html
toolkit/components/passwordmgr/test/subtst_master_pass.html
toolkit/components/passwordmgr/test/test_master_password.html
toolkit/components/prompts/test/chromeScript.js
--- a/toolkit/components/passwordmgr/test/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest.ini
@@ -1,20 +1,16 @@
 [DEFAULT]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || e10s
 support-files =
   authenticate.sjs
   blank.html
   formsubmit.sjs
-  notification_common.js
   prompt_common.js
   pwmgr_common.js
-  subtst_master_pass.html
   subtst_prompt_async.html
 
-[test_master_password.html]
-skip-if = toolkit == 'android' # Tests desktop prompts
 [test_prompt_async.html]
 skip-if = toolkit == 'android' # Tests desktop prompts
 [test_xhr.html]
 skip-if = toolkit == 'android' # Tests desktop prompts
 [test_xml_load.html]
 skip-if = toolkit == 'android' # Tests desktop prompts
--- a/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest/mochitest.ini
@@ -32,14 +32,18 @@ skip-if = toolkit == 'android' # autocom
 [test_form_action_2.html]
 [test_form_action_javascript.html]
 [test_formless_autofill.html]
 skip-if = toolkit == 'android' # Bug 1259768
 [test_formless_submit.html]
 skip-if = toolkit == 'android' # Bug 1259768
 [test_input_events.html]
 [test_input_events_for_identical_values.html]
+[test_master_password.html]
+skip-if = toolkit == 'android' || e10s # Tests desktop prompts
+support-files =
+  subtst_master_pass.html
 [test_maxlength.html]
 [test_passwords_in_type_password.html]
 [test_prompt.html]
 skip-if = e10s || os == "linux" || toolkit == 'android' # Tests desktop prompts
 [test_recipe_login_fields.html]
 [test_xhr_2.html]
rename from toolkit/components/passwordmgr/test/subtst_master_pass.html
rename to toolkit/components/passwordmgr/test/mochitest/subtst_master_pass.html
rename from toolkit/components/passwordmgr/test/test_master_password.html
rename to toolkit/components/passwordmgr/test/mochitest/test_master_password.html
--- a/toolkit/components/passwordmgr/test/test_master_password.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_master_password.html
@@ -1,36 +1,39 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
   <title>Test for master password</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <script type="text/javascript" src="pwmgr_common.js"></script>
   <script type="text/javascript" src="prompt_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 Login Manager test: master password.
 <script>
 "use strict";
 
+// Force parent to not look for tab-modal prompts, as they're not used for auth prompts.
+isTabModal = false;
+
 commonInit();
-SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout("untriaged");
 
 var pwmgr   = SpecialPowers.Cc["@mozilla.org/login-manager;1"]
                            .getService(SpecialPowers.Ci.nsILoginManager);
 var pwcrypt = SpecialPowers.Cc["@mozilla.org/login-manager/crypto/SDR;1"]
                            .getService(Ci.nsILoginManagerCrypto);
 
 var nsLoginInfo = new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
 
-var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/";
-var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/";
+var exampleCom = "http://example.com/tests/toolkit/components/passwordmgr/test/mochitest/";
+var exampleOrg = "http://example.org/tests/toolkit/components/passwordmgr/test/mochitest/";
 
 var login1 = new nsLoginInfo();
 var login2 = new nsLoginInfo();
 
 login1.init("http://example.com", "http://example.com", null,
             "user1", "pass1", "uname", "pword");
 login2.init("http://example.org", "http://example.org", null,
             "user2", "pass2", "uname", "pword");
@@ -43,259 +46,237 @@ pwmgr.addLogin(login2);
 
 <div id="content" style="display: none">
 <iframe id="iframe1"></iframe>
 <iframe id="iframe2"></iframe>
 </div>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
-var testNum = 1;
 var iframe1 = document.getElementById("iframe1");
 var iframe2 = document.getElementById("iframe2");
 
-// A couple of tests have to wait until the password manager gets around to
-// filling in the password in the subtest (after we dismiss the master
-// password dialog). In order to accomplish this, the test waits for an event
-// and then posts a message back up to us telling us to continue.
-var continuation = null;
-addEventListener("message", () => {
-    if (continuation) {
-        var c = continuation;
-        continuation = null;
-        c();
-    }
-});
-
-/*
- * handleDialog
- *
- * Invoked a short period of time after calling startCallbackTimer(), and
- * allows testing the actual auth dialog while it's being displayed. Tests
- * should call startCallbackTimer() each time the auth dialog is expected (the
- * timer is a one-shot).
- */
-function handleDialog(doc, testNum) {
-  ok(true, "handleDialog running for test " + testNum);
-
-  var clickOK   = true;
-  var doNothing = false;
-  var passfield = doc.getElementById("password1Textbox");
-  var dialog    = doc.getElementById("commonDialog");
-
-    switch(testNum) {
-      case 1:
-        is(passfield.getAttribute("value"), "", "Checking empty prompt");
-        passfield.setAttribute("value", masterPassword);
-        is(passfield.getAttribute("value"), masterPassword, "Checking filled prompt");
-        break;
-
-      case 2:
-        clickOK = false;
-        break;
-
-      case 3:
-        is(passfield.getAttribute("value"), "", "Checking empty prompt");
-        passfield.setAttribute("value", masterPassword);
-        break;
-
-      case 4:
-        doNothing = true;
-        break;
-
-      case 5:
-        is(passfield.getAttribute("value"), "", "Checking empty prompt");
-        passfield.setAttribute("value", masterPassword);
-        break;
-
-      default:
-        ok(false, "Uhh, unhandled switch for testNum #" + testNum);
-        break;
-    }
-
-    didDialog = true;
-
-    if (!doNothing) {
-        SpecialPowers.addObserver(outerWindowObserver, "outer-window-destroyed", false);
-        if (clickOK)
-            dialog.acceptDialog();
-        else
-            dialog.cancelDialog();
-    }
-
-    ok(true, "handleDialog done for test " + testNum);
-
-    if (testNum == 4)
-        checkTest4A();
-}
-
-var outerWindowObserver = {
-  observe: function(id) {
-    SpecialPowers.removeObserver(outerWindowObserver, "outer-window-destroyed");
-    var func;
-    if (testNum == 1)
-        func = startTest2;
-    else if (testNum == 2)
-        func = startTest3;
-
-    // For tests 3 and 4C, we use the 'continuation' mechanism, described
-    // above.
-    if (func)
-        setTimeout(func, 300);
-  }
-};
-
-
-function startTest1() {
+add_task(function* test_1() {
     ok(pwcrypt.isLoggedIn, "should be initially logged in (no MP)");
     enableMasterPassword();
     ok(!pwcrypt.isLoggedIn, "should be logged out after setting MP");
 
-    // --- Test 1 ---
     // Trigger a MP prompt via the API
-    startCallbackTimer();
+    var state = {
+        msg         : "Please enter the master password for the Software Security Device.",
+        title       : "the title",
+        textValue   : "",
+        passValue   : "",
+        iconClass   : "authentication-icon question-icon",
+        titleHidden : true,
+        textHidden  : true,
+        passHidden  : false,
+        checkHidden : true,
+        checkMsg    : "",
+        checked     : false,
+        focused     : "passField",
+        defButton   : "button0",
+    };
+    var action = {
+        buttonClick : "ok",
+        passField   : masterPassword,
+    };
+    var promptDone = handlePrompt(state, action);
+
     var logins = pwmgr.getAllLogins();
-    ok(didDialog, "handleDialog was invoked");
+
+    yield promptDone;
     is(logins.length, 3, "expected number of logins");
 
     ok(pwcrypt.isLoggedIn, "should be logged in after MP prompt");
     logoutMasterPassword();
     ok(!pwcrypt.isLoggedIn, "should be logged out");
-}
+});
 
-function startTest2() {
+add_task(function* test_2() {
     // Try again but click cancel.
-    testNum++;
-    startCallbackTimer();
+    var state = {
+        msg         : "Please enter the master password for the Software Security Device.",
+        title       : "the title",
+        textValue   : "",
+        passValue   : "",
+        iconClass   : "authentication-icon question-icon",
+        titleHidden : true,
+        textHidden  : true,
+        passHidden  : false,
+        checkHidden : true,
+        checkMsg    : "",
+        checked     : false,
+        focused     : "passField",
+        defButton   : "button0",
+    };
+    var action = {
+        buttonClick : "cancel",
+    };
+    var promptDone = handlePrompt(state, action);
+
     var failedAsExpected = false;
-    logins = null;
+    var logins = null;
     try {
         logins = pwmgr.getAllLogins();
     } catch (e) { failedAsExpected = true; }
-    ok(didDialog, "handleDialog was invoked");
+    yield promptDone;
     ok(failedAsExpected, "getAllLogins should have thrown");
     is(logins, null, "shouldn't have gotten logins");
     ok(!pwcrypt.isLoggedIn, "should still be logged out");
-}
+});
 
-function startTest3() {
-    // Load a single iframe to trigger a MP
-    testNum++;
+add_task(function* test_3() {
+    var state = {
+        msg         : "Please enter the master password for the Software Security Device.",
+        title       : "the title",
+        textValue   : "",
+        passValue   : "",
+        iconClass   : "authentication-icon question-icon",
+        titleHidden : true,
+        textHidden  : true,
+        passHidden  : false,
+        checkHidden : true,
+        checkMsg    : "",
+        checked     : false,
+        focused     : "passField",
+        defButton   : "button0",
+    };
+    var action = {
+        buttonClick : "ok",
+        passField   : masterPassword,
+    };
+    var promptDone = handlePrompt(state, action);
+
+    var fillPromise = new Promise(resolve => {
+        addEventListener("message", resolve);
+    });
+
+    info("Load a single iframe to trigger a MP");
     iframe1.src = exampleCom + "subtst_master_pass.html";
-    continuation = checkTest3;
-    startCallbackTimer();
-}
 
-function checkTest3() {
-    ok(true, "checkTest3 starting");
-    ok(didDialog, "handleDialog was invoked");
+    yield promptDone;
+    info("promptDone");
+    yield fillPromise;
+    info("filled");
 
     // check contents of iframe1 fields
     var u = SpecialPowers.wrap(iframe1).contentDocument.getElementById("userfield");
     var p = SpecialPowers.wrap(iframe1).contentDocument.getElementById("passfield");
     is(u.value, "user1", "checking expected user to have been filled in");
     is(p.value, "pass1", "checking expected pass to have been filled in");
 
     ok(pwcrypt.isLoggedIn, "should be logged in");
     logoutMasterPassword();
     ok(!pwcrypt.isLoggedIn, "should be logged out");
-
+});
 
-    // --- Test 4 ---
+add_task(function* test_4() {
+    var state = {
+        msg         : "Please enter the master password for the Software Security Device.",
+        title       : "the title",
+        textValue   : "",
+        passValue   : "",
+        iconClass   : "authentication-icon question-icon",
+        titleHidden : true,
+        textHidden  : true,
+        passHidden  : false,
+        checkHidden : true,
+        checkMsg    : "",
+        checked     : false,
+        focused     : "passField",
+        defButton   : "button0",
+    };
+    var action = {
+        buttonClick : "none",
+    };
+    var promptDone = handlePrompt(state, action);
+
     // first part of loading 2 MP-triggering iframes
-    testNum++;
     iframe1.src = exampleOrg + "subtst_master_pass.html";
-    // start the callback, but we'll not enter the MP, just call checkTest4A
-    startCallbackTimer();
-}
-
-function checkTest4A() {
-    ok(true, "checkTest4A starting");
-    ok(didDialog, "handleDialog was invoked");
+    // The MP prompt is open but don't take any action yet.
+    yield promptDone;
 
     // check contents of iframe1 fields
     var u = SpecialPowers.wrap(iframe1).contentDocument.getElementById("userfield");
     var p = SpecialPowers.wrap(iframe1).contentDocument.getElementById("passfield");
     is(u.value, "", "checking expected empty user");
     is(p.value, "", "checking expected empty pass");
 
-
     ok(!pwcrypt.isLoggedIn, "should be logged out");
 
     // XXX check that there's 1 MP window open
 
     // Load another iframe with a login form
     // This should detect that there's already a pending MP prompt, and not
-    // put up a second one. The load event will fire (note that when pwmgr is
-    // driven from DOMContentLoaded, if that blocks due to prompting for a MP,
-    // the load even will also be blocked until the prompt is dismissed).
-    iframe2.onload = checkTest4B_delay;
+    // put up a second one.
+    var loadPromise = new Promise(resolve => {
+        iframe2.addEventListener("load", function onload() {
+            iframe2.removeEventListener("load", onload);
+            resolve();
+        });
+    });
+
     iframe2.src = exampleCom + "subtst_master_pass.html";
-}
+    yield loadPromise;
 
-function checkTest4B_delay() {
     // Testing a negative, wait a little to give the login manager a chance to
     // (incorrectly) fill in the form.
-    setTimeout(checkTest4B, 500);
-}
+    yield new Promise(resolve => setTimeout(resolve, 500));
 
-function checkTest4B() {
-    ok(true, "checkTest4B starting");
     // iframe2 should load without having triggered a MP prompt (because one
     // is already waiting)
 
     // check contents of iframe2 fields
-    var u = SpecialPowers.wrap(iframe2).contentDocument.getElementById("userfield");
-    var p = SpecialPowers.wrap(iframe2).contentDocument.getElementById("passfield");
+    u = SpecialPowers.wrap(iframe2).contentDocument.getElementById("userfield");
+    p = SpecialPowers.wrap(iframe2).contentDocument.getElementById("passfield");
     is(u.value, "", "checking expected empty user");
     is(p.value, "", "checking expected empty pass");
 
     // XXX check that there's 1 MP window open
     ok(!pwcrypt.isLoggedIn, "should be logged out");
 
-    continuation = checkTest4C;
+    // Ok, now enter the MP. The MP prompt is already up.
+
+    var fillPromise = new Promise(resolve => {
+        addEventListener("message", resolve);
+    });
 
-    // Ok, now enter the MP. The MP prompt is already up, but we'll just reuse startCallBackTimer.
-    // --- Test 5 ---
-    testNum++;
-    startCallbackTimer();
-}
-
-function checkTest4C() {
-    ok(true, "checkTest4C starting");
-    ok(didDialog, "handleDialog was invoked");
+    // fill existing MP dialog with MP.
+    action = {
+        buttonClick : "ok",
+        passField   : masterPassword,
+    };
+    yield handlePrompt(state, action);
+    yield fillPromise;
 
     // We shouldn't have to worry about iframe1's load event racing with
     // filling of iframe2's data. We notify observers synchronously, so
     // iframe2's observer will process iframe2 before iframe1 even finishes
-    // processing the form (which is blocking its load event).
+    // processing the form.
     ok(pwcrypt.isLoggedIn, "should be logged in");
 
     // check contents of iframe1 fields
-    var u = SpecialPowers.wrap(iframe1).contentDocument.getElementById("userfield");
-    var p = SpecialPowers.wrap(iframe1).contentDocument.getElementById("passfield");
+    u = SpecialPowers.wrap(iframe1).contentDocument.getElementById("userfield");
+    p = SpecialPowers.wrap(iframe1).contentDocument.getElementById("passfield");
     is(u.value, "user2", "checking expected user to have been filled in");
     is(p.value, "pass2", "checking expected pass to have been filled in");
 
     // check contents of iframe2 fields
     u = SpecialPowers.wrap(iframe2).contentDocument.getElementById("userfield");
     p = SpecialPowers.wrap(iframe2).contentDocument.getElementById("passfield");
     is(u.value, "user1", "checking expected user to have been filled in");
     is(p.value, "pass1", "checking expected pass to have been filled in");
-
-    SimpleTest.finish();
-}
+});
 
 // XXX do a test5ABC with clicking cancel?
 
 SimpleTest.registerCleanupFunction(function finishTest() {
     disableMasterPassword();
 
     pwmgr.removeLogin(login1);
     pwmgr.removeLogin(login2);
 });
 
-window.addEventListener("runTests", startTest1);
 </script>
 </pre>
 </body>
 </html>
-
--- a/toolkit/components/prompts/test/chromeScript.js
+++ b/toolkit/components/prompts/test/chromeScript.js
@@ -186,16 +186,18 @@ function dismissPrompt(ui, action) {
       // and thus DOM events are suppressed.
       let interval = setInterval(() => {
         if (ui.button0.disabled)
           return;
         ui.button0.click();
         clearInterval(interval);
       }, 100);
       break;
+    case "none":
+      break;
 
     default:
       throw "dismissPrompt action listed unknown button.";
   }
 }
 
 function getDialogDoc() {
   // Trudge through all the open windows, until we find the one