зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1625028 - Add plain mochitest coverage for new-password heuristics r=MattN
* Updated the toolkit/components/passwordmgr/test/mochitest/test_autocomplete_new_password.html test to include a third form that has enough signal for the new-password heuristics to detect its password field as a new password field. * Factored out most of the test_autofillAutocompletePassword_withGeneration task to be rechecked for this new form. * Created some new helper functions and promoted them to the global scope in the test, so they can be used by other tasks as well. Differential Revision: https://phabricator.services.mozilla.com/D68499 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
21171604ac
Коммит
d3709f2977
|
@ -46,7 +46,19 @@ let readyPromise = registerRunTests();
|
|||
<!-- form2 uses a new-password type=password field -->
|
||||
<form id="form2" action="https://autofill" onsubmit="return false;">
|
||||
<input type="text" name="uname">
|
||||
<input type="password" name="pword" autocomplete="new-password">
|
||||
<input type="password" name="password" autocomplete="new-password">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- form3 has enough signal to make new-password heuristics (Bug 1595244) detect
|
||||
a new password field, even though there is no autocomplete="new-password"
|
||||
attribute on the <input type="password"> element-->
|
||||
<form id="form3" action="https://autofill" onsubmit="return false;">
|
||||
<input type="text" name="username">
|
||||
<label>
|
||||
New password
|
||||
<input type="password" name="password">
|
||||
</label>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -96,6 +108,31 @@ async function promiseACPopupClosed() {
|
|||
}, "Wait for AC popup to be closed");
|
||||
}
|
||||
|
||||
async function showACPopup(formNumber, expectedACLabels) {
|
||||
let shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let results = await shownPromise;
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
}
|
||||
|
||||
async function checkTelemetryEventsPWGenShown(expectedPWGenTelemetryEvents) {
|
||||
info(`showed generated password option, check there are now ${expectedPWGenTelemetryEvents} generatedpassword telemetry events`);
|
||||
await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == expectedPWGenTelemetryEvents;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsShown }, `Wait for there to be ${expectedPWGenTelemetryEvents} shown telemetry events`);
|
||||
}
|
||||
|
||||
async function checkTelemetryEventsPWGenUsed(expectedPWGenTelemetryEvents) {
|
||||
info("filled generated password again, ensure we don't record another generatedpassword autocomplete telemetry event");
|
||||
let telemetryEvents;
|
||||
try {
|
||||
telemetryEvents = await waitForTelemetryEventsCondition(events => events.length == expectedPWGenTelemetryEvents + 1,
|
||||
{ process: "parent", filterProps: TelemetryFilterPropsUsed },
|
||||
`Wait for there to be ${expectedPWGenTelemetryEvents + 1} used events`, 50);
|
||||
} catch (ex) {}
|
||||
ok(!telemetryEvents, `Expected to timeout waiting for there to be ${expectedPWGenTelemetryEvents + 1} events`);
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["signon.generation.available", false],
|
||||
|
@ -109,6 +146,9 @@ add_task(async function setup() {
|
|||
is(showEvents.length, 0, "Expect 0 show events");
|
||||
let acEvents = await getTelemetryEvents({ process: "parent", filterProps: TelemetryFilterPropsAC, clear: true });
|
||||
is(acEvents.length, 0, "Expect 0 autocomplete events");
|
||||
|
||||
// This can be removed once Bug 1623431 is resolved.
|
||||
document.getElementById("form3").reset();
|
||||
});
|
||||
|
||||
add_task(async function test_autofillAutocompleteUsername_noGeneration() {
|
||||
|
@ -119,11 +159,7 @@ add_task(async function test_autofillAutocompleteUsername_noGeneration() {
|
|||
checkForm(2, "", "");
|
||||
|
||||
$_(2, "uname").focus();
|
||||
const shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let results = await shownPromise;
|
||||
let expectedACLabels = ["user1"];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
await showACPopup(2, ["user1"]);
|
||||
|
||||
let acEvents = await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == 1;
|
||||
|
@ -146,13 +182,9 @@ add_task(async function test_autofillAutocompletePassword_noGeneration() {
|
|||
// 2nd form should not be filled
|
||||
checkForm(2, "", "");
|
||||
|
||||
let pword = $_(2, "pword");
|
||||
let pword = $_(2, "password");
|
||||
pword.focus();
|
||||
const shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let results = await shownPromise;
|
||||
let expectedACLabels = ["user1"];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
await showACPopup(2, ["user1"]);
|
||||
let acEvents = await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == 1;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsAC, clear: true }, `Wait for there to be 1 autocomplete telemetry event`);
|
||||
|
@ -188,12 +220,8 @@ add_task(async function test_autofillAutocompleteUsername_noGeneration2() {
|
|||
checkForm(2, "", "");
|
||||
|
||||
$_(2, "uname").focus();
|
||||
const shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let results = await shownPromise;
|
||||
// No generation option on username fields.
|
||||
let expectedACLabels = ["user1"];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
await showACPopup(2, ["user1"]);
|
||||
let acEvents = await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == 1;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsAC, clear: true }, `Wait for there to be 1 autocomplete telemetry event`);
|
||||
|
@ -212,192 +240,183 @@ add_task(async function test_autofillAutocompleteUsername_noGeneration2() {
|
|||
});
|
||||
|
||||
add_task(async function test_autofillAutocompletePassword_withGeneration() {
|
||||
// 2nd form should not be filled
|
||||
checkForm(2, "", "");
|
||||
const formNumbersToTest = [2, 3];
|
||||
// Bug 1616356 and Bug 1548878: Recorded once per origin
|
||||
let expectedPWGenTelemetryEvents = 0;
|
||||
// Bug 1619498: Recorded once every time the autocomplete popup is shown
|
||||
let expectedACShownTelemetryEvents = 0;
|
||||
for (let formNumber of formNumbersToTest) {
|
||||
// This form should not be filled
|
||||
checkForm(formNumber, "", "");
|
||||
|
||||
let pword = $_(2, "pword");
|
||||
pword.focus();
|
||||
let shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let results = await shownPromise;
|
||||
let expectedACLabels = [
|
||||
"user1",
|
||||
"Use a Securely Generated Password",
|
||||
];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
let pword = $_(formNumber, "password");
|
||||
pword.focus();
|
||||
|
||||
let expectedCount = 1;
|
||||
info(`showed generated password option, check there are now ${expectedCount} generatedpassword telemetry events`);
|
||||
await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == expectedCount;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsShown }, `Wait for there to be ${expectedCount} shown telemetry events`);
|
||||
await showACPopup(formNumber, [
|
||||
"user1",
|
||||
"Use a Securely Generated Password",
|
||||
]);
|
||||
expectedPWGenTelemetryEvents++;
|
||||
expectedACShownTelemetryEvents++;
|
||||
|
||||
let acEvents = await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == 1;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsAC }, `Wait for there to be 1 autocomplete telemetry event`);
|
||||
checkACTelemetryEvent(acEvents[0], pword, {
|
||||
"generatedPasswo": "1",
|
||||
"hadPrevious": "0",
|
||||
"loginWithOrigin": "1",
|
||||
"loginsFooter": "1"
|
||||
});
|
||||
await checkTelemetryEventsPWGenShown(expectedPWGenTelemetryEvents);
|
||||
let acEvents = await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == expectedACShownTelemetryEvents;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsAC }, `Wait for there to be ${expectedACShownTelemetryEvents} autocomplete telemetry event(s)`);
|
||||
checkACTelemetryEvent(acEvents[expectedACShownTelemetryEvents - 1], pword, {
|
||||
"generatedPasswo": "1",
|
||||
"hadPrevious": "0",
|
||||
"loginWithOrigin": "1",
|
||||
"loginsFooter": "1"
|
||||
});
|
||||
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_Enter");
|
||||
// Can't use promiseFormsProcessed() when autocomplete fills the field directly.
|
||||
await SimpleTest.promiseWaitForCondition(() => pword.value == "pass1", "Check pw filled");
|
||||
checkForm(2, "", "pass1");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_Enter");
|
||||
// Can't use promiseFormsProcessed() when autocomplete fills the field directly.
|
||||
await SimpleTest.promiseWaitForCondition(() => pword.value == "pass1", "Check pw filled");
|
||||
checkForm(formNumber, "", "pass1");
|
||||
|
||||
// No autocomplete results should appear for non-empty pw fields.
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
await promiseNoUnexpectedPopupShown();
|
||||
// No autocomplete results should appear for non-empty pw fields.
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
await promiseNoUnexpectedPopupShown();
|
||||
|
||||
info("Removing all logins to test auto-saving of generated passwords");
|
||||
await LoginManager.removeAllLogins();
|
||||
info("Removing all logins to test auto-saving of generated passwords");
|
||||
await LoginManager.removeAllLogins();
|
||||
|
||||
while (pword.value) {
|
||||
while (pword.value) {
|
||||
synthesizeKey("KEY_Backspace");
|
||||
}
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field");
|
||||
|
||||
info("This time select the generated password");
|
||||
await showACPopup(formNumber, [
|
||||
"Use a Securely Generated Password",
|
||||
]);
|
||||
expectedACShownTelemetryEvents++;
|
||||
|
||||
await checkTelemetryEventsPWGenShown(expectedPWGenTelemetryEvents);
|
||||
acEvents = await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == expectedACShownTelemetryEvents;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsAC }, `Wait for there to be ${expectedACShownTelemetryEvents} autocomplete telemetry event(s)`);
|
||||
checkACTelemetryEvent(acEvents[expectedACShownTelemetryEvents - 1], pword, {
|
||||
"generatedPasswo": "1",
|
||||
"hadPrevious": "0",
|
||||
"loginsFooter": "1"
|
||||
});
|
||||
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let storageAddPromise = promiseStorageChanged(["addLogin"]);
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, 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(() => !!pword.value, "Check generated pw filled");
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill of generated pw");
|
||||
info("Wait for generated password to be added to storage");
|
||||
await storageAddPromise;
|
||||
|
||||
let logins = await LoginManager.getAllLogins();
|
||||
let timePasswordChanged = logins[logins.length - 1].timePasswordChanged;
|
||||
let time = dateAndTimeFormatter.format(new Date(timePasswordChanged));
|
||||
const LABEL_NO_USERNAME = "No username (" + time + ")";
|
||||
|
||||
let generatedPW = pword.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(pword, false, "After fill");
|
||||
|
||||
info("Check field is masked upon blurring");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After shift-tab to focus again");
|
||||
// Remove selection for OS where the whole value is selected upon focus.
|
||||
synthesizeKey("KEY_ArrowRight");
|
||||
|
||||
while (pword.value) {
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, pword.value);
|
||||
synthesizeKey("KEY_Backspace");
|
||||
}
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field");
|
||||
|
||||
info("Blur the empty field to trigger a 'change' event");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after blanking");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, 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(pword, true, "Blur after backspacing");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Focus again after backspacing");
|
||||
synthesizeKey("KEY_Backspace"); // Blank the field again
|
||||
|
||||
await showACPopup(formNumber, [
|
||||
LABEL_NO_USERNAME,
|
||||
"Use a Securely Generated Password",
|
||||
]);
|
||||
expectedACShownTelemetryEvents++;
|
||||
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_Enter");
|
||||
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check generated pw filled");
|
||||
// Same generated password should be used, even despite the 'change' to @ earlier.
|
||||
checkForm(formNumber, "", generatedPW);
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "Second fill of the generated pw");
|
||||
|
||||
await checkTelemetryEventsPWGenUsed(expectedPWGenTelemetryEvents);
|
||||
|
||||
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 (pword.value) {
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, pword.value);
|
||||
synthesizeKey("KEY_Backspace");
|
||||
}
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field again");
|
||||
|
||||
info("Blur the field to trigger a 'change' event again");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after blanking again");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, 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",
|
||||
]);
|
||||
expectedACShownTelemetryEvents++;
|
||||
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_Enter");
|
||||
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check saved generated pw filled");
|
||||
// Same generated password should be used but from storage
|
||||
checkForm(formNumber, "", generatedPW);
|
||||
// Passwords from storage should always be masked.
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after fill from storage");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after blur");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after shift-tab to focus again");
|
||||
|
||||
info("reset initial login state with login1");
|
||||
runInParent(initLogins);
|
||||
info("invalidate the autocomplete cache after updating storage above");
|
||||
synthesizeKey("KEY_Backspace");
|
||||
|
||||
recreateTree(document.getElementById(`form${formNumber}`));
|
||||
}
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field");
|
||||
|
||||
info("This time select the generated password");
|
||||
shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
results = await shownPromise;
|
||||
expectedACLabels = [
|
||||
"Use a Securely Generated Password",
|
||||
];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let storageAddPromise = promiseStorageChanged(["addLogin"]);
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, 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(() => !!pword.value, "Check generated pw filled");
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After first fill of generated pw");
|
||||
info("Wait for generated password to be added to storage");
|
||||
await storageAddPromise;
|
||||
|
||||
expectedCount = 1;
|
||||
info(`filled generated password, check there are now ${expectedCount} generatedpassword telemetry events`);
|
||||
await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == expectedCount;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsUsed }, `Wait for there to be ${expectedCount} used telemetry events`);
|
||||
|
||||
let logins = await LoginManager.getAllLogins();
|
||||
let timePasswordChanged = logins[logins.length - 1].timePasswordChanged;
|
||||
let time = dateAndTimeFormatter.format(new Date(timePasswordChanged));
|
||||
const LABEL_NO_USERNAME = "No username (" + time + ")";
|
||||
|
||||
let generatedPW = pword.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(pword, false, "After fill");
|
||||
|
||||
info("Check field is masked upon blurring");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "After blur");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "After shift-tab to focus again");
|
||||
// Remove selection for OS where the whole value is selected upon focus.
|
||||
synthesizeKey("KEY_ArrowRight");
|
||||
|
||||
while (pword.value) {
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, pword.value);
|
||||
synthesizeKey("KEY_Backspace");
|
||||
}
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field");
|
||||
|
||||
info("Blur the empty field to trigger a 'change' event");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after blanking");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, 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(pword, true, "Blur after backspacing");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Focus again after backspacing");
|
||||
synthesizeKey("KEY_Backspace"); // Blank the field again
|
||||
|
||||
shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
results = await shownPromise;
|
||||
expectedACLabels = [
|
||||
LABEL_NO_USERNAME,
|
||||
"Use a Securely Generated Password",
|
||||
];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_Enter");
|
||||
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check generated pw filled");
|
||||
// Same generated password should be used, even despite the 'change' to @ earlier.
|
||||
checkForm(2, "", generatedPW);
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, "Second fill of the generated pw");
|
||||
|
||||
info("filled generated password again, ensure we don't record another generatedpassword autocomplete telemetry event");
|
||||
let telemetryEvents;
|
||||
expectedCount = 2;
|
||||
try {
|
||||
telemetryEvents = await waitForTelemetryEventsCondition(events => events.length == expectedCount,
|
||||
{ process: "parent", filterProps: TelemetryFilterPropsUsed },
|
||||
`Wait for there to be ${expectedCount} used events`, 50);
|
||||
} catch (ex) {}
|
||||
ok(!telemetryEvents, "Expected to timeout waiting for there to be 2 events");
|
||||
|
||||
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 (pword.value) {
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, false, pword.value);
|
||||
synthesizeKey("KEY_Backspace");
|
||||
}
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blanked field again");
|
||||
|
||||
info("Blur the field to trigger a 'change' event again");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Blur after blanking again");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus again
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "Focus again after blanking again");
|
||||
// Remove selection for OS where the whole value is selected upon focus.
|
||||
synthesizeKey("KEY_ArrowRight");
|
||||
|
||||
shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
results = await shownPromise;
|
||||
expectedACLabels = [
|
||||
LABEL_NO_USERNAME,
|
||||
"Use a Securely Generated Password",
|
||||
];
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
synthesizeKey("KEY_Enter");
|
||||
await SimpleTest.promiseWaitForCondition(() => !!pword.value, "Check saved generated pw filled");
|
||||
// Same generated password should be used but from storage
|
||||
checkForm(2, "", generatedPW);
|
||||
// Passwords from storage should always be masked.
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after fill from storage");
|
||||
synthesizeKey("KEY_Tab"); // blur
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after blur");
|
||||
synthesizeKey("KEY_Tab", { shiftKey: true }); // focus
|
||||
LOGIN_FIELD_UTILS.checkPasswordMasked(pword, true, "after shift-tab to focus again");
|
||||
|
||||
info("reset initial login state with login1");
|
||||
runInParent(initLogins);
|
||||
info("invalidate the autocomplete cache after updating storage above");
|
||||
synthesizeKey("KEY_Backspace");
|
||||
|
||||
recreateTree(document.getElementById("form2"));
|
||||
});
|
||||
|
||||
add_task(async function test_autofillAutocompletePassword_saveLoginDisabled() {
|
||||
|
@ -408,17 +427,10 @@ add_task(async function test_autofillAutocompletePassword_saveLoginDisabled() {
|
|||
|
||||
await LoginManager.setLoginSavingEnabled("https://example.com", false);
|
||||
|
||||
let pword = $_(2, "pword");
|
||||
let pword = $_(2, "password");
|
||||
pword.focus();
|
||||
let shownPromise = promiseACShown();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
let results = await shownPromise;
|
||||
let expectedACLabels = [
|
||||
// when login-saving is disabled for an origin, we expect no generated password row here
|
||||
"user1",
|
||||
];
|
||||
info("ac results: " + results.join(", "));
|
||||
checkAutoCompleteResults(results, expectedACLabels, "example.com", "Check all rows are correct");
|
||||
// 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");
|
||||
|
@ -434,7 +446,7 @@ add_task(async function test_deleteAndReselectGeneratedPassword() {
|
|||
|
||||
// form should not be filled
|
||||
checkForm(2, "", "");
|
||||
let pword = $_(2, "pword");
|
||||
let pword = $_(2, "password");
|
||||
let uname = $_(2, "uname");
|
||||
|
||||
async function showAndSelectACPopupItem(index) {
|
||||
|
@ -512,10 +524,10 @@ add_task(async function test_deleteAndReselectGeneratedPassword() {
|
|||
});
|
||||
|
||||
add_task(async function test_passwordGenerationShownTelemetry() {
|
||||
// Should only be recorded once per principal origin per session but the cache is cleared once via initLogins.
|
||||
// Should only be recorded once per principal origin per session, but the cache is cleared each time ``initLogins`` is called.
|
||||
await waitForTelemetryEventsCondition(events => {
|
||||
return events.length == 2;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsShown }, "Expect two shown telemetry events");
|
||||
return events.length == 3;
|
||||
}, { process: "parent", filterProps: TelemetryFilterPropsShown }, "Expect 3 shown telemetry events");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
|
|
Загрузка…
Ссылка в новой задаче