Bug 1388674 - Update tests to use setUserInput, ensuring we get an input event for field modifications. r=MattN
☠☠ backed out by dbb0fff9e65c ☠ ☠
authorSam Foster <sfoster@mozilla.com>
Mon, 18 Nov 2019 23:55:19 +0000
changeset 502516 5caf9e9337388ac29a786e9600a6af240bb00275
parent 502515 ee452cb16fac66c1f5011cef8435f7e2b3e83502
child 502517 09e3e82fb4396ae250cc5e92c7af8447ff5a5683
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMattN
bugs1388674
milestone72.0a1
Bug 1388674 - Update tests to use setUserInput, ensuring we get an input event for field modifications. r=MattN Differential Revision: https://phabricator.services.mozilla.com/D51718
toolkit/components/passwordmgr/test/browser/browser_doorhanger_crossframe.js
toolkit/components/passwordmgr/test/browser/browser_doorhanger_dismissed_for_ccnumber.js
toolkit/components/passwordmgr/test/browser/browser_doorhanger_empty_password.js
toolkit/components/passwordmgr/test/browser/browser_doorhanger_password_edits.js
toolkit/components/passwordmgr/test/browser/browser_doorhanger_save_password.js
toolkit/components/passwordmgr/test/browser/browser_doorhanger_toggles.js
toolkit/components/passwordmgr/test/browser/browser_doorhanger_username_edits.js
toolkit/components/passwordmgr/test/browser/browser_formless_submit_chrome.js
toolkit/components/passwordmgr/test/browser/head.js
toolkit/components/passwordmgr/test/browser/subtst_notifications_1.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_10.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_11_popup.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_2.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_2pw_0un.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_2pw_1un_1text.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_3.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_4.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_5.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_6.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_8.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_9.html
toolkit/components/passwordmgr/test/browser/subtst_notifications_change_p.html
toolkit/components/passwordmgr/test/mochitest/pwmgr_common.js
toolkit/components/passwordmgr/test/mochitest/test_basic_form_2pw_2.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
toolkit/components/passwordmgr/test/mochitest/test_munged_username.html
toolkit/components/passwordmgr/test/mochitest/test_one_doorhanger_per_un_pw.html
toolkit/components/passwordmgr/test/mochitest/test_onsubmit_value_change.html
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_crossframe.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_crossframe.js
@@ -91,24 +91,24 @@ async function submitSomeCrossSiteFrames
 
   // Fill in the username and password for both the outer and inner frame
   // and submit the inner frame.
   notifyPromise = listenForNotifications(1);
   info("submit page after changing inner form");
 
   await SpecialPowers.spawn(outerFrameBC, [], () => {
     let doc = content.document;
-    doc.getElementById("outer-username").value = "outer";
-    doc.getElementById("outer-password").value = "outerpass";
+    doc.getElementById("outer-username").setUserInput("outer");
+    doc.getElementById("outer-password").setUserInput("outerpass");
   });
 
   await SpecialPowers.spawn(innerFrameBC, [locationMode], doClick => {
     let doc = content.document;
-    doc.getElementById("inner-username").value = "inner";
-    doc.getElementById("inner-password").value = "innerpass";
+    doc.getElementById("inner-username").setUserInput("inner");
+    doc.getElementById("inner-password").setUserInput("innerpass");
     if (doClick) {
       doc.getElementById("inner-gobutton").click();
     } else {
       doc.getElementById("inner-form").submit();
     }
   });
 
   await acceptPasswordSave();
@@ -133,18 +133,18 @@ async function submitSomeCrossSiteFrames
   await checkFormFields(innerFrameBC2, "inner", "inner", "innerpass");
 
   // Next, change the username and password fields in the outer frame and submit.
   notifyPromise = listenForNotifications(1);
   info("submit page after changing outer form");
 
   await SpecialPowers.spawn(outerFrameBC2, [locationMode], doClick => {
     let doc = content.document;
-    doc.getElementById("outer-username").value = "outer2";
-    doc.getElementById("outer-password").value = "outerpass2";
+    doc.getElementById("outer-username").setUserInput("outer2");
+    doc.getElementById("outer-password").setUserInput("outerpass2");
     if (doClick) {
       doc.getElementById("outer-gobutton").click();
     } else {
       doc.getElementById("outer-form").submit();
     }
 
     doc.getElementById("outer-form").submit();
   });
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_dismissed_for_ccnumber.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_dismissed_for_ccnumber.js
@@ -80,20 +80,22 @@ add_task(async function test_doorhanger_
       url,
     },
     async function test_un_with_invalid_cc_number(browser) {
       // If the username field has a CC number that is invalid,
       // we show the doorhanger to save logins like we usually do.
 
       let processedPromise = listenForTestNotification("FormSubmit");
       await ContentTask.spawn(browser, null, async () => {
-        content.document.getElementById("form-basic-username").value =
-          "1234123412341234";
-        content.document.getElementById("form-basic-password").value = "411";
-
+        content.document
+          .getElementById("form-basic-username")
+          .setUserInput("1234123412341234");
+        content.document
+          .getElementById("form-basic-password")
+          .setUserInput("411");
         content.document.getElementById("form-basic-submit").click();
       });
       await processedPromise;
 
       let notif = await getCaptureDoorhangerThatMayOpen("password-save");
       ok(notif, "got notification popup");
       ok(
         !notif.dismissed,
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_empty_password.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_empty_password.js
@@ -17,18 +17,18 @@ add_task(async function test_empty_passw
       url:
         "https://example.com/browser/toolkit/components/passwordmgr/test/browser/form_basic.html",
     },
     async function(browser) {
       // Submit the form in the content page with the credentials from the test
       // case. This will cause the doorhanger notification to be displayed.
       await ContentTask.spawn(browser, null, async function() {
         let doc = content.document;
-        doc.getElementById("form-basic-username").value = "username";
-        doc.getElementById("form-basic-password").value = "pw";
+        doc.getElementById("form-basic-username").setUserInput("username");
+        doc.getElementById("form-basic-password").setUserInput("pw");
         doc.getElementById("form-basic").submit();
       });
 
       await waitForDoorhanger(browser, "password-save");
       // Synthesize input to empty the field
       await updateDoorhangerInputValues({
         password: "",
       });
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_password_edits.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_password_edits.js
@@ -9,47 +9,55 @@
  *   - Editing username to an empty one and a new password.
  *
  * If both the username and password matches an already existing login, we should not
  * update it's password, but only it's usage timestamp and count.
  */
 add_task(async function test_edit_password() {
   let testCases = [
     {
+      description: "No saved logins, update password in doorhanger",
       usernameInPage: "username",
       passwordInPage: "password",
       passwordChangedTo: "newPassword",
       timesUsed: 1,
     },
     {
+      description: "Login is saved, update password in doorhanger",
       usernameInPage: "username",
       usernameInPageExists: true,
       passwordInPage: "password",
       passwordInStorage: "oldPassword",
       passwordChangedTo: "newPassword",
       timesUsed: 2,
     },
     {
+      description:
+        "Change username in doorhanger to match saved login, update password in doorhanger",
       usernameInPage: "username",
       usernameChangedTo: "newUsername",
       usernameChangedToExists: true,
       passwordInPage: "password",
       passwordChangedTo: "newPassword",
       timesUsed: 2,
     },
     {
+      description:
+        "Change username in doorhanger to match saved login, dont update password in doorhanger",
       usernameInPage: "username",
       usernameChangedTo: "newUsername",
       usernameChangedToExists: true,
       passwordInPage: "password",
       passwordChangedTo: "password",
       timesUsed: 2,
       checkPasswordNotUpdated: true,
     },
     {
+      description:
+        "Change username and password in doorhanger to match saved empty-username login",
       usernameInPage: "newUsername",
       usernameChangedTo: "",
       usernameChangedToExists: true,
       passwordInPage: "password",
       passwordChangedTo: "newPassword",
       timesUsed: 2,
     },
   ];
@@ -94,41 +102,32 @@ add_task(async function test_edit_passwo
           PopupNotifications.panel,
           "popupshown",
           event => event.target == PopupNotifications.panel
         );
         await ContentTask.spawn(browser, testCase, async function(
           contentTestCase
         ) {
           let doc = content.document;
-          doc.getElementById("form-basic-username").value =
-            contentTestCase.usernameInPage;
-          doc.getElementById("form-basic-password").value =
-            contentTestCase.passwordInPage;
+          doc
+            .getElementById("form-basic-username")
+            .setUserInput(contentTestCase.usernameInPage);
+          doc
+            .getElementById("form-basic-password")
+            .setUserInput(contentTestCase.passwordInPage);
           doc.getElementById("form-basic").submit();
         });
         await promiseShown;
         let notificationElement = PopupNotifications.panel.childNodes[0];
-        // Style flush to make sure binding is attached
-        notificationElement.querySelector("#password-notification-password")
-          .clientTop;
 
-        // Modify the username in the dialog if requested.
-        if (testCase.usernameChangedTo) {
-          notificationElement.querySelector(
-            "#password-notification-username"
-          ).value = testCase.usernameChangedTo;
-        }
-
-        // Modify the password in the dialog if requested.
-        if (testCase.passwordChangedTo) {
-          notificationElement.querySelector(
-            "#password-notification-password"
-          ).value = testCase.passwordChangedTo;
-        }
+        // Modify the username & password in the dialog if requested.
+        await updateDoorhangerInputValues({
+          username: testCase.usernameChangedTo,
+          password: testCase.passwordChangedTo,
+        });
 
         // We expect a modifyLogin notification if the final username used by the
         // dialog exists in the logins database, otherwise an addLogin one.
         let expectModifyLogin =
           typeof testCase.usernameChangedTo !== "undefined"
             ? testCase.usernameChangedToExists
             : testCase.usernameInPageExists;
 
@@ -137,42 +136,52 @@ add_task(async function test_edit_passwo
         // of operation we expect.
         let expectedNotification = expectModifyLogin
           ? "modifyLogin"
           : "addLogin";
         let promiseLogin = TestUtils.topicObserved(
           "passwordmgr-storage-changed",
           (_, data) => data == expectedNotification
         );
+
+        let promiseHidden = BrowserTestUtils.waitForEvent(
+          PopupNotifications.panel,
+          "popuphidden"
+        );
         notificationElement.button.doCommand();
+
         let [result] = await promiseLogin;
+        await promiseHidden;
 
         // Check that the values in the database match the expected values.
         let login = expectModifyLogin
           ? result
               .QueryInterface(Ci.nsIArray)
               .queryElementAt(1, Ci.nsILoginInfo)
           : result.QueryInterface(Ci.nsILoginInfo);
+        let meta = login.QueryInterface(Ci.nsILoginMetaInfo);
 
-        Assert.equal(
-          login.username,
-          testCase.usernameChangedTo || testCase.usernameInPage
-        );
-        Assert.equal(
-          login.password,
-          testCase.passwordChangedTo || testCase.passwordInPage
-        );
-
-        let meta = login.QueryInterface(Ci.nsILoginMetaInfo);
-        Assert.equal(meta.timesUsed, testCase.timesUsed);
-
+        let expectedLogin = {
+          username:
+            "usernameChangedTo" in testCase
+              ? testCase.usernameChangedTo
+              : testCase.usernameInPage,
+          password:
+            "passwordChangedTo" in testCase
+              ? testCase.passwordChangedTo
+              : testCase.passwordInPage,
+          timesUsed: testCase.timesUsed,
+        };
         // Check that the password was not updated if the user is empty
         if (testCase.checkPasswordNotUpdated) {
-          Assert.ok(meta.timeLastUsed > meta.timeCreated);
-          Assert.ok(meta.timeCreated == meta.timePasswordChanged);
+          expectedLogin.usedSince = meta.timeCreated;
+          expectedLogin.timeCreated = meta.timePasswordChanged;
         }
+        verifyLogins([expectedLogin]);
+
+        await cleanupDoorhanger();
       }
     );
 
     // Clean up the database before the next test case is executed.
     Services.logins.removeAllLogins();
   }
 });
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_save_password.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_save_password.js
@@ -88,65 +88,58 @@ add_task(async function test_save_change
         gBrowser,
         url:
           "https://example.com/browser/toolkit/components/" +
           "passwordmgr/test/browser/form_basic.html",
       },
       async function(browser) {
         // Submit the form in the content page with the credentials from the test
         // case. This will cause the doorhanger notification to be displayed.
-        let promiseShown = BrowserTestUtils.waitForEvent(
-          PopupNotifications.panel,
-          "popupshown",
-          event => event.target == PopupNotifications.panel
-        );
         await ContentTask.spawn(browser, [username, password], async function([
           contentUsername,
           contentPassword,
         ]) {
           let doc = content.document;
-          doc.getElementById("form-basic-username").value = contentUsername;
-          doc.getElementById("form-basic-password").value = contentPassword;
+          doc
+            .getElementById("form-basic-username")
+            .setUserInput(contentUsername);
+          doc
+            .getElementById("form-basic-password")
+            .setUserInput(contentPassword);
           doc.getElementById("form-basic").submit();
         });
-        await promiseShown;
-        let notif = PopupNotifications.getNotification("password", browser);
-        let notificationElement = PopupNotifications.panel.childNodes[0];
-        // Style flush to make sure binding is attached
-        notificationElement.querySelector("#password-notification-password")
-          .clientTop;
-
-        // Check the actual content of the popup notification.
-        Assert.equal(
-          notificationElement.querySelector("#password-notification-username")
-            .value,
-          username
-        );
-        Assert.equal(
-          notificationElement.querySelector("#password-notification-password")
-            .value,
-          password
-        );
 
         // Simulate the action on the notification to request the login to be
         // saved, and wait for the data to be updated or saved based on the type
         // of operation we expect.
-        let expectedNotification;
+        let expectedNotification, expectedDoorhanger;
         if (oldPassword !== undefined && oldUsername !== undefined) {
           expectedNotification = "addLogin";
+          expectedDoorhanger = "password-save";
         } else if (oldPassword !== undefined) {
           expectedNotification = "modifyLogin";
+          expectedDoorhanger = "password-change";
         } else {
           expectedNotification = "addLogin";
+          expectedDoorhanger = "password-save";
         }
+
+        let notif = getCaptureDoorhanger(
+          expectedDoorhanger,
+          PopupNotifications,
+          browser
+        );
+        // Check the actual content of the popup notification.
+        await checkDoorhangerUsernamePassword(username, password);
+
         let promiseLogin = TestUtils.topicObserved(
           "passwordmgr-storage-changed",
           (_, data) => data == expectedNotification
         );
-        notificationElement.button.doCommand();
+        await clickDoorhangerButton(notif, REMEMBER_BUTTON);
         await promiseLogin;
         await cleanupDoorhanger(notif); // clean slate for the next test
 
         // Check that the values in the database match the expected values.
         verifyLogins(expectOutcome);
       }
     );
 
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_toggles.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_toggles.js
@@ -13,28 +13,24 @@ add_task(async function test_toggle_pass
     {
       gBrowser,
       url:
         "https://example.com/browser/toolkit/components/passwordmgr/test/browser/form_basic.html",
     },
     async function(browser) {
       // Submit the form in the content page with the credentials from the test
       // case. This will cause the doorhanger notification to be displayed.
-      let promiseShown = BrowserTestUtils.waitForEvent(
-        PopupNotifications.panel,
-        "popupshown",
-        event => event.target == PopupNotifications.panel
-      );
       await ContentTask.spawn(browser, null, async function() {
         let doc = content.document;
-        doc.getElementById("form-basic-username").value = "username";
-        doc.getElementById("form-basic-password").value = "pw";
+        doc.getElementById("form-basic-username").setUserInput("username");
+        doc.getElementById("form-basic-password").setUserInput("pw");
         doc.getElementById("form-basic").submit();
       });
-      await promiseShown;
+      // Check the actual content of the popup notification.
+      await checkDoorhangerUsernamePassword("username", "pw");
 
       let notificationElement = PopupNotifications.panel.childNodes[0];
       let passwordTextbox = notificationElement.querySelector(
         "#password-notification-password"
       );
       let toggleCheckbox = notificationElement.querySelector(
         "#password-notification-visibilityToggle"
       );
@@ -67,31 +63,26 @@ add_task(async function test_checkbox_di
     {
       gBrowser,
       url:
         "https://example.com/browser/toolkit/components/passwordmgr/test/browser/form_basic.html",
     },
     async function(browser) {
       // Submit the form in the content page with the credentials from the test
       // case. This will cause the doorhanger notification to be displayed.
-      let promiseShown = BrowserTestUtils.waitForEvent(
-        PopupNotifications.panel,
-        "popupshown",
-        event => event.target == PopupNotifications.panel
-      );
-
       LoginTestUtils.masterPassword.enable();
 
       await ContentTask.spawn(browser, null, async function() {
         let doc = content.document;
-        doc.getElementById("form-basic-username").value = "username";
-        doc.getElementById("form-basic-password").value = "pass";
+        doc.getElementById("form-basic-username").setUserInput("username");
+        doc.getElementById("form-basic-password").setUserInput("pass");
         doc.getElementById("form-basic").submit();
       });
-      await promiseShown;
+      // Check the actual content of the popup notification.
+      await checkDoorhangerUsernamePassword("username", "pass");
 
       let notificationElement = PopupNotifications.panel.childNodes[0];
       let passwordTextbox = notificationElement.querySelector(
         "#password-notification-password"
       );
       let toggleCheckbox = notificationElement.querySelector(
         "#password-notification-visibilityToggle"
       );
--- a/toolkit/components/passwordmgr/test/browser/browser_doorhanger_username_edits.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_doorhanger_username_edits.js
@@ -89,32 +89,34 @@ add_task(async function test_edit_userna
           "popupshown",
           event => event.target == PopupNotifications.panel
         );
         await ContentTask.spawn(
           browser,
           testCase.usernameInPage,
           async function(usernameInPage) {
             let doc = content.document;
-            doc.getElementById("form-basic-username").value = usernameInPage;
-            doc.getElementById("form-basic-password").value = "password";
+            doc
+              .getElementById("form-basic-username")
+              .setUserInput(usernameInPage);
+            doc.getElementById("form-basic-password").setUserInput("password");
             doc.getElementById("form-basic").submit();
           }
         );
         await promiseShown;
         let notificationElement = PopupNotifications.panel.childNodes[0];
         // Style flush to make sure binding is attached
         notificationElement.querySelector("#password-notification-password")
           .clientTop;
 
         // Modify the username in the dialog if requested.
         if (testCase.usernameChangedTo) {
-          notificationElement.querySelector(
-            "#password-notification-username"
-          ).value = testCase.usernameChangedTo;
+          await updateDoorhangerInputValues({
+            username: testCase.usernameChangedTo,
+          });
         }
 
         // We expect a modifyLogin notification if the final username used by the
         // dialog exists in the logins database, otherwise an addLogin one.
         let expectModifyLogin = testCase.usernameChangedTo
           ? testCase.usernameChangedToExists
           : testCase.usernameInPageExists;
 
@@ -123,18 +125,23 @@ add_task(async function test_edit_userna
         // of operation we expect.
         let expectedNotification = expectModifyLogin
           ? "modifyLogin"
           : "addLogin";
         let promiseLogin = TestUtils.topicObserved(
           "passwordmgr-storage-changed",
           (_, data) => data == expectedNotification
         );
+        let promiseHidden = BrowserTestUtils.waitForEvent(
+          PopupNotifications.panel,
+          "popuphidden"
+        );
         notificationElement.button.doCommand();
         let [result] = await promiseLogin;
+        await promiseHidden;
 
         // Check that the values in the database match the expected values.
         let login = expectModifyLogin
           ? result
               .QueryInterface(Ci.nsIArray)
               .queryElementAt(1, Ci.nsILoginInfo)
           : result.QueryInterface(Ci.nsILoginInfo);
         Assert.equal(
--- a/toolkit/components/passwordmgr/test/browser/browser_formless_submit_chrome.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_formless_submit_chrome.js
@@ -1,20 +1,22 @@
 /*
  * Test that browser chrome UI interactions don't trigger a capture doorhanger.
  */
 
 "use strict";
 
 async function fillTestPage(aBrowser) {
   await ContentTask.spawn(aBrowser, null, async function() {
-    content.document.getElementById("form-basic-username").value =
-      "my_username";
-    content.document.getElementById("form-basic-password").value =
-      "my_password";
+    content.document
+      .getElementById("form-basic-username")
+      .setUserInput("my_username");
+    content.document
+      .getElementById("form-basic-password")
+      .setUserInput("my_password");
   });
   info("fields filled");
 }
 
 function withTestPage(aTaskFn) {
   return BrowserTestUtils.withNewTab(
     {
       gBrowser,
--- a/toolkit/components/passwordmgr/test/browser/head.js
+++ b/toolkit/components/passwordmgr/test/browser/head.js
@@ -83,16 +83,19 @@ function verifyLogins(expectedLogins = [
         ok(login.timeLastUsed > expected.usedSince, "Check timeLastUsed");
       }
       if (typeof expected.passwordChangedSince !== "undefined") {
         ok(
           login.timePasswordChanged > expected.passwordChangedSince,
           "Check timePasswordChanged"
         );
       }
+      if (typeof expected.timeCreated !== "undefined") {
+        is(login.timeCreated, expected.timeCreated, "Check timeCreated");
+      }
     }
   }
   return allLogins;
 }
 
 /**
  * Submit the content form and return a promise resolving to the username and
  * password values echoed out in the response
@@ -103,27 +106,42 @@ function verifyLogins(expectedLogins = [
  * @param {Object = null} responseSelectors - Optional object with selectors to find the username and password in the response
  */
 async function submitFormAndGetResults(
   browser,
   formAction = "",
   selectorValues,
   responseSelectors
 ) {
-  function contentSubmitForm([contentFormAction, contentSelectorValues]) {
+  async function contentSubmitForm([contentFormAction, contentSelectorValues]) {
+    const { WrapPrivileged } = ChromeUtils.import(
+      "resource://specialpowers/WrapPrivileged.jsm",
+      this
+    );
     let doc = content.document;
     let form = doc.querySelector("form");
     if (contentFormAction) {
       form.action = contentFormAction;
     }
     for (let [sel, value] of Object.entries(contentSelectorValues)) {
       try {
-        doc.querySelector(sel).setUserInput(value);
+        let field = doc.querySelector(sel);
+        let gotInput = ContentTaskUtils.waitForEvent(
+          field,
+          "input",
+          "Got input event on " + sel
+        );
+        // we don't get an input event if the new value == the old
+        field.value = "###";
+        WrapPrivileged.wrap(field).setUserInput(value);
+        await gotInput;
       } catch (ex) {
-        throw new Error(`submitForm: Couldn't set value of field at: ${sel}`);
+        throw new Error(
+          `submitForm: Couldn't set value of field at: ${sel}: ${ex.message}`
+        );
       }
     }
     form.submit();
   }
   await ContentTask.spawn(
     browser,
     [formAction, selectorValues],
     contentSubmitForm
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_1.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_1.html
@@ -9,18 +9,18 @@
 <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 = "notifyu1";
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_10.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_10.html
@@ -8,17 +8,17 @@
 <h2>Subtest 10</h2>
 <form id="form" action="formsubmit.sjs">
   <input id="pass" name="pass" type="password">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_11_popup.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_11_popup.html
@@ -11,18 +11,18 @@
   <input id="pass" name="pass" type="password">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
   // Get the password from the query string (exclude '?').
   let [username, password] = window.location.search.substring(1).split("|");
-  userField.value = username;
-  passField.value = password;
+  SpecialPowers.wrap(userField).setUserInput(username);
+  SpecialPowers.wrap(passField).setUserInput(password);
   form.submit();
   window.opener.formSubmitted();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_2.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_2.html
@@ -10,18 +10,18 @@
 <form id="form" action="formsubmit.sjs">
   <input id="user" name="user" autocomplete="off">
   <input id="pass" name="pass" type="password">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  userField.value = "notifyu1";
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_2pw_0un.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_2pw_0un.html
@@ -9,17 +9,17 @@
 <form id="form" action="formsubmit.sjs">
   <input id="pass1" name="pass1" type="password" value="staticpw">
   <input id="pass" name="pass" type="password">
   <button type="submit">Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  pass.value = "notifyp1";
+  SpecialPowers.wrap(pass).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var pass      = document.getElementById("pass");
 
 </script>
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_2pw_1un_1text.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_2pw_1un_1text.html
@@ -11,18 +11,18 @@
   <input id="city"  name="city"  value="city">
   <input id="pass"  name="pass"  type="password">
   <input id="pin"   name="pin"   type="password" value="static-pin">
   <button type="submit">Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  userField.value = "notifyu1";
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_3.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_3.html
@@ -10,18 +10,18 @@
 <form id="form" action="formsubmit.sjs">
   <input id="user" name="user">
   <input id="pass" name="pass" type="password" autocomplete="off">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  userField.value = "notifyu1";
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_4.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_4.html
@@ -10,18 +10,18 @@
 <form id="form" action="formsubmit.sjs" autocomplete="off">
   <input id="user" name="user">
   <input id="pass" name="pass" type="password">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  userField.value = "notifyu1";
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_5.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_5.html
@@ -8,17 +8,17 @@
 <h2>Subtest 5</h2>
 <form id="form" action="formsubmit.sjs">
   <input id="user" name="user">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  userField.value = "notifyu1";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 
 </script>
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_6.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_6.html
@@ -9,17 +9,17 @@
 (password-only form)
 <form id="form" action="formsubmit.sjs">
   <input id="pass" name="pass" type="password">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  passField.value = "notifyp1";
+  SpecialPowers.wrap(passField).setUserInput("notifyp1");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var passField = document.getElementById("pass");
 
 </script>
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_8.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_8.html
@@ -9,18 +9,18 @@
 <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 = "notifyu1";
-  passField.value = "pass2";
+  SpecialPowers.wrap(userField).setUserInput("notifyu1");
+  SpecialPowers.wrap(passField).setUserInput("pass2");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_9.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_9.html
@@ -9,18 +9,18 @@
 <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 = "";
-  passField.value = "pass2";
+  SpecialPowers.wrap(userField).setUserInput("");
+  SpecialPowers.wrap(passField).setUserInput("pass2");
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
 
--- a/toolkit/components/passwordmgr/test/browser/subtst_notifications_change_p.html
+++ b/toolkit/components/passwordmgr/test/browser/subtst_notifications_change_p.html
@@ -10,18 +10,18 @@
   <input id="pass_current" name="pass_current" type="password" value="notifyp1">
   <input id="pass" name="pass" type="password">
   <input id="pass_confirm" name="pass_confirm" type="password">
   <button type='submit'>Submit</button>
 </form>
 
 <script>
 function submitForm() {
-  passField.value = "pass2";
-  passConfirmField.value = "pass2";
+  SpecialPowers.wrap(passField).setUserInput("pass2");
+  SpecialPowers.wrap(passConfirmField).setUserInput("pass2");
 
   form.submit();
 }
 
 window.onload = submitForm;
 var form      = document.getElementById("form");
 var userField = document.getElementById("user");
 var passField = document.getElementById("pass");
--- a/toolkit/components/passwordmgr/test/mochitest/pwmgr_common.js
+++ b/toolkit/components/passwordmgr/test/mochitest/pwmgr_common.js
@@ -109,16 +109,67 @@ function checkAutoCompleteResults(actual
 }
 
 function getIframeBrowsingContext(window, iframeNumber = 0) {
   let bc = SpecialPowers.wrap(window).getWindowGlobalChild().browsingContext;
   return SpecialPowers.unwrap(bc.getChildren()[iframeNumber]);
 }
 
 /**
+ * Set input values via setUserInput to emulate user input
+ * and distinguish them from declarative or script-assigned values
+ */
+function setUserInputValues(parentNode, selectorValues) {
+  for (let [selector, newValue] of Object.entries(selectorValues)) {
+    info(`setUserInputValues, selector: ${selector}`);
+    try {
+      let field = SpecialPowers.wrap(parentNode.querySelector(selector));
+      if (field.value == newValue) {
+        // we don't get an input event if the new value == the old
+        field.value += "#";
+      }
+      field.setUserInput(newValue);
+    } catch (ex) {
+      info(ex.message);
+      info(ex.stack);
+      ok(
+        false,
+        `setUserInputValues: Couldn't set value of field: ${ex.message}`
+      );
+    }
+  }
+}
+
+/**
+ * @param {Function} [aFilterFn = undefined] Function to filter out irrelevant submissions.
+ * @return {Promise} resolving when a relevant form submission was processed.
+ */
+function getSubmitMessage(aFilterFn = undefined) {
+  info("getSubmitMessage");
+  return new Promise((resolve, reject) => {
+    PWMGR_COMMON_PARENT.addMessageListener(
+      "formSubmissionProcessed",
+      function processed(...args) {
+        if (aFilterFn && !aFilterFn(...args)) {
+          // This submission isn't the one we're waiting for.
+          return;
+        }
+
+        info("got formSubmissionProcessed");
+        PWMGR_COMMON_PARENT.removeMessageListener(
+          "formSubmissionProcessed",
+          processed
+        );
+        resolve(...args);
+      }
+    );
+  });
+}
+
+/**
  * Check for expected username/password in form.
  * @see `checkForm` below for a similar function.
  */
 function checkLoginForm(
   usernameField,
   expectedUsername,
   passwordField,
   expectedPassword
--- a/toolkit/components/passwordmgr/test/mochitest/test_basic_form_2pw_2.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_basic_form_2pw_2.html
@@ -31,19 +31,19 @@ var numStartingLogins = 0;
 function startTest() {
   // Check for unfilled forms
   is($_(1, "uname").value, "", "Checking username 1");
   is($_(1, "pword").value, "", "Checking password 1A");
   is($_(1, "qword").value, "", "Checking password 1B");
 
   // Fill in the username and password fields, for account creation.
   // Form 1
-  $_(1, "uname").value = "newuser1";
-  $_(1, "pword").value = "newpass1";
-  $_(1, "qword").value = "newpass1";
+  SpecialPowers.wrap($_(1, "uname")).setUserInput("newuser1");
+  SpecialPowers.wrap($_(1, "pword")).setUserInput("newpass1");
+  SpecialPowers.wrap($_(1, "qword")).setUserInput("newpass1");
 
   // eslint-disable-next-line no-unused-vars
   var button = getFormSubmitButton(1);
 
   todo(false, "form submission disabled, can't auto-accept dialog yet");
   SimpleTest.finish();
 }
 
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit.html
@@ -41,129 +41,158 @@ add_task(async function setup() {
     }],
   });
 });
 
 const DEFAULT_ORIGIN = "http://mochi.test:8888";
 const TESTCASES = [
   {
     // Inputs
-    document: `<input type=password value="pass1">`,
+    document: `<input type=password value="">`,
+    selectorValues: {
+      "[type=password]": "pass1",
+    },
     inputIndexForFormLike: 0,
 
     // Expected outputs similar to PasswordManager:onFormSubmit
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: null,
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">`,
+    document: `<input id="u1" value="">
+      <input type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "[type=password]": "pass1",
+    },
     inputIndexForFormLike: 0,
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">`,
+    document: `<input id="u1" value="">
+      <input type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "[type=password]": "pass1",
+    },
     inputIndexForFormLike: 1,
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">
-      <input type=password value="pass2">`,
+    document: `<input id="u1" value="">
+      <input id="p1" type=password value="">
+      <input id="p2" type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "pass1",
+      "#p2": "pass2",
+    },
     inputIndexForFormLike: 2,
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: "pass1",
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">
-      <input type=password value="pass2">
-      <input type=password value="pass2">`,
+    document: `<input id="u1" value="">
+      <input id="p1" type=password value="">
+      <input id="p2" type=password value="">
+      <input id="p3" type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "pass1",
+      "#p2": "pass2",
+      "#p3": "pass2",
+    },
     inputIndexForFormLike: 3,
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: "pass1",
   },
   {
-    document: `<input value="user1">
-      <input type=password value="user2" form="form1">
-      <input type=password value="pass1">
+    document: `<input id="u1" value="">
+      <input id="p1" type=password value="" form="form1">
+      <input id="p2" type=password value="">
       <form id="form1">
-        <input value="user3">
-        <input type=password value="pass2">
+        <input id="u2" value="">
+        <input id="p3" type=password value="">
       </form>`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "user2",
+      "#p2": "pass1",
+      "#u2": "user3",
+      "#p3": "pass2",
+    },
     inputIndexForFormLike: 2,
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   {
     document: `<!-- recipe field override -->
-      <input name="recipeuname" value="username from recipe">
-      <input value="default field username">
-      <input type=password value="pass1">
-      <input name="recipepword" type=password value="pass2">`,
+      <input name="recipeuname" value="">
+      <input id="u1" value="">
+      <input id="p1" type=password value="">
+      <input name="recipepword" type=password value="">`,
+    selectorValues: {
+      "[name='recipeuname']": "username from recipe",
+      "#u1": "default field username",
+      "#p1": "pass1",
+      "[name='recipepword']": "pass2",
+    },
     inputIndexForFormLike: 2,
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "username from recipe",
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: null,
   },
 ];
 
-function getSubmitMessage() {
-  info("getSubmitMessage");
-  return new Promise((resolve, reject) => {
-    PWMGR_COMMON_PARENT.addMessageListener("formSubmissionProcessed", function processed(...args) {
-      info("got formSubmissionProcessed");
-      PWMGR_COMMON_PARENT.removeMessageListener("formSubmissionProcessed", processed);
-      resolve(...args);
-    });
-  });
-}
-
 add_task(async function test() {
   let count = 0;
   let loginFrame = document.getElementById("loginFrame");
 
   for (let tc of TESTCASES) {
-    let frameDoc = loginFrame.contentWindow.document;
+    let frameDoc = SpecialPowers.wrap(loginFrame.contentWindow).document;
     info("Starting testcase: " + JSON.stringify(tc));
 
+    let formProcessed = promiseFormsProcessed();
     // eslint-disable-next-line no-unsanitized/property
     frameDoc.documentElement.innerHTML = tc.document;
+    await formProcessed;
+    // We eliminate no user input as a reason for not capturing by modifying the value
+    setUserInputValues(frameDoc.documentElement, tc.selectorValues);
+
     let inputForFormLike = frameDoc.querySelectorAll("input")[tc.inputIndexForFormLike];
 
     let formLike = LoginFormFactory.createFromField(inputForFormLike);
 
     info("Calling _onFormSubmit with FormLike");
-    let processedPromise = getSubmitMessage();
+    let submitProcessed = getSubmitMessage();
     LoginManagerChild.forWindow(frameDoc.defaultView)._onFormSubmit(formLike);
 
-    let submittedResult = await processedPromise;
+    let submittedResult = await submitProcessed;
 
     // Check data sent via PasswordManager:onFormSubmit
     is(submittedResult.origin, tc.origin, "Check origin");
     is(submittedResult.formActionOrigin, tc.formActionOrigin, "Check formActionOrigin");
 
     if (tc.usernameFieldValue === null) {
       is(submittedResult.usernameField, tc.usernameFieldValue, "Check usernameField");
     } else {
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation.html
@@ -42,127 +42,145 @@ add_task(async function setup() {
 const DEFAULT_ORIGIN = "http://test1.mochi.test:8888";
 const SCRIPTS = {
   PUSHSTATE: `history.pushState({}, "Pushed state", "?pushed");`,
   WINDOW_LOCATION: `window.location = "data:text/html;charset=utf-8,window.location";`,
 };
 const TESTCASES = [
   {
     // Inputs
-    document: `<input type=password value="pass1">`,
+    document: `<input type=password value="">`,
+    selectorValues: {
+      "[type=password]": "pass1",
+    },
 
     // Expected outputs similar to PasswordManager:onFormSubmit
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: null,
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">`,
+    document: `<input id="u1" value="">
+      <input type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "[type=password]": "pass1",
+    },
 
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">
-      <input type=password value="pass2">`,
+    document: `<input id="u1" value="">
+      <input id="p1" type=password value="">
+      <input id="p2" type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "pass1",
+      "#p2": "pass2",
+    },
 
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: "pass1",
   },
   {
-    document: `<input value="user1">
-      <input type=password value="pass1">
-      <input type=password value="pass2">
-      <input type=password value="pass2">`,
+    document: `<input id="u1" value="">
+      <input id="p1" type=password value="">
+      <input id="p2" type=password value="">
+      <input id="p3" type=password value="">`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "pass1",
+      "#p2": "pass2",
+      "#p3": "pass2",
+    },
 
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: "pass1",
   },
   {
     // Since there are two FormLikes to auto-submit in this case we mark
     // one FormLike's password fields with a magic "ignore-form-submission"
     // value so we can just focus on the other form. We then repeat the testcase
     // below with the other FormLike ignored.
-    document: `<input value="user1">
-      <input type=password value="ignore-form-submission" form="form1">
-      <input type=password value="pass1">
+    document: `<input id="u1" value="">
+      <input type=password id="p1" value="" form="form1">
+      <input type=password id="p2" value="">
       <form id="form1">
-        <input value="user3">
-        <input type=password value="ignore-form-submission">
+        <input id="u2" value="">
+        <input id="p3" type=password value="">
       </form>`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "ignore-form-submission",
+      "#p2": "pass1",
+      "#u2": "user3",
+      "#p3": "ignore-form-submission",
+    },
 
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "user1",
     newPasswordFieldValue: "pass1",
     oldPasswordFieldValue: null,
   },
   { // Same as above but with the other form ignored.
-    document: `<input value="user1">
-      <input type=password value="pass2" form="form1">
-      <input type=password value="ignore-form-submission">
+    document: `<input id="u1" value="">
+      <input id="p1" type=password value="" form="form1">
+      <input id="p2" type=password value="">
       <form id="form1">
-        <input value="user3">
-        <input type=password value="pass2">
+        <input id="u2" value="">
+        <input id="p3" type=password value="">
       </form>`,
+    selectorValues: {
+      "#u1": "user1",
+      "#p1": "pass2",
+      "#p2": "ignore-form-submission",
+      "#u2": "user3",
+      "#p3": "pass2",
+    },
 
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: null,
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: null,
   },
   {
     document: `<!-- recipe field override -->
-      <input name="recipeuname" value="username from recipe">
-      <input value="default field username">
-      <input type=password value="pass1">
-      <input name="recipepword" type=password value="pass2">`,
+      <input name="recipeuname" value="">
+      <input id="u1" value="">
+      <input id="p1" type=password value="">
+      <input name="recipepword" type=password value="">`,
+    selectorValues: {
+      "[name='recipeuname']": "username from recipe",
+      "#u1": "default field username",
+      "#p1": "pass1",
+      "[name='recipepword']": "pass2",
+    },
 
     origin: DEFAULT_ORIGIN,
     formActionOrigin: DEFAULT_ORIGIN,
     usernameFieldValue: "username from recipe",
     newPasswordFieldValue: "pass2",
     oldPasswordFieldValue: null,
   },
 ];
 
-/**
- * @param {Function} [aFilterFn = undefined] Function to filter out irrelevant submissions.
- * @return {Promise} resolving when a relevant form submission was processed.
- */
-function getSubmitMessage(aFilterFn = undefined) {
-  info("getSubmitMessage");
-  return new Promise((resolve, reject) => {
-    PWMGR_COMMON_PARENT.addMessageListener("formSubmissionProcessed", function processed(...args) {
-      if (aFilterFn && !aFilterFn(...args)) {
-        // This submission isn't the one we're waiting for.
-        return;
-      }
-
-      info("got formSubmissionProcessed");
-      PWMGR_COMMON_PARENT.removeMessageListener("formSubmissionProcessed", processed);
-      resolve(...args);
-    });
-  });
-}
-
 function filterFormSubmissions(data) {
   return data.newPasswordField.value != "ignore-form-submission";
 }
 
 add_task(async function test() {
   let loginFrame = document.getElementById("loginFrame");
 
   for (let tc of TESTCASES) {
@@ -184,25 +202,30 @@ add_task(async function test() {
         if (surroundDocumentWithForm) {
           if (testDoc.includes("<form")) {
             info("Skipping surroundDocumentWithForm case since document already contains a <form>");
             continue;
           }
           testDoc = "<form>" + testDoc + "</form>";
         }
 
+        let formProcessed = promiseFormsProcessed();
         // eslint-disable-next-line no-unsanitized/property
         frameDoc.documentElement.innerHTML = testDoc;
-        // Wait for the form to be processed before trying to submit.
-        await promiseFormsProcessed();
-        let processedPromise = getSubmitMessage(filterFormSubmissions);
+        await formProcessed;
+        // We eliminate no user input as a reason for not capturing by modifying the value
+        setUserInputValues(frameDoc.documentElement, tc.selectorValues)
+
+        let submitProcessed = getSubmitMessage(filterFormSubmissions);
         info("Running " + scriptName + " script to cause a submission");
         frameDoc.defaultView.eval(SCRIPTS[scriptName]);
 
-        let submittedResult = await processedPromise;
+        info("Waiting for formSubmissionProcsssed message");
+        let submittedResult = await submitProcessed;
+        info("Got for formSubmissionProcsssed message");
 
         // Check data sent via PasswordManager:onFormSubmit
         is(submittedResult.origin, tc.origin, "Check origin");
         is(submittedResult.formActionOrigin, tc.formActionOrigin, "Check formActionOrigin");
 
         if (tc.usernameFieldValue === null) {
           is(submittedResult.usernameField, tc.usernameFieldValue, "Check usernameField");
         } else {
--- a/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_formless_submit_navigation_negative.html
@@ -48,32 +48,44 @@ const SCRIPTS = {
   WINDOW_LOCATION_RELOAD: `window.location.reload();`,
   HISTORY_BACK: `history.back();`,
   HISTORY_GO_MINUS1: `history.go(-1);`,
 };
 const TESTCASES = [
   // Begin test cases that shouldn't trigger capture.
   {
     // Empty password field in a form
-    document: `<form><input type=password value=""></form>`,
+    document: `<form><input type=password value="xxx"></form>`,
+    selectorValues: {
+      "[type=password]": "",
+    },
   },
   {
     // Empty password field
     document: `<input type=password value="">`,
+    selectorValues: {
+      "[type=password]": "",
+    },
   },
   {
     // Test with an input that would normally be captured but with SCRIPTS that
     // shouldn't trigger capture.
-    document: `<input type=password value="pass2">`,
+    document: `<input type=password value="">`,
+    selectorValues: {
+      "[type=password]": "pass2",
+    },
     wouldCapture: true,
   },
   {
     // Test with an input that would normally be captured but with SCRIPTS that
     // shouldn't trigger capture.
-    document: `<form><input type=password value="pass2"></form>`,
+    document: `<form><input type=password value=""></form>`,
+    selectorValues: {
+      "[type=password]": "pass2",
+    },
     wouldCapture: true,
   },
 ];
 
 add_task(async function test() {
   let loginFrame = document.getElementById("loginFrame");
 
   let waitTime;
@@ -99,19 +111,18 @@ add_task(async function test() {
         }, {once: true});
       });
       loginFrame.src = DEFAULT_ORIGIN + "/tests/toolkit/components/passwordmgr/test/mochitest/blank.html";
       await loadedPromise;
 
       let frameDoc = SpecialPowers.wrap(loginFrame.contentWindow).document;
       // eslint-disable-next-line no-unsanitized/property
       frameDoc.documentElement.innerHTML = tc.document;
-
-      // Wait for the form to be processed before trying to submit.
-      await promiseFormsProcessed();
+      // We eliminate no user input as a reason for not capturing by modifying the value
+      setUserInputValues(frameDoc.documentElement, tc.selectorValues);
 
       info("Running " + scriptName + " script to check for a submission");
       frameDoc.defaultView.eval(SCRIPTS[scriptName]);
 
       // Wait to see if the promise above resolves.
       await new Promise(resolve => setTimeout(resolve, waitTime));
       ok(true, "Done waiting for captures");
     }
--- a/toolkit/components/passwordmgr/test/mochitest/test_munged_username.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_munged_username.html
@@ -58,16 +58,25 @@ async function loadFormIntoIframe(origin
   await loadedPromise;
   await SpecialPowers.spawn(getIframeBrowsingContext(window, 0), [html], function(contentHtml) {
     // eslint-disable-next-line no-unsanitized/property
     this.content.document.documentElement.innerHTML = contentHtml;
   });
 
   // Wait for the form to be processed before trying to submit.
   await promiseFormsProcessed();
+
+  await SpecialPowers.spawn(getIframeBrowsingContext(window, 0), [html], function(contentHtml) {
+    let doc = this.content.document;
+    for (let field of doc.querySelectorAll("input")) {
+      let actualValue = field.value;
+      field.value = "";
+      SpecialPowers.wrap(field).setUserInput(actualValue);
+    }
+  });
 }
 
 add_task(async function setup() {
   info("Waiting for setup and page and frame loads");
   await readyPromise;
   await loadPromise;
 });
 
@@ -122,30 +131,16 @@ const TESTCASES = [
   },
   {
     testName: "test_okBulletUsername2",
     username: "••user••",
     expected: "••user••",
   },
 ];
 
-/**
- * @return {Promise} resolving when form submission was processed.
- */
-function getSubmitMessage() {
-  info("getSubmitMessage");
-  return new Promise((resolve, reject) => {
-    PWMGR_COMMON_PARENT.addMessageListener("formSubmissionProcessed", function processed(...args) {
-      info("got formSubmissionProcessed");
-      PWMGR_COMMON_PARENT.removeMessageListener("formSubmissionProcessed", processed);
-      resolve(...args);
-    });
-  });
-}
-
 add_task(async function test_new_logins() {
   for (let tc of TESTCASES) {
     info("Starting testcase: " + JSON.stringify(tc));
     await loadFormIntoIframe(DEFAULT_ORIGIN, `<form id="form1" onsubmit="return false;">
       <input  type="text"       name="uname" value="${tc.username}">
       <input  type="password"   name="pword" value="thepassword">
       <button type="submit" id="submitBtn">Submit</button>
     </form>`);
@@ -188,18 +183,18 @@ add_task(async function test_no_autofill
   await loadFormIntoIframe(ORG_ORIGIN, `<form id="form1" onsubmit="return false;">
     <input  type="text"       name="uname" value="">
     <input  type="password"   name="pword" value="">
     <button type="submit" id="submitBtn">Submit</button>
   </form>`);
   await SpecialPowers.spawn(getIframeBrowsingContext(window, 0), [], function() {
     let doc = this.content.document;
     Assert.equal(doc.querySelector("[name='uname']").value, "", "Check username didn't get autofilled");
-    doc.querySelector("[name='uname']").setUserInput("real••••user");
-    doc.querySelector("[name='pword']").setUserInput("pass1");
+    SpecialPowers.wrap(doc.querySelector("[name='uname']")).setUserInput("real••••user");
+    SpecialPowers.wrap(doc.querySelector("[name='pword']")).setUserInput("pass1");
   });
 
   // we shouldn't get the save password doorhanger...
   let popupShownPromise = promiseNoUnexpectedPopupShown();
 
   // Check data sent via PasswordManager:onFormSubmit
   let processedPromise = getSubmitMessage();
   await SpecialPowers.spawn(getIframeBrowsingContext(window, 0), [], function() {
--- a/toolkit/components/passwordmgr/test/mochitest/test_one_doorhanger_per_un_pw.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_one_doorhanger_per_un_pw.html
@@ -7,27 +7,16 @@
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="pwmgr_common.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <script>
   let chromeScript = runChecksAfterCommonInit();
 
-  function getSubmitMessage() {
-    info("getSubmitMessage");
-    return new Promise((resolve, reject) => {
-      chromeScript.addMessageListener("formSubmissionProcessed", function processed(...args) {
-        info("got formSubmissionProcessed");
-        chromeScript.removeMessageListener("formSubmissionProcessed", processed);
-        resolve(...args);
-      });
-    });
-  }
-
   SimpleTest.requestFlakyTimeout("Giving a chance for the unexpected popupshown to occur");
 </script>
 <p id="display"></p>
 
 <div id="content" style="display: none">
    <form id="form1" onsubmit="return false;">
     <input  type="text"     name="uname" id="ufield">
     <input  type="password" name="pword" id="pfield">
@@ -40,18 +29,18 @@
   /** Test for Login Manager: Don't repeatedly prompt to save the
       same username and password combination in the same document **/
 
   add_task(async function test_prompt_does_not_reappear() {
     let username = document.getElementById("ufield");
     let password = document.getElementById("pfield");
     let submitButton = document.getElementById("submitBtn");
 
-    username.value = "user";
-    password.value = "pass";
+    SpecialPowers.wrap(username).setUserInput("user");
+    SpecialPowers.wrap(password).setUserInput("pass");
 
     let processedPromise = getSubmitMessage();
     let promptShownPromise = promisePromptShown("passwordmgr-prompt-save");
     submitButton.click();
     await processedPromise;
     await promptShownPromise;
 
     is(username.value, "user", "Checking for filled username");
--- a/toolkit/components/passwordmgr/test/mochitest/test_onsubmit_value_change.html
+++ b/toolkit/components/passwordmgr/test/mochitest/test_onsubmit_value_change.html
@@ -35,22 +35,25 @@ Login Manager test: input value change r
   </form>
 
 </div>
 
 <pre id="test"></pre>
 <script>
   /** Test for Login Manager: input value change right after onsubmit event **/
   add_task(async function checkFormValues() {
-    document.getElementById("ufield").value = "testuser";
-    document.getElementById("pfield").value = "testpass";
+    SpecialPowers.wrap(document.getElementById("ufield")).setUserInput("testuser");
+    SpecialPowers.wrap(document.getElementById("pfield")).setUserInput("testpass");
     is($_(1, "uname").value, "testuser", "Checking for filled username");
     is($_(1, "pword").value, "testpass", "Checking for filled password");
 
     document.getElementById("form1").addEventListener("submit", () => {
+      // deliberately assign to .value rather than setUserInput:
+      // the scenario under test here is that script is changing/populating
+      // fields after the user has clicked the submit button
       document.getElementById("ufield").value = "newuser";
       document.getElementById("pfield").value = "newpass";
     }, true);
 
     document.getElementById("form1").addEventListener("submit", (e) => e.preventDefault());
 
     let processedPromise = getSubmitMessage();