diff options
Diffstat (limited to 'toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation.html')
-rw-r--r-- | toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation.html | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation.html b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation.html new file mode 100644 index 0000000000..3fd8b1e90b --- /dev/null +++ b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation.html @@ -0,0 +1,596 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>Test autofill and autocomplete on autocomplete=new-password fields</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <script src="pwmgr_common.js"></script> + <script src="../../../satchel/test/satchel_common.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<p id="display"></p> +<div id="content"></div> +<pre id="test"> +Login Manager test: autofill with password generation on `autocomplete=new-password` fields. + +<template id="form1-template"> + <form id="form1" action="https://autofill"> + <input type="text" name="uname"> + <input type="password" name="p"> + <button type="submit" name="submit">Submit</button> + </form> +</template> + +<template id="form2-template"> + <form id="form2" action="https://autofill"> + <input type="text" name="uname"> + <input type="password" name="password" autocomplete="new-password"> + <button type="submit" name="submit">Submit</button> + </form> +</template> + +<template id="form3-template"> + <form id="form3" action="https://autofill"> + <input type="text" name="username"> + <label>New password<input type="password" name="password"></label> + <button type="submit" name="submit">Submit</button> + </form> +</template> + +<script class="testbody" type="text/javascript"> + const { TestUtils } = SpecialPowers.ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" + ); + + const formTemplates = { + form1: document.getElementById("form1-template"), + form2: document.getElementById("form2-template"), + form3: document.getElementById("form3-template"), + }; + + const dateAndTimeFormatter = new SpecialPowers.Services.intl.DateTimeFormat(undefined, { + dateStyle: "medium", + }); + + async function showACPopup(formNumber, expectedACLabels) { + const autocompleteItems = await popupByArrowDown(); + checkAutoCompleteResults(autocompleteItems, expectedACLabels, + window.location.host, "Check all rows are correct"); + } + + function clearGeneratedPasswords() { + const { LoginManagerParent } = ChromeUtils.importESModule( + "resource://gre/modules/LoginManagerParent.sys.mjs" + ); + if (LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin()) { + LoginManagerParent.getGeneratedPasswordsByPrincipalOrigin().clear(); + } + } + + add_named_task("autofill autocomplete username no generation", async () => { + await setPreferencesForTask( + ["signon.generation.available", false], + ["signon.generation.enabled", false], + ); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form1 = setContentForTask(formTemplates.form1); + + const autofillResult1 = await formAutofillResult(form1.id); + is(autofillResult1, "filled", "form has not been filled due to multiple logins"); + + // reference form was filled as expected? + is(form1.uname.value, "user1", "username is filled"); + is(form1.p.value, "pass1", "password is filled"); + + const form2 = setContentForTask(formTemplates.form2); + const autofillResult2 = await formAutofillResult(form2.id); + is(autofillResult2, "password_autocomplete_new_password", "form has not been filled due to password_autocomplete_new_password"); + + // 2nd form should not be filled + is(form2.uname.value, "", "username is empty"); + is(form2.password.value, "", "password is empty"); + + form2.uname.focus(); + await showACPopup(2, ["user1"]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + + const autofillResult3 = await formAutofillResult(form2.id); + is(autofillResult3, "filled", "form has been filled"); + is(form2.uname.value, "user1", "username is filled"); + is(form2.password.value, "pass1", "password is filled"); + }); + + add_named_task("autofill autocomplete password no generation", async () => { + await setPreferencesForTask( + ["signon.generation.available", false], + ["signon.generation.enabled", false], + ); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form = setContentForTask(formTemplates.form2); + const autofillResult = await formAutofillResult(form.id); + is(autofillResult, "password_autocomplete_new_password", "form has not been filled due to password_autocomplete_new_password"); + + // form should not be filled + is(form.uname.value, "", "username is empty"); + is(form.password.value, "", "password is empty"); + + form.password.focus(); + // No generation option on username fields. + await showACPopup(2, ["user1"]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + + await SimpleTest.promiseWaitForCondition(() => form.password.value == "pass1", "Check pw filled"); + is(form.uname.value, "", "username is empty"); + is(form.password.value, "pass1", "password is filled"); + + // No autocomplete results should appear for non-empty pw fields. + await noPopupByArrowDown(); + }); + + add_named_task("autofill autocomplete username no generation #2", async () => { + await setPreferencesForTask( + ["signon.generation.available", false], + ["signon.generation.enabled", false], + ); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form = setContentForTask(formTemplates.form2); + const autofillResult1 = await formAutofillResult(form.id); + is(autofillResult1, "password_autocomplete_new_password", "form has not been filled due to password_autocomplete_new_password"); + + // form should not be filled + is(form.uname.value, "", "username is empty"); + is(form.password.value, "", "password is empty"); + + form.uname.focus(); + // No generation option on username fields. + await showACPopup(2, ["user1"]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + + const autofillResult2 = await formAutofillResult(form.id); + is(autofillResult2, "filled", "form has been filled"); + is(form.uname.value, "user1", "username is filled"); + is(form.password.value, "pass1", "password is filled"); + }); + + add_named_task("autofill autocomplete passsword with generation", async () => { + await setPreferencesForTask( + ["signon.generation.available", true], + ["signon.generation.enabled", true], + ); + + runInParent(clearGeneratedPasswords); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form = setContentForTask(formTemplates.form2); + const formNumber = 2; + + const autofillResult = await formAutofillResult(form.id); + is(autofillResult, "password_autocomplete_new_password", "form has not been filled due to password_autocomplete_new_password"); + + form.reset(); + + // form should not be filled + is(form.uname.value, "", "username is empty"); + is(form.password.value, "", "password is empty"); + + form.password.focus(); + + await showACPopup(formNumber, [ + "user1", + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + await SimpleTest.promiseWaitForCondition(() => form.password.value == "pass1", "Check pw filled"); + is(form.uname.value, "", "username is empty"); + is(form.password.value, "pass1", "password is filled"); + + // No autocomplete results should appear for non-empty pw fields. + await noPopupByArrowDown(); + + info("Removing all logins to test auto-saving of generated passwords"); + await LoginManager.removeAllUserFacingLogins(); + + while (form.password.value) { + synthesizeKey("KEY_Backspace"); + } + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field"); + + info("This time select the generated password"); + await showACPopup(formNumber, [ + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + const storageAddPromise = promiseStorageChanged(["addLogin"]); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Before first fill of generated pw"); + synthesizeKey("KEY_Enter"); + + info("waiting for the password field to be filled with the generated password"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled"); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After first fill of generated pw"); + info("Wait for generated password to be added to storage"); + await storageAddPromise; + + let logins = await LoginManager.getAllLogins(); + const timePasswordChanged = logins[logins.length - 1].timePasswordChanged; + const time = dateAndTimeFormatter.format(new Date(timePasswordChanged)); + const LABEL_NO_USERNAME = "No username (" + time + ")"; + + const generatedPW = form.password.value; + is(generatedPW.length, GENERATED_PASSWORD_LENGTH, "Check generated password length"); + ok(generatedPW.match(GENERATED_PASSWORD_REGEX), "Check generated password format"); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After fill"); + + info("Check field is masked upon blurring"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "After blur"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After shift-tab to focus again"); + // Remove selection for OS where the whole value is selected upon focus. + synthesizeKey("KEY_ArrowRight"); + + while (form.password.value) { + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, form.password.value); + synthesizeKey("KEY_Backspace"); + } + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field"); + + info("Blur the empty field to trigger a 'change' event"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after blanking"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after blanking"); + + info("Type a single character after blanking"); + synthesizeKey("@"); + + info("Blur the single-character field to trigger a 'change' event"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after backspacing"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after backspacing"); + synthesizeKey("KEY_Backspace"); // Blank the field again + + await showACPopup(formNumber, [ + LABEL_NO_USERNAME, + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled"); + // Same generated password should be used, even despite the 'change' to @ earlier. + is(form.uname.value, "", "username is empty"); + is(form.password.value, generatedPW, "password is filled with generated password"); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "Second fill of the generated pw"); + + logins = await LoginManager.getAllLogins(); + is(logins.length, 1, "Still 1 login after filling the generated password a 2nd time"); + is(logins[0].timePasswordChanged, timePasswordChanged, "Saved login wasn't changed"); + is(logins[0].password, generatedPW, "Password is the same"); + + info("filling the saved login to ensure the field is masked again"); + + while (form.password.value) { + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, form.password.value); + synthesizeKey("KEY_Backspace"); + } + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field again"); + + info("Blur the field to trigger a 'change' event again"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after blanking again"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after blanking again"); + // Remove selection for OS where the whole value is selected upon focus. + synthesizeKey("KEY_ArrowRight"); + + await showACPopup(formNumber, [ + LABEL_NO_USERNAME, + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check saved generated pw filled"); + // Same generated password should be used but from storage + is(form.uname.value, "", "username is empty"); + is(form.password.value, generatedPW, "password is filled with generated password"); + // Passwords from storage should always be masked. + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after fill from storage"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after blur"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after shift-tab to focus again"); + }); + + add_named_task("autofill autocomplete passsword with generation #2", async () => { + await setPreferencesForTask( + ["signon.generation.available", true], + ["signon.generation.enabled", true], + ); + + runInParent(clearGeneratedPasswords); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form = setContentForTask(formTemplates.form3); + const formNumber = 3; + + const autofillResult = await formAutofillResult(form.id); + is(autofillResult, "filled", "form has been filled"); + + form.reset(); + + is(form.username.value, "", "username is empty"); + is(form.password.value, "", "password is empty"); + + form.password.focus(); + + await showACPopup(formNumber, [ + "user1", + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + await SimpleTest.promiseWaitForCondition(() => form.password.value == "pass1", "Check pw filled"); + is(form.username.value, "", "username is empty"); + is(form.password.value, "pass1", "password is filled"); + + // No autocomplete results should appear for non-empty pw fields. + await noPopupByArrowDown(); + + info("Removing all logins to test auto-saving of generated passwords"); + await LoginManager.removeAllUserFacingLogins(); + + while (form.password.value) { + synthesizeKey("KEY_Backspace"); + } + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field"); + + info("This time select the generated password"); + await showACPopup(formNumber, [ + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + const storageAddPromise = promiseStorageChanged(["addLogin"]); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Before first fill of generated pw"); + synthesizeKey("KEY_Enter"); + + info("waiting for the password field to be filled with the generated password"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled"); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After first fill of generated pw"); + info("Wait for generated password to be added to storage"); + await storageAddPromise; + + let logins = await LoginManager.getAllLogins(); + const timePasswordChanged = logins[logins.length - 1].timePasswordChanged; + const time = dateAndTimeFormatter.format(new Date(timePasswordChanged)); + const LABEL_NO_USERNAME = "No username (" + time + ")"; + + const generatedPW = form.password.value; + is(generatedPW.length, GENERATED_PASSWORD_LENGTH, "Check generated password length"); + ok(generatedPW.match(GENERATED_PASSWORD_REGEX), "Check generated password format"); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After fill"); + + info("Check field is masked upon blurring"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "After blur"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "After shift-tab to focus again"); + // Remove selection for OS where the whole value is selected upon focus. + synthesizeKey("KEY_ArrowRight"); + + while (form.password.value) { + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, form.password.value); + synthesizeKey("KEY_Backspace"); + } + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field"); + + info("Blur the empty field to trigger a 'change' event"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after blanking"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after blanking"); + + info("Type a single character after blanking"); + synthesizeKey("@"); + + info("Blur the single-character field to trigger a 'change' event"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after backspacing"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after backspacing"); + synthesizeKey("KEY_Backspace"); // Blank the field again + + await showACPopup(formNumber, [ + LABEL_NO_USERNAME, + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled"); + // Same generated password should be used, even despite the 'change' to @ earlier. + is(form.username.value, "", "username is empty"); + is(form.password.value, generatedPW, "password is filled with generated password"); + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, "Second fill of the generated pw"); + + logins = await LoginManager.getAllLogins(); + is(logins.length, 1, "Still 1 login after filling the generated password a 2nd time"); + is(logins[0].timePasswordChanged, timePasswordChanged, "Saved login wasn't changed"); + is(logins[0].password, generatedPW, "Password is the same"); + + info("filling the saved login to ensure the field is masked again"); + + while (form.password.value) { + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, false, form.password.value); + synthesizeKey("KEY_Backspace"); + } + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blanked field again"); + + info("Blur the field to trigger a 'change' event again"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Blur after blanking again"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "Focus again after blanking again"); + // Remove selection for OS where the whole value is selected upon focus. + synthesizeKey("KEY_ArrowRight"); + + await showACPopup(formNumber, [ + LABEL_NO_USERNAME, + "Use a Securely Generated Password", + ]); + + synthesizeKey("KEY_ArrowDown"); + synthesizeKey("KEY_Enter"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check saved generated pw filled"); + // Same generated password should be used but from storage + is(form.username.value, "", "username is empty"); + is(form.password.value, generatedPW, "password is filled with generated password"); + // Passwords from storage should always be masked. + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after fill from storage"); + synthesizeKey("KEY_Tab"); // blur + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after blur"); + synthesizeKey("KEY_Tab", { shiftKey: true }); // focus + LOGIN_FIELD_UTILS.checkPasswordMasked(form.password, true, "after shift-tab to focus again"); + }); + + add_named_task("autofill autocomplete password save login disabled", async () => { + await setPreferencesForTask( + ["signon.generation.available", true], + ["signon.generation.enabled", true], + ); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form = setContentForTask(formTemplates.form2); + const autofillResult = await formAutofillResult(form.id); + is(autofillResult, "password_autocomplete_new_password", "form has not been filled due to password_autocomplete_new_password"); + + // form should not be filled + is(form.uname.value, "", "username is empty"); + is(form.password.value, "", "password is empty"); + + const formOrigin = new URL(document.documentURI).origin; + is(formOrigin, location.origin, "Expected form origin"); + + await LoginManager.setLoginSavingEnabled(location.origin, false); + + form.password.focus(); + // when login-saving is disabled for an origin, we expect no generated password row here + await showACPopup(2, ["user1"]); + + // close any open menu + synthesizeKey("KEY_Escape"); + await untilAutocompletePopupClosed(); + + await LoginManager.setLoginSavingEnabled(location.origin, true); + }); + + add_named_task("delete and reselect generated password", async () => { + await setPreferencesForTask( + ["signon.generation.available", true], + ["signon.generation.enabled", true], + ); + await setStoredLoginsDuringTask([location.origin, "https://autofill", null, "user1", "pass1"]); + + const form = setContentForTask(formTemplates.form2); + const autofillResult = await formAutofillResult(form.id); + is(autofillResult, "password_autocomplete_new_password", "form has not been filled due to password_autocomplete_new_password"); + + info("Removing all logins to test auto-saving of generated passwords"); + await LoginManager.removeAllUserFacingLogins(); + + // form should not be filled + is(form.uname.value, "", "username is empty"); + is(form.password.value, "", "password is empty"); + + async function showAndSelectACPopupItem(index) { + form.password.focus(); + if (form.password.value) { + form.password.select(); + synthesizeKey("KEY_Backspace"); + } + const autocompleteItems = await popupByArrowDown(); + if (index < 0) { + index = autocompleteItems.length + index; + } + for (let i = 0; i <= index; i++) { + synthesizeKey("KEY_ArrowDown"); + } + await TestUtils.waitForTick(); + return autocompleteItems[index]; + } + + let menuLabel, itemIndex, savedLogins; + + // fill the password field with the generated password via auto-complete menu + const addLoginPromise = promiseStorageChanged(["addLogin"]); + // select last-but-2 item - the one before the footer + menuLabel = await showAndSelectACPopupItem(-2); + is(menuLabel, "Use a Securely Generated Password", "Check item label"); + synthesizeKey("KEY_Enter"); + info("waiting for the password field to be filled with the generated password"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled"); + info("Wait for generated password to be added to storage"); + await addLoginPromise; + + savedLogins = await LoginManager.getAllLogins(); + is(savedLogins.length, 1, "Check saved logins count"); + + form.uname.focus(); + await TestUtils.waitForTick(); + + is(form.password.value.length, LoginTestUtils.generation.LENGTH, "Check password looks generated"); + const GENERATED_PASSWORD = form.password.value; + + info("clear the password field and delete the saved login using the AC menu") + const removeLoginPromise = promiseStorageChanged(["removeLogin"]); + + itemIndex = 0; + menuLabel = await showAndSelectACPopupItem(itemIndex); + ok(menuLabel.includes("No username"), "Check first item is the auto-saved login"); + // Send delete to remove the auto-saved login from storage + // On OS X, shift-backspace and shift-delete work, just delete does not. + // On Win/Linux, shift-backspace does not work, delete and shift-delete do. + synthesizeKey("KEY_Delete", {shiftKey: true}); + await removeLoginPromise; + + form.uname.focus(); + await TestUtils.waitForTick(); + + savedLogins = await LoginManager.getAllLogins(); + is(savedLogins.length, 0, "Check saved logins count"); + + info("Re-fill with the generated password"); + // select last-but-2 item - the one before the footer + menuLabel = await showAndSelectACPopupItem(-2); + is(menuLabel, "Use a Securely Generated Password", "Check item label"); + synthesizeKey("KEY_Enter"); + info("waiting for the password field to be filled with the generated password"); + await SimpleTest.promiseWaitForCondition(() => !!form.password.value, "Check generated pw filled"); + + form.uname.focus(); + await TestUtils.waitForTick(); + is(form.password.value, GENERATED_PASSWORD, "Generated password has not changed"); + }); +</script> +</pre> +</body> +</html> |