Bug 1255265 - Convert password manager test_notifications.html to browser_capture_doorhanger.js. r=dolske
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Mon, 21 Mar 2016 15:30:18 -0400
changeset 290275 095be1660e1f5ba50f68feef4e0a74bcf0d4b6fa
parent 290274 b903047d9572a456eed53377f12b24b1354c1135
child 290276 fbab845377a5bf1fe2215bccff9c5d2714f03e86
push id18365
push usermozilla@noorenberghe.ca
push dateFri, 25 Mar 2016 13:23:49 +0000
treeherderfx-team@d823452bea13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdolske
bugs1255265
milestone48.0a1
Bug 1255265 - Convert password manager test_notifications.html to browser_capture_doorhanger.js. r=dolske test_notifications.html was using an <iframe> which is less realistic so I'm using top-level documents. MozReview-Commit-ID: DdXXYofcRLr
toolkit/components/passwordmgr/test/LoginTestUtils.jsm
toolkit/components/passwordmgr/test/browser/browser.ini
toolkit/components/passwordmgr/test/browser/browser_capture_doorhanger.js
toolkit/components/passwordmgr/test/browser/browser_context_menu.js
toolkit/components/passwordmgr/test/browser/browser_filldoorhanger.js
toolkit/components/passwordmgr/test/browser/browser_notifications.js
toolkit/components/passwordmgr/test/browser/head.js
toolkit/components/passwordmgr/test/mochitest.ini
toolkit/components/passwordmgr/test/notification_common.js
toolkit/components/passwordmgr/test/subtst_notifications_7.html
toolkit/components/passwordmgr/test/test_notifications.html
--- a/toolkit/components/passwordmgr/test/LoginTestUtils.jsm
+++ b/toolkit/components/passwordmgr/test/LoginTestUtils.jsm
@@ -238,8 +238,20 @@ this.LoginTestUtils.testData = {
 
       new LoginInfo("chrome://example_extension", null, "Example Login One",
                     "the username", "the password one", "", ""),
       new LoginInfo("chrome://example_extension", null, "Example Login Two",
                     "the username", "the password two", "", ""),
     ];
   },
 };
+
+this.LoginTestUtils.recipes = {
+  getRecipeParent() {
+    let { LoginManagerParent } = Cu.import("resource://gre/modules/LoginManagerParent.jsm", {});
+    if (!LoginManagerParent.recipeParentPromise) {
+      return null;
+    }
+    return LoginManagerParent.recipeParentPromise.then((recipeParent) => {
+      return recipeParent;
+    });
+  },
+};
--- a/toolkit/components/passwordmgr/test/browser/browser.ini
+++ b/toolkit/components/passwordmgr/test/browser/browser.ini
@@ -1,17 +1,31 @@
 [DEFAULT]
 support-files =
+  ../formsubmit.sjs
+  ../subtst_notifications_1.html
+  ../subtst_notifications_2.html
+  ../subtst_notifications_2pw_0un.html
+  ../subtst_notifications_2pw_1un_1text.html
+  ../subtst_notifications_3.html
+  ../subtst_notifications_4.html
+  ../subtst_notifications_5.html
+  ../subtst_notifications_6.html
+  ../subtst_notifications_8.html
+  ../subtst_notifications_9.html
+  ../subtst_notifications_10.html
   authenticate.sjs
   form_basic.html
+  head.js
   insecure_test.html
   insecure_test_subframe.html
   multiple_forms.html
   streamConverter_content.sjs
 
+[browser_capture_doorhanger.js]
 [browser_DOMFormHasPassword.js]
 [browser_DOMInputPasswordAdded.js]
 [browser_filldoorhanger.js]
 [browser_hasInsecureLoginForms.js]
 [browser_hasInsecureLoginForms_streamConverter.js]
 [browser_notifications.js]
 skip-if = true # Intermittent failures: Bug 1182296, bug 1148771
 [browser_passwordmgr_editing.js]
rename from toolkit/components/passwordmgr/test/test_notifications.html
rename to toolkit/components/passwordmgr/test/browser/browser_capture_doorhanger.js
--- a/toolkit/components/passwordmgr/test/test_notifications.html
+++ b/toolkit/components/passwordmgr/test/browser/browser_capture_doorhanger.js
@@ -1,619 +1,410 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <meta charset="utf-8">
-  <title>Test for Login Manager</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="pwmgr_common.js"></script>
-  <script type="text/javascript" src="notification_common.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-Login Manager test: notifications
-<p id="display"></p>
+/*
+ * Test capture popup notifications
+ */
+
+const BRAND_BUNDLE = Services.strings.createBundle("chrome://branding/locale/brand.properties");
+const BRAND_SHORT_NAME = BRAND_BUNDLE.GetStringFromName("brandShortName");
+
+let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
+                                             Ci.nsILoginInfo, "init");
+let login1 = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
+                             "notifyu1", "notifyp1", "user", "pass");
+let login2 = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
+                             "", "notifyp1", "", "pass");
+let login1B = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
+                              "notifyu1B", "notifyp1B", "user", "pass");
+let login2B = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
+                              "", "notifyp1B", "", "pass");
+
+requestLongerTimeout(2);
+
+add_task(function* setup() {
+  // Load recipes for this test.
+  let recipeParent = yield LoginManagerParent.recipeParentPromise;
+  yield recipeParent.load({
+    siteRecipes: [{
+      hosts: ["example.org"],
+      usernameSelector: "#user",
+      passwordSelector: "#pass",
+    }],
+  });
+});
 
-<div id="content" style="display: none">
-  <iframe id="iframe"></iframe>
-</div>
+add_task(function* test_remember_opens() {
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    notif.remove();
+  });
+});
 
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.8">
+add_task(function* test_clickNever() {
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    is(true, Services.logins.getLoginSavingEnabled("http://mochi.test:8888"),
+       "Checking for login saving enabled");
+    clickDoorhangerButton(notif, NEVER_BUTTON);
+  });
 
-/** Test for Login Manager: notifications. **/
-
-const { Services } = SpecialPowers.Cu.import("resource://gre/modules/Services.jsm");
+  info("Make sure Never took effect");
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(!notif, "checking for no notification popup");
+    is(false, Services.logins.getLoginSavingEnabled("http://mochi.test:8888"),
+       "Checking for login saving disabled");
+    Services.logins.setLoginSavingEnabled("http://mochi.test:8888", true);
+  });
+});
 
-const BRAND_BUNDLE = "chrome://branding/locale/brand.properties";
+add_task(function* test_clickRemember() {
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
 
-// Set testpath to the directory where we live. Used to load tests from
-// alternate Mochitest servers (different hostnames, same content).
-var testpath = document.location.pathname + "/../";
+    is(Services.logins.getAllLogins().length, 0, "Should not have any logins yet");
+    clickDoorhangerButton(notif, REMEMBER_BUTTON);
+  });
 
-var subtests = [
-                   "subtst_notifications_1.html", // 1
-                   "subtst_notifications_1.html", // 2
-                   "subtst_notifications_1.html", // 3
-                   "subtst_notifications_1.html", // 4
-                   "subtst_notifications_1.html", // 5
-                   "subtst_notifications_1.html", // 6
-                   "subtst_notifications_1.html", // 7
-                   "subtst_notifications_1.html", // 8
-                   "subtst_notifications_2.html", // 9
-                   "subtst_notifications_3.html", // 10
-                   "subtst_notifications_4.html", // 11
-                   "subtst_notifications_5.html", // 12
-                   "subtst_notifications_1.html", // 13
-                   "subtst_notifications_6.html", // 14
-                   "subtst_notifications_1.html", // 15
-                   "subtst_notifications_6.html", // 16
-                   "subtst_notifications_8.html", // 17
-                   "subtst_notifications_8.html", // 18
-                   "subtst_notifications_9.html", // 19
-                   "subtst_notifications_10.html",  // 20
-                   "http://test1.example.org:80" + testpath + "subtst_notifications_1.html", // 21
-                   "http://test1.example.org:80" + testpath + "subtst_notifications_7.html", // 22
-                   "http://test1.example.org:80" + testpath + "subtst_notifications_6.html", // 23
-                   "subtst_notifications_2pw_0un.html",  // 24
-                   "subtst_notifications_2pw_0un.html",  // 25
-                   "subtst_notifications_2pw_0un.html",  // 26
-                   "subtst_notifications_2pw_0un.html",  // 27
-                   "subtst_notifications_2pw_0un.html",  // 28
-                   "http://example.org" + testpath + "subtst_notifications_2pw_1un_1text.html", // 29
-                   "http://example.org" + testpath + "subtst_notifications_2pw_1un_1text.html", // 30
-                   "subtst_notifications_1.html", // 31
-               ];
+  info("Make sure Remember took effect and we don't prompt for an existing login");
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(!notif, "checking for no notification popup");
+  });
+
+  checkOnlyLoginWasUsedTwice({ justChanged: false });
+
+  // remove that login
+  Services.logins.removeLogin(login1);
+});
+
+/* signons.rememberSignons pref tests... */
+
+add_task(function* test_rememberSignonsFalse() {
+  info("Make sure we don't prompt with rememberSignons=false");
+  Services.prefs.setBoolPref("signon.rememberSignons", false);
+
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(!notif, "checking for no notification popup");
+  });
+});
+
+add_task(function* test_rememberSignonsTrue() {
+  info("Make sure we prompt with rememberSignons=true");
+  Services.prefs.setBoolPref("signon.rememberSignons", true);
 
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    notif.remove();
+  });
+});
 
-var ignoreLoad = false;
-function handleLoad(aEvent) {
-    // ignore every other load event ... We get one for loading the subtest (which
-    // we want to ignore), and another when the subtest's form submits itself
-    // (which we want to handle, to start the next test).
-    ignoreLoad = !ignoreLoad;
-    if (ignoreLoad) {
-        ok(true, "Ignoring load of subtest #" + testNum);
-        return;
-    }
-    ok(true, "Processing submission of subtest #" + testNum);
+/* autocomplete=off tests... */
+
+add_task(function* test_autocompleteOffUsername() {
+  info("Check for notification popup when autocomplete=off present on username");
+
+  yield testSubmittingLoginForm("subtst_notifications_2.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "checking for notification popup");
+    notif.remove();
+  });
+});
 
-    checkTest();
+add_task(function* test_autocompleteOffPassword() {
+  info("Check for notification popup when autocomplete=off present on password");
 
-    testNum++;
+  yield testSubmittingLoginForm("subtst_notifications_3.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "checking for notification popup");
+    notif.remove();
+  });
+});
 
-    if (testNum <= subtests.length) {
-        ok(true, "Starting test #" + testNum);
-        iframe.src = subtests[testNum-1];
-    } else {
-        ok(true, "notification tests finished.");
-        SimpleTest.finish();
-    }
-}
+add_task(function* test_autocompleteOffForm() {
+  info("Check for notification popup when autocomplete=off present on form");
+
+  yield testSubmittingLoginForm("subtst_notifications_4.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "checking for notification popup");
+    notif.remove();
+  });
+});
 
 
-// Remember, Never for This Site, Not Now
-function checkTest() {
-    var popup, notificationText, expectedText;
-
-    // The document generated from formsubmit.sjs contains the user/pass it
-    // received inside <span id="blah">value</span>
-    var gotUser = SpecialPowers.wrap(iframe).contentDocument.getElementById("user").textContent;
-    var gotPass = SpecialPowers.wrap(iframe).contentDocument.getElementById("pass").textContent;
-
-    let brandBundle = Services.strings.createBundle(BRAND_BUNDLE);
-    let brandShortName = brandBundle.GetStringFromName("brandShortName");
-
-    switch(testNum) {
-
-      /* Basic Yes/No/Never tests... */
-
-      case 1:
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        popup.remove();
-        break;
+add_task(function* test_noPasswordField() {
+  info("Check for no notification popup when no password field present");
 
-      case 2:
-        // Same subtest, this time click Never
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        is(true, pwmgr.getLoginSavingEnabled("http://mochi.test:8888"),
-           "Checking for login saving enabled");
-        clickPopupButton(popup, kNeverButton);
-        break;
-
-      case 3:
-        // Same subtest, make sure Never took effect
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
-        is(false, pwmgr.getLoginSavingEnabled("http://mochi.test:8888"),
-           "Checking for login saving disabled");
-        // reenable login saving.
-        pwmgr.setLoginSavingEnabled("http://mochi.test:8888", true);
-        break;
-
-      case 4:
-        // Same subtest, this time click Remember
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-
-        // Sanity check, no logins should exist yet.
-        var logins = pwmgr.getAllLogins();
-        is(logins.length, 0, "Should not have any logins yet");
-
-        clickPopupButton(popup, kRememberButton);
-        break;
+  yield testSubmittingLoginForm("subtst_notifications_5.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "null", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(!notif, "checking for no notification popup");
+  });
+});
 
-      case 5:
-        // Same subtest, make sure we didn't prompt for an existing login.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
-
-        // Check to make sure we updated the timestamps and use count on the
-        // existing login that was submitted for this form.
-        var logins = pwmgr.getAllLogins();
-        is(logins.length, 1, "Should only have 1 login");
-        ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI");
-        is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission");
-        ok(logins[0].timeLastUsed > logins[0].timeCreated, "timeLastUsed bumped");
-        ok(logins[0].timeCreated == logins[0].timePasswordChanged, "timeChanged not updated");
-
-        // remove that login
-        pwmgr.removeLogin(login1);
-        break;
-
-      /* signons.rememberSignons pref tests... */
+add_task(function* test_pwOnlyLoginMatchesForm() {
+  info("Check for update popup when existing pw-only login matches form.");
+  Services.logins.addLogin(login2);
 
-      case 6:
-        // Same subtest, make sure we're getting the popup again.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        popup.remove();
-        // Change prefs to no longer remember signons
-        prefs.setBoolPref("rememberSignons", false);
-        break;
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "checking for notification popup");
+    notif.remove();
+  });
 
-      case 7:
-        // Same subtest, make sure we're not prompting.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
-        // Change prefs to remember signons again
-        prefs.setBoolPref("rememberSignons", true);
-        break;
-
-      case 8:
-        // Same subtest, make sure we're getting the popup again.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        popup.remove();
-        break;
-
-      /* autocomplete=off tests... */
-
-      case 9:
-        // Check for notification popup when autocomplete=off present
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "checking for notification popup");
-        popup.remove();
-        break;
+  Services.logins.removeLogin(login2);
+});
 
-      case 10:
-        // Check for notification popup when autocomplete=off present
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "checking for notification popup");
-        popup.remove();
-        break;
-
-      case 11:
-        // Check for notification popup when autocomplete=off present
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "checking for notification popup");
-        popup.remove();
-        break;
-
-      /* no password field test... */
-
-      case 12:
-        // Check for no notification popup when no password field present
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "null",     "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
-
-        // Add login for the next test.
-        pwmgr.addLogin(login2);
-        break;
+add_task(function* test_pwOnlyFormMatchesLogin() {
+  info("Check for no notification popup when pw-only form matches existing login.");
+  Services.logins.addLogin(login1);
 
-      case 13:
-        // Check for update popup when existing pw-only login matches form.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "checking for notification popup");
-        popup.remove();
-        pwmgr.removeLogin(login2);
-
-        // Add login for the next test
-        pwmgr.addLogin(login1);
-        break;
+  yield testSubmittingLoginForm("subtst_notifications_6.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(!notif, "checking for no notification popup");
+  });
 
-      case 14:
-        // Check for no notification popup when pw-only form matches existing login.
-        is(gotUser, "null",     "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
-        pwmgr.removeLogin(login1);
-
-        // Add login for the next test
-        pwmgr.addLogin(login2B);
-        break;
-
-      case 15:
-        // Check for notification popup when existing pw-only login doesn't match form.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        pwmgr.removeLogin(login2B);
-        popup.remove();
+  Services.logins.removeLogin(login1);
+});
 
-        // Add login for the next test
-        pwmgr.addLogin(login1B);
-        break;
-
-      case 16:
-        // Check for notification popup when pw-only form doesn't match existing login.
-        is(gotUser, "null",     "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        pwmgr.removeLogin(login1B);
-        popup.remove();
-
-        // Add login for the next tests
-        pwmgr.addLogin(login1);
-        break;
-
-      case 17:
-        // Check for change-password popup, u+p login on u+p form. (not changed)
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "pass2",    "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got notification popup");
-        clickPopupButton(popup, kDontChangeButton);
-        break;
+add_task(function* test_pwOnlyFormDoesntMatchExisting() {
+  info("Check for notification popup when pw-only form doesn't match existing login.");
+  Services.logins.addLogin(login1B);
 
-      case 18:
-        // Check for change-password popup, u+p login on u+p form.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "pass2",    "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got notification popup");
-        clickPopupButton(popup, kChangeButton);
-
-        // Check to make sure we updated the timestamps and use count for
-        // the login being changed with this form.
-        var logins = pwmgr.getAllLogins();
-        is(logins.length, 1, "Should only have 1 login");
-        ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI");
-        is(logins[0].timesUsed, 2, "check .timesUsed incremented on change");
-        ok(logins[0].timeCreated < logins[0].timeLastUsed, "timeLastUsed bumped");
-        ok(logins[0].timeLastUsed == logins[0].timePasswordChanged, "timeUsed == timeChanged");
+  yield testSubmittingLoginForm("subtst_notifications_6.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    notif.remove();
+  });
 
-        // cleanup
-        login1.password = "pass2";
-        pwmgr.removeLogin(login1);
-        login1.password = "notifyp1";
-
-        // Add login for the next test
-        pwmgr.addLogin(login2);
-        break;
-
-      // ...can't change a u+p login on a p-only form...
+  Services.logins.removeLogin(login1B);
+});
 
-      case 19:
-        // Check for change-password popup, p-only login on u+p form.
-        // (needed a different subtest for this because the login created in
-        // test_0init was interfering)
-        is(gotUser, "",         "Checking submitted username");
-        is(gotPass, "pass2",    "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got notification popup");
-        clickPopupButton(popup, kChangeButton);
-        break;
+add_task(function* test_changeUPLoginOnUPForm_dont() {
+  info("Check for change-password popup, u+p login on u+p form. (not changed)");
+  Services.logins.addLogin(login1);
 
-      case 20:
-        // Check for change-password popup, p-only login on p-only form.
-        is(gotUser, "null",     "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got notification popup");
-        clickPopupButton(popup, kChangeButton);
-
-        pwmgr.removeLogin(login2);
-        break;
-
-      case 21:
-        // Check text on a user+pass notification popup
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        // Check the text, which comes from the localized saveLoginText string.
-        notificationText = popup.message;
-        expectedText = "Would you like " + brandShortName + " to remember this login?";
-        is(expectedText, notificationText, "Checking text: " + notificationText);
-        popup.remove();
-        break;
+  yield testSubmittingLoginForm("subtst_notifications_8.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "pass2", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "got notification popup");
+    clickDoorhangerButton(notif, DONT_CHANGE_BUTTON);
+  });
 
-      case 22:
-        // Check text on a user+pass notification popup, username is really long
-        is(gotUser, "nowisthetimeforallgoodmentocometotheaidoftheircountry", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        // Check the text, which comes from the localized saveLoginText string.
-        notificationText = popup.message;
-        expectedText = "Would you like " + brandShortName + " to remember this login\?";
-        is(expectedText, notificationText, "Checking text: " + notificationText);
-        popup.remove();
-        break;
-
-      case 23:
-        // Check text on a pass-only notification popup
-        is(gotUser, "null",     "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        // Check the text, which comes from the localized saveLoginTextNoUser string.
-        notificationText = popup.message;
-        expectedText = "Would you like " + brandShortName + " to remember this password\?";
-        is(expectedText, notificationText, "Checking text: " + notificationText);
-        popup.remove();
-        break;
-
-      case 24:
-        // Check for notification popup when a form with 2 password fields (no username) is
-        // submitted and there are no saved logins.
-        is(gotUser, "null", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-        popup.remove();
-
-        // Add login for the next test
-        pwmgr.addLogin(login1B);
-        break;
+  Services.logins.removeLogin(login1);
+});
 
-      case 25:
-        // Check for notification popup when a form with 2 password fields (no username) is
-        // submitted and there is a saved login with a username and different password.
-        is(gotUser, "null", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got notification popup");
-        popup.remove();
-        // remove that login
-        pwmgr.removeLogin(login1B);
-
-        // Add login for the next test
-        pwmgr.addLogin(login2B);
-        break;
-
-      case 26:
-        // Check for notification popup when a form with 2 password fields (no username) is
-        // submitted and there is a saved login with no username and a different password.
-        is(gotUser, "null", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(popup, "got notification popup");
-        popup.remove();
-        // remove that login
-        pwmgr.removeLogin(login2B);
-
-        // Add login for the next test
-        pwmgr.addLogin(login1);
-
-        break;
+add_task(function* test_changeUPLoginOnUPForm_change() {
+  info("Check for change-password popup, u+p login on u+p form.");
+  Services.logins.addLogin(login1);
 
-      case 27:
-        // Check for no notification popup when a form with 2 password fields (no username) is
-        // submitted and there is a saved login with a username and the same password.
-        is(gotUser, "null", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(!popup, "checking for no notification popup");
+  yield testSubmittingLoginForm("subtst_notifications_8.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "pass2", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "got notification popup");
+    clickDoorhangerButton(notif, CHANGE_BUTTON);
+    ok(!getCaptureDoorhanger("password-change"), "popup should be gone");
+  });
 
-        // Check to make sure we updated the timestamps and use count on the
-        // existing login that was submitted for this form.
-        var logins = pwmgr.getAllLogins();
-        is(logins.length, 1, "Should only have 1 login");
-        ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI");
-        is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission");
-        ok(logins[0].timeLastUsed > logins[0].timeCreated, "timeLastUsed bumped");
-        ok(logins[0].timeCreated == logins[0].timePasswordChanged, "timeChanged not updated");
-
-        // remove that login
-        pwmgr.removeLogin(login1);
-
-        // Add login for the next test
-        pwmgr.addLogin(login2);
-        break;
-
-      case 28:
-        // Check for no notification popup when a form with 2 password fields (no username) is
-        // submitted and there is a saved login with no username and the same password.
-        is(gotUser, "null", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-change");
-        ok(!popup, "checking for no notification popup");
+  checkOnlyLoginWasUsedTwice({ justChanged: true });
 
-        // Check to make sure we updated the timestamps and use count on the
-        // existing login that was submitted for this form.
-        var logins = pwmgr.getAllLogins();
-        is(logins.length, 1, "Should only have 1 login");
-        ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI");
-        is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission");
-        ok(logins[0].timeLastUsed > logins[0].timeCreated, "timeLastUsed bumped");
-        ok(logins[0].timeCreated == logins[0].timePasswordChanged, "timeChanged not updated");
-
-        // remove that login
-        pwmgr.removeLogin(login2);
-        break;
-
-      case 29: {
-        // Check that we capture the proper fields when a field recipe is in use.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(popup, "got notification popup");
-
-        // Sanity check, no logins should exist yet.
-        let logins = pwmgr.getAllLogins();
-        is(logins.length, 0, "Should not have any logins yet");
-
-        clickPopupButton(popup, kRememberButton);
-        break;
-      }
+  // cleanup
+  login1.password = "pass2";
+  Services.logins.removeLogin(login1);
+  login1.password = "notifyp1";
+});
 
-      case 30: {
-        // Same subtest, make sure we didn't prompt for an existing login.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
-
-        // Check to make sure we updated the timestamps and use count on the
-        // existing login that was submitted for this form.
-        let logins = pwmgr.getAllLogins();
-        is(logins.length, 1, "Should only have 1 login");
-        ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI");
-        is(logins[0].username, "notifyu1", "check .username for existing login submission");
-        is(logins[0].password, "notifyp1", "check .password for existing login submission");
-        is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission");
-        ok(logins[0].timeLastUsed > logins[0].timeCreated, "timeLastUsed bumped");
-        ok(logins[0].timeCreated == logins[0].timePasswordChanged, "timeChanged not updated");
-
-        // remove the added login
-        pwmgr.removeAllLogins();
-
-        // Add login for the next test
-        pwmgr.addLogin(login3);
-
-        break;
-      }
-
-      case 31: {
-        // make sure we didn't prompt for an existing login with different
-        // scheme for formSubmitURL.
-        is(gotUser, "notifyu1", "Checking submitted username");
-        is(gotPass, "notifyp1", "Checking submitted password");
-        popup = getPopup(popupNotifications, "password-save");
-        ok(!popup, "checking for no notification popup");
+add_task(function* test_changePLoginOnUPForm() {
+  info("Check for change-password popup, p-only login on u+p form.");
+  Services.logins.addLogin(login2);
 
-        // Check to make sure we updated the timestamps and use count on the
-        // existing login that was submitted for this form.
-        var logins = pwmgr.getAllLogins();
-        is(logins.length, 1, "Should only have 1 login");
-        ok(SpecialPowers.call_Instanceof(logins[0], Ci.nsILoginMetaInfo), "metainfo QI");
-        is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission");
-        ok(logins[0].timeLastUsed > logins[0].timeCreated, "timeLastUsed bumped");
-        ok(logins[0].timeCreated == logins[0].timePasswordChanged, "timeChanged not updated");
-
-        // remove that login
-        pwmgr.removeAllLogins();
-        break;
-      }
-      default:
-        ok(false, "Unexpected call to checkTest for test #" + testNum);
-
-    }
-
-    // TODO:
-    // * existing login test, form has different password --> change password, no save prompt
-}
-
-const Ci = SpecialPowers.Ci;
-const Cc = SpecialPowers.Cc;
-ok(Ci != null, "Access Ci");
-ok(Cc != null, "Access Cc");
-
-var pwmgr = Cc["@mozilla.org/login-manager;1"].
-            getService(Ci.nsILoginManager);
-ok(pwmgr != null, "Access pwmgr");
-
-pwmgr.removeAllLogins();
+  yield testSubmittingLoginForm("subtst_notifications_9.html", function*(fieldValues) {
+    is(fieldValues.username, "", "Checking submitted username");
+    is(fieldValues.password, "pass2", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "got notification popup");
+    clickDoorhangerButton(notif, CHANGE_BUTTON);
+    ok(!getCaptureDoorhanger("password-change"), "popup should be gone");
+  });
+});
 
-var prefs = Cc["@mozilla.org/preferences-service;1"].
-            getService(Ci.nsIPrefService);
-ok(prefs != null, "Access prefs");
-prefs = prefs.getBranch("signon.");
-ok(prefs != null, "Access pref branch");
-
-var nsLoginInfo = new SpecialPowers.wrap(SpecialPowers.Components).Constructor("@mozilla.org/login-manager/loginInfo;1",
-                                             Ci.nsILoginInfo, "init");
-var login1 = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
-                             "notifyu1", "notifyp1", "user", "pass");
-var login2 = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
-                             "", "notifyp1", "", "pass");
-var login1B = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
-                              "notifyu1B", "notifyp1B", "user", "pass");
-var login2B = new nsLoginInfo("http://mochi.test:8888", "http://mochi.test:8888", null,
-                              "", "notifyp1B", "", "pass");
-var login3 = new nsLoginInfo("http://mochi.test:8888", "https://mochi.test:8888", null,
-                             "notifyu1", "notifyp1", "user", "pass");
+add_task(function* test_changePLoginOnPForm() {
+  info("Check for change-password popup, p-only login on p-only form.");
 
-var parentScriptURL = SimpleTest.getTestFileURL("pwmgr_common.js");
-var mm = SpecialPowers.loadChromeScript(parentScriptURL);
-
-var iframe = document.getElementById("iframe");
-iframe.onload = handleLoad;
-
-// popupNotifications (not *popup*) is a constant, per-tab container. So, we
-// only need to fetch it once.
-var popupNotifications = getPopupNotifications(window.top);
-ok(popupNotifications, "Got popupNotifications");
-
-var testNum = 1;
-
-// Load recipes for this test.
-mm.sendAsyncMessage("loadRecipes", {
-  siteRecipes: [{
-    hosts: ["example.org"],
-    usernameSelector: "#user",
-    passwordSelector: "#pass",
-  }],
+  yield testSubmittingLoginForm("subtst_notifications_10.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "got notification popup");
+    clickDoorhangerButton(notif, CHANGE_BUTTON);
+    ok(!getCaptureDoorhanger("password-change"), "popup should be gone");
+  });
+  Services.logins.removeLogin(login2);
 });
 
-mm.addMessageListener("loadedRecipes", function loadedRecipes() {
-  ok(true, "Starting test #" + testNum);
-  iframe.src = subtests[testNum-1];
-})
+add_task(function* test_checkUPSaveText() {
+  info("Check text on a user+pass notification popup");
+
+  yield testSubmittingLoginForm("subtst_notifications_1.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    // Check the text, which comes from the localized saveLoginText string.
+    let notificationText = notif.message;
+    let expectedText = "Would you like " + BRAND_SHORT_NAME + " to remember this login?";
+    is(expectedText, notificationText, "Checking text: " + notificationText);
+    notif.remove();
+  });
+});
+
+add_task(function* test_checkPSaveText() {
+  info("Check text on a pass-only notification popup");
+
+  yield testSubmittingLoginForm("subtst_notifications_6.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    // Check the text, which comes from the localized saveLoginTextNoUser string.
+    let notificationText = notif.message;
+    let expectedText = "Would you like " + BRAND_SHORT_NAME + " to remember this password?";
+    is(expectedText, notificationText, "Checking text: " + notificationText);
+    notif.remove();
+  });
+});
+
+add_task(function* test_capture2pw0un() {
+  info("Check for notification popup when a form with 2 password fields (no username) " +
+       "is submitted and there are no saved logins.");
+
+  yield testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+    notif.remove();
+  });
+});
+
+add_task(function* test_change2pw0unExistingDifferentUP() {
+  info("Check for notification popup when a form with 2 password fields (no username) " +
+       "is submitted and there is a saved login with a username and different password.");
+
+  Services.logins.addLogin(login1B);
+
+  yield testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "got notification popup");
+    notif.remove();
+  });
+
+  Services.logins.removeLogin(login1B);
+});
+
+add_task(function* test_change2pw0unExistingDifferentP() {
+  info("Check for notification popup when a form with 2 password fields (no username) " +
+       "is submitted and there is a saved login with no username and different password.");
+
+  Services.logins.addLogin(login2B);
 
-SimpleTest.waitForExplicitFinish();
-</script>
-</pre>
-</body>
-</html>
+  yield testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(notif, "got notification popup");
+    notif.remove();
+  });
+
+  Services.logins.removeLogin(login2B);
+});
+
+add_task(function* test_change2pw0unExistingWithSameP() {
+  info("Check for no notification popup when a form with 2 password fields (no username) " +
+       "is submitted and there is a saved login with a username and the same password.");
+
+  Services.logins.addLogin(login2);
+
+  yield testSubmittingLoginForm("subtst_notifications_2pw_0un.html", function*(fieldValues) {
+    is(fieldValues.username, "null", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-change");
+    ok(!notif, "checking for no notification popup");
+  });
+
+  checkOnlyLoginWasUsedTwice({ justChanged: false });
+
+  Services.logins.removeLogin(login2);
+});
+
+add_task(function* test_recipeCaptureFields_NewLogin() {
+  info("Check that we capture the proper fields when a field recipe is in use.");
+
+  yield testSubmittingLoginForm("subtst_notifications_2pw_1un_1text.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(notif, "got notification popup");
+
+    // Sanity check, no logins should exist yet.
+    let logins = Services.logins.getAllLogins();
+    is(logins.length, 0, "Should not have any logins yet");
+
+    clickDoorhangerButton(notif, REMEMBER_BUTTON);
+  }, "http://example.org"); // The recipe is for example.org
+});
+
+add_task(function* test_recipeCaptureFields_ExistingLogin() {
+  info("Check that we capture the proper fields when a field recipe is in use " +
+       "and there is a matching login");
+
+  yield testSubmittingLoginForm("subtst_notifications_2pw_1un_1text.html", function*(fieldValues) {
+    is(fieldValues.username, "notifyu1", "Checking submitted username");
+    is(fieldValues.password, "notifyp1", "Checking submitted password");
+    let notif = getCaptureDoorhanger("password-save");
+    ok(!notif, "checking for no notification popup");
+  }, "http://example.org");
+
+  checkOnlyLoginWasUsedTwice({ justChanged: false });
+  let logins = Services.logins.getAllLogins();
+  is(logins[0].username, "notifyu1", "check .username for existing login submission");
+  is(logins[0].password, "notifyp1", "check .password for existing login submission");
+
+  Services.logins.removeAllLogins();
+});
+
+// TODO:
+// * existing login test, form has different password --> change password, no save prompt
--- a/toolkit/components/passwordmgr/test/browser/browser_context_menu.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_context_menu.js
@@ -1,16 +1,14 @@
 /*
  * Test the password manager context menu.
  */
 
 "use strict";
 
-Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
-
 // The hostname for the test URIs.
 const TEST_HOSTNAME = "https://example.com";
 const MULTIPLE_FORMS_PAGE_PATH = "/browser/toolkit/components/passwordmgr/test/browser/multiple_forms.html";
 
 /**
  * Initialize logins needed for the tests and disable autofill
  * for login forms for easier testing of manual fill.
  */
--- a/toolkit/components/passwordmgr/test/browser/browser_filldoorhanger.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_filldoorhanger.js
@@ -1,13 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
-
 /**
  * All these tests require the experimental login fill UI to be enabled. We also
  * disable autofill for login forms for easier testing of manual fill.
  */
 add_task(function* test_initialize() {
   Services.prefs.setBoolPref("signon.ui.experimental", true);
   Services.prefs.setBoolPref("signon.autofillForms", false);
   registerCleanupFunction(function () {
--- a/toolkit/components/passwordmgr/test/browser/browser_notifications.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_notifications.js
@@ -1,13 +1,9 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
 Cu.import("resource://testing-common/ContentTaskUtils.jsm", this);
-Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
 /**
  * Test that the doorhanger notification for password saving is populated with
  * the correct values in various password capture cases.
  */
 add_task(function* test_save_change() {
   let testCases = [{
     username: "username",
     password: "password",
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/browser/head.js
@@ -0,0 +1,118 @@
+const DIRECTORY_PATH = "/browser/toolkit/components/passwordmgr/test/browser/";
+
+Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
+
+registerCleanupFunction(function* cleanup_removeAllLoginsAndResetRecipes() {
+  Services.logins.removeAllLogins();
+  let recipeParent = LoginTestUtils.recipes.getRecipeParent();
+  if (!recipeParent) {
+    // No need to reset the recipes if the recipe module wasn't even loaded.
+    return;
+  }
+  yield recipeParent.then(recipeParent => recipeParent.reset());
+});
+
+/**
+ * Loads a test page in `DIRECTORY_URL` which automatically submits to formsubmit.sjs and returns a
+ * promise resolving with the field values when the optional `aTaskFn` is done.
+ *
+ * @param {String} aPageFile - test page file name which auto-submits to formsubmit.sjs
+ * @param {Function} aTaskFn - task which can be run before the tab closes.
+ * @param {String} [aOrigin="http://mochi.test:8888"] - origin of the server to
+ *                                                      use to load `aPageFile`.
+ */
+function testSubmittingLoginForm(aPageFile, aTaskFn, aOrigin = "http://mochi.test:8888") {
+  return BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: aOrigin + DIRECTORY_PATH + aPageFile,
+  }, function*(browser) {
+    ok(true, "loaded " + aPageFile);
+    let fieldValues = yield ContentTask.spawn(browser, undefined, function*() {
+      yield ContentTaskUtils.waitForCondition(() => {
+        return content.location.pathname.endsWith("/formsubmit.sjs") &&
+          content.document.readyState == "complete";
+      }, "Wait for form submission load (formsubmit.sjs)");
+      let username = content.document.getElementById("user").textContent;
+      let password = content.document.getElementById("pass").textContent;
+      return {
+        username,
+        password,
+      };
+    });
+    ok(true, "form submission loaded");
+    if (aTaskFn) {
+      yield* aTaskFn(fieldValues);
+    }
+    return fieldValues;
+  });
+}
+
+function checkOnlyLoginWasUsedTwice({ justChanged }) {
+  // Check to make sure we updated the timestamps and use count on the
+  // existing login that was submitted for the test.
+  let logins = Services.logins.getAllLogins();
+  is(logins.length, 1, "Should only have 1 login");
+  ok(logins[0] instanceof Ci.nsILoginMetaInfo, "metainfo QI");
+  is(logins[0].timesUsed, 2, "check .timesUsed for existing login submission");
+  ok(logins[0].timeCreated < logins[0].timeLastUsed, "timeLastUsed bumped");
+  if (justChanged) {
+    is(logins[0].timeLastUsed, logins[0].timePasswordChanged, "timeLastUsed == timePasswordChanged");
+  } else {
+    is(logins[0].timeCreated, logins[0].timePasswordChanged, "timeChanged not updated");
+  }
+}
+
+// Begin popup notification (doorhanger) functions //
+
+const REMEMBER_BUTTON = 0;
+const NEVER_BUTTON = 1;
+
+const CHANGE_BUTTON = 0;
+const DONT_CHANGE_BUTTON = 1;
+
+/**
+ * Checks if we have a password capture popup notification
+ * of the right type and with the right label.
+ *
+ * @param {String} aKind The desired `passwordNotificationType`
+ * @return the found password popup notification.
+ */
+function getCaptureDoorhanger(aKind) {
+  ok(true, "Looking for " + aKind + " popup notification");
+  let notification = PopupNotifications.getNotification("password");
+  if (notification) {
+    is(notification.options.passwordNotificationType, aKind, "Notification type matches.");
+    if (aKind == "password-change") {
+      is(notification.mainAction.label, "Update", "Main action label matches update doorhanger.");
+    } else if (aKind == "password-save") {
+      is(notification.mainAction.label, "Remember", "Main action label matches save doorhanger.");
+    }
+  }
+  return notification;
+}
+
+/**
+ * Clicks the specified popup notification button.
+ *
+ * @param {Element} aPopup Popup Notification element
+ * @param {Number} aButtonIndex Number indicating which button to click.
+ *                              See the constants in this file.
+ */
+function clickDoorhangerButton(aPopup, aButtonIndex) {
+  ok(true, "Looking for action at index " + aButtonIndex);
+
+  let notifications = aPopup.owner.panel.childNodes;
+  ok(notifications.length > 0, "at least one notification displayed");
+  ok(true, notifications.length + " notification(s)");
+  let notification = notifications[0];
+
+  if (aButtonIndex == 0) {
+    ok(true, "Triggering main action");
+    notification.button.doCommand();
+  } else if (aButtonIndex <= aPopup.secondaryActions.length) {
+    ok(true, "Triggering secondary action " + aButtonIndex);
+    notification.childNodes[aButtonIndex].doCommand();
+  }
+}
+
+// End popup notification (doorhanger) functions //
--- a/toolkit/components/passwordmgr/test/mochitest.ini
+++ b/toolkit/components/passwordmgr/test/mochitest.ini
@@ -4,30 +4,18 @@ support-files =
   authenticate.sjs
   blank.html
   formsubmit.sjs
   notification_common.js
   privbrowsing_perwindowpb_iframe.html
   prompt_common.js
   pwmgr_common.js
   subtst_master_pass.html
-  subtst_notifications_1.html
-  subtst_notifications_10.html
   subtst_notifications_11.html
   subtst_notifications_11_popup.html
-  subtst_notifications_2.html
-  subtst_notifications_2pw_0un.html
-  subtst_notifications_2pw_1un_1text.html
-  subtst_notifications_3.html
-  subtst_notifications_4.html
-  subtst_notifications_5.html
-  subtst_notifications_6.html
-  subtst_notifications_7.html
-  subtst_notifications_8.html
-  subtst_notifications_9.html
   subtst_privbrowsing_1.html
   subtst_privbrowsing_2.html
   subtst_privbrowsing_3.html
   subtst_privbrowsing_4.html
   subtst_prompt_async.html
 
 [test_basic_form_2pw_2.html]
 [test_basic_form_autocomplete.html]
@@ -35,18 +23,16 @@ skip-if = toolkit == 'android'
 [test_case_differences.html]
 skip-if = toolkit == 'android'
 [test_bug_627616.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_master_password.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_master_password_cleanup.html]
 skip-if = toolkit == 'android'
-[test_notifications.html]
-skip-if = toolkit == 'android'
 [test_notifications_popup.html]
 skip-if = os == "linux" || toolkit == 'android' # bug 934057
 [test_prompt.html]
 skip-if = os == "linux" || toolkit == 'android' #TIMED_OUT
 [test_prompt_async.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_xhr.html]
 skip-if = toolkit == 'android' #TIMED_OUT
--- a/toolkit/components/passwordmgr/test/notification_common.js
+++ b/toolkit/components/passwordmgr/test/notification_common.js
@@ -32,16 +32,17 @@ function getPopupNotifications(aWindow) 
     return popupNotifications;
 }
 
 
 /**
  * Checks if we have a password popup notification
  * of the right type and with the right label.
  *
+ * @deprecated Write a browser-chrome test instead and use the fork of this method there.
  * @returns the found password popup notification.
  */
 function getPopup(aPopupNote, aKind) {
     ok(true, "Looking for " + aKind + " popup notification");
     var notification = aPopupNote.getNotification("password");
     if (notification) {
       is(notification.options.passwordNotificationType, aKind, "Notification type matches.");
       if (aKind == "password-change") {
@@ -49,18 +50,18 @@ function getPopup(aPopupNote, aKind) {
       } else if (aKind == "password-save") {
         is(notification.mainAction.label, "Remember", "Main action label matches save doorhanger.");
       }
     }
     return notification;
 }
 
 
-/*
- * clickPopupButton
+/**
+ * @deprecated - Use a browser chrome test instead.
  *
  * Clicks the specified popup notification button.
  */
 function clickPopupButton(aPopup, aButtonIndex) {
     ok(true, "Looking for action at index " + aButtonIndex);
 
     var notifications = SpecialPowers.wrap(aPopup.owner).panel.childNodes;
     ok(notifications.length > 0, "at least one notification displayed");
deleted file mode 100644
--- a/toolkit/components/passwordmgr/test/subtst_notifications_7.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  <title>Subtest for Login Manager notifications</title>
-</head>
-<body>
-<h2>Subtest 7</h2>
-<form id="form" action="formsubmit.sjs">
-  <input id="user" name="user">
-  <input id="pass" name="pass" type="password">
-  <button type='submit'>Submit</button>
-</form>
-
-<script>
-function submitForm() {
-  userField.value = "nowisthetimeforallgoodmentocometotheaidoftheircountry";
-  passField.value = "notifyp1";
-  form.submit();
-}
-
-window.onload = submitForm;
-var form      = document.getElementById("form");
-var userField = document.getElementById("user");
-var passField = document.getElementById("pass");
-
-</script>
-</body>
-</html>