summaryrefslogtreecommitdiffstats
path: root/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation_confirm.html
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation_confirm.html')
-rw-r--r--toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation_confirm.html380
1 files changed, 380 insertions, 0 deletions
diff --git a/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation_confirm.html b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation_confirm.html
new file mode 100644
index 0000000000..54cb450815
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/mochitest/test_autocomplete_password_generation_confirm.html
@@ -0,0 +1,380 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test filling generated passwords into confirm 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: filling generated passwords into confirm password fields
+
+<template id="form1-template">
+ <form id="form1" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordNext">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form2-template">
+ <form id="form2" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordNext" value="initial value">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form3-template">
+ <form id="form3" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordNext" readonly>
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form4-template">
+ <form id="form4" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordNext" disabled>
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form5-template">
+ <form id="form5" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordBetween">
+ <input type="password" name="pwordNext" autocomplete="new-password">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form6-template">
+ <form id="form6" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordNext">
+ <input type="password" name="pwordAfter" autocomplete="new-password" disabled>
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form7-template">
+ <form id="form7" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="junk0">
+ <input type="password" name="junk1">
+ <input type="password" name="junk2">
+ <input type="password" name="junk3">
+ <input type="password" name="junk4">
+ <input type="password" name="pwordNext" autocomplete="new-password">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form8-template">
+ <form id="form8" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="junk0" disabled>
+ <input type="password" name="junk1" disabled>
+ <input type="password" name="junk2" disabled>
+ <input type="password" name="junk3" disabled>
+ <input type="password" name="junk4" disabled>
+ <input type="password" name="pwordNext" autocomplete="new-password">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form9-template">
+ <form id="form9" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="hidden" name="junk0">
+ <input type="hidden" name="junk1">
+ <input type="hidden" name="junk2">
+ <input type="hidden" name="junk3">
+ <input type="hidden" name="junk4">
+ <input type="password" name="pwordNext" autocomplete="new-password">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<template id="form10-template">
+ <form id="form10" action="https://example.com">
+ <input type="text" name="uname">
+ <input type="password" name="pword" autocomplete="new-password">
+ <input type="password" name="pwordNext" autocomplete="new-password">
+ <input type="password" name="pwordExtra" autocomplete="new-password">
+ <button type="submit">Submit</button>
+ </form>
+</template>
+
+<script class="testbody" type="text/javascript">
+ const formTemplates = {
+ form1: document.getElementById("form1-template"),
+ form2: document.getElementById("form2-template"),
+ form3: document.getElementById("form3-template"),
+ form4: document.getElementById("form4-template"),
+ form5: document.getElementById("form5-template"),
+ form6: document.getElementById("form6-template"),
+ form7: document.getElementById("form7-template"),
+ form8: document.getElementById("form8-template"),
+ form9: document.getElementById("form9-template"),
+ form10: document.getElementById("form10-template"),
+ };
+
+ const setupScript = runInParent(function parentTestSetup() {
+ const { LoginTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/LoginTestUtils.sys.mjs"
+ );
+
+ addMessageListener(
+ "resetLoginsAndGeneratedPasswords", () => {
+ LoginTestUtils.clearData();
+ LoginTestUtils.resetGeneratedPasswordsCache();
+ }
+ );
+ });
+
+ function resetLoginsAndGeneratedPasswords() {
+ return setupScript.sendAsyncMessage("resetLoginsAndGeneratedPasswords");
+ }
+
+ async function triggerPasswordGeneration(form) {
+ await openPopupOn(form.pword);
+ synthesizeKey("KEY_ArrowDown");
+ synthesizeKey("KEY_Enter");
+ await SimpleTest.promiseWaitForCondition(() => !!form.pword.value, "Wait for generated password to get filled");
+ }
+
+ add_named_task("autocomplete menu contains option to generate password", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+
+ const { items } = await openPopupOn(form.pword);
+
+ checkAutoCompleteResults(items, [
+ "Use a Securely Generated Password"
+ ], location.host, "Check all rows are correct");
+ });
+
+ add_named_task("username field highlight", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ ok(!form.uname.matches(":autofill"), "Highlight was not applied to the username field");
+ });
+
+ add_named_task("password field highlight", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ ok(form.pword.matches(":autofill"), "Highlight was applied to the password field");
+ });
+
+ add_named_task("username field is left untouched", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ is(form.uname.value, "", "Value is still empty")
+ });
+
+ add_named_task("generated password looks like a generated password", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ const generatedPassword = form.pword.value;
+ is(generatedPassword.length, GENERATED_PASSWORD_LENGTH, "Generated password length matches");
+ ok(generatedPassword.match(GENERATED_PASSWORD_REGEX), "Generated password format matches");
+ });
+
+ add_named_task("password confirmation also gets filled with the generated password", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, form.pword.value, "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password field is not masked initially after password generation", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ LOGIN_FIELD_UTILS.checkPasswordMasked(form.pword, false, "password field is not masked after password generation");
+ LOGIN_FIELD_UTILS.checkPasswordMasked(form.pwordNext, true, "password confirmation field is masked after user input");
+ });
+
+ add_named_task("password field is masked after user input", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ form.pwordNext.focus();
+ form.pwordNext.select();
+ synthesizeKey("KEY_Backspace");
+ synthesizeKey("a");
+ form.pwordNext.blur();
+ LOGIN_FIELD_UTILS.checkPasswordMasked(form.pword, true, "password field is masked after user input");
+ LOGIN_FIELD_UTILS.checkPasswordMasked(form.pwordNext, true, "password confirmation field is also masked after user input");
+ });
+
+ add_named_task("password field highlight is cleared after user input", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ form.pwordNext.focus();
+ form.pwordNext.select();
+ synthesizeKey("KEY_Backspace");
+ synthesizeKey("a");
+ form.pwordNext.blur();
+ await SimpleTest.promiseWaitForCondition(() => !form.pwordNext.matches(":autofill"), "Highlight was cleared");
+ });
+
+ add_named_task("generated password can be changed", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ const generatedPassword = form.pword.value;
+ form.pword.focus();
+ synthesizeKey("KEY_End");
+ synthesizeKey("@");
+ is(form.pword.value, `${generatedPassword}@`, "Value of the password field changed");
+ });
+
+ add_named_task("password confirmation field does not receive changes from password field", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+ const generatedPassword = form.pword.value;
+
+ // changing the password field value should result in a message sent to the parent process
+ const messageSentPromise = getPasswordEditedMessage();
+
+ form.pword.focus();
+ synthesizeKey("KEY_End");
+ synthesizeKey("@");
+
+ // bluring results in a "change" event
+ form.pword.blur();
+ await messageSentPromise;
+
+ is(form.pwordNext.value, generatedPassword, "Value of the confirm field still holds the original generated password");
+ ok(form.pwordNext.matches(":autofill"), "Highlight is still applied to password confirmation field");
+ });
+
+ add_named_task("password confirmation field behaves like a normal password field once changed", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ await triggerPasswordGeneration(form);
+
+ form.pwordNext.focus();
+ form.pwordNext.select();
+ synthesizeKey("KEY_Backspace");
+
+ // verify the focused confirm field now masks its input like a normal,
+ // non-generated password field after being emptied
+ form.pwordNext.focus();
+ synthesizeKey("a");
+ form.pwordNext.blur();
+
+ LOGIN_FIELD_UTILS.checkPasswordMasked(form.pwordNext, true, "password confirmation field is masked");
+ await SimpleTest.promiseWaitForCondition(() => !form.pwordNext.matches(":autofill"), "highlight was cleared");
+ });
+
+ add_named_task("password confirmation also gets filled with the generated password, even if it has been changed to be of type text", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ form.pwordNext.type = "text";
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, form.pword.value, "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password confirmation does not get filled with the generated password if it is not empty", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form2);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, "initial value", "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password confirmation does not get filled with the generated password if it has been edited", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form1);
+ form.pwordNext.focus()
+ sendString("edited value");
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, "edited value", "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password confirmation does not get filled with the generated password if its readonly", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form3);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, "", "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password confirmation does not get filled with the generated password if its disabled", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form4);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, "", "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password confirmation matching autocomplete info gets filled with the generated password", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form5);
+ await triggerPasswordGeneration(form);
+ is(form.pwordBetween.value, "", "Value of the between field has not been filled");
+ is(form.pwordNext.value, form.pword.value, "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("password confirmation matching autocomplete info gets ignored if its disabled, even if has autocomplete info", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form6);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, form.pword.value, "Value of the confirm field has been filled with generated password");
+ is(form.pwordAfter.value, "", "Value of the disabled confirmation field has not been filled");
+ });
+
+ add_named_task("password confirmation matching autocomplete info gets ignored there are too many fields in between, even if has autocomplete info", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form7);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, "", "Value of the confirm field has not been filled");
+ });
+
+ add_named_task("password confirmation matching autocomplete info gets ignored there are too many disabled fields in between, even if has autocomplete info", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form8);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, "", "Value of the confirm field has not been filled");
+ });
+
+ add_named_task("password confirmation matching autocomplete info gets filled even if there are many hidden fields in between", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form9);
+ await triggerPasswordGeneration(form);
+ is(form.pwordNext.value, form.pword.value, "Value of the confirm field has been filled with generated password");
+ });
+
+ add_named_task("do not fill third password field after the confirm-password field", async () => {
+ await resetLoginsAndGeneratedPasswords();
+ const form = setContentForTask(formTemplates.form10);
+ await triggerPasswordGeneration(form);
+ is(form.pwordExtra.value, "", "Value of the additional confirm field has not been filled");
+ });
+</script>
+</pre>
+</body>
+</html>