mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-21 16:18:28 +01:00
[PM-5245] Autofill not triggering for fields that are not visible on load (#7209)
This commit is contained in:
parent
de4f9c723b
commit
12de4b1386
@ -11,6 +11,7 @@ export class AutoFillConstants {
|
||||
"user id",
|
||||
"customer id",
|
||||
"login id",
|
||||
"login",
|
||||
// German
|
||||
"benutzername",
|
||||
"benutzer name",
|
||||
|
@ -162,6 +162,85 @@ describe("CollectAutofillContentService", () => {
|
||||
expect(collectAutofillContentService["buildAutofillFieldsData"]).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("updates the visibility for cached autofill fields", async () => {
|
||||
const formId = "validFormId";
|
||||
const formAction = "https://example.com/";
|
||||
const formMethod = "post";
|
||||
const formName = "validFormName";
|
||||
const usernameFieldId = "usernameField";
|
||||
const usernameFieldName = "username";
|
||||
const usernameFieldLabel = "User Name";
|
||||
const passwordFieldId = "passwordField";
|
||||
const passwordFieldName = "password";
|
||||
const passwordFieldLabel = "Password";
|
||||
document.body.innerHTML = `
|
||||
<form id="${formId}" action="${formAction}" method="${formMethod}" name="${formName}">
|
||||
<label for="${usernameFieldId}">${usernameFieldLabel}</label>
|
||||
<input type="text" id="${usernameFieldId}" name="${usernameFieldName}" />
|
||||
<label for="${passwordFieldId}">${passwordFieldLabel}</label>
|
||||
<input type="password" id="${passwordFieldId}" name="${passwordFieldName}" />
|
||||
</form>
|
||||
`;
|
||||
const formElement = document.getElementById(formId) as ElementWithOpId<HTMLFormElement>;
|
||||
const autofillForm: AutofillForm = {
|
||||
opid: "__form__0",
|
||||
htmlAction: formAction,
|
||||
htmlName: formName,
|
||||
htmlID: formId,
|
||||
htmlMethod: formMethod,
|
||||
};
|
||||
const fieldElement = document.getElementById(
|
||||
usernameFieldId,
|
||||
) as ElementWithOpId<FormFieldElement>;
|
||||
const autofillField: AutofillField = {
|
||||
opid: "__0",
|
||||
elementNumber: 0,
|
||||
maxLength: 999,
|
||||
viewable: false,
|
||||
htmlID: usernameFieldId,
|
||||
htmlName: usernameFieldName,
|
||||
htmlClass: null,
|
||||
tabindex: null,
|
||||
title: "",
|
||||
tagName: "input",
|
||||
"label-tag": usernameFieldLabel,
|
||||
"label-data": null,
|
||||
"label-aria": null,
|
||||
"label-top": null,
|
||||
"label-right": passwordFieldLabel,
|
||||
"label-left": usernameFieldLabel,
|
||||
placeholder: "",
|
||||
rel: null,
|
||||
type: "text",
|
||||
value: "",
|
||||
checked: false,
|
||||
autoCompleteType: "",
|
||||
disabled: false,
|
||||
readonly: false,
|
||||
selectInfo: null,
|
||||
form: "__form__0",
|
||||
"aria-hidden": false,
|
||||
"aria-disabled": false,
|
||||
"aria-haspopup": false,
|
||||
"data-stripe": null,
|
||||
};
|
||||
collectAutofillContentService["domRecentlyMutated"] = false;
|
||||
collectAutofillContentService["autofillFormElements"] = new Map([
|
||||
[formElement, autofillForm],
|
||||
]);
|
||||
collectAutofillContentService["autofillFieldElements"] = new Map([
|
||||
[fieldElement, autofillField],
|
||||
]);
|
||||
const isFormFieldViewableSpy = jest
|
||||
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
|
||||
.mockResolvedValue(true);
|
||||
|
||||
await collectAutofillContentService.getPageDetails();
|
||||
|
||||
expect(autofillField.viewable).toBe(true);
|
||||
expect(isFormFieldViewableSpy).toHaveBeenCalledWith(fieldElement);
|
||||
});
|
||||
|
||||
it("returns an object containing information about the current page as well as autofill data for the forms and fields of the page", async () => {
|
||||
const documentTitle = "Test Page";
|
||||
const formId = "validFormId";
|
||||
|
@ -54,6 +54,8 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
}
|
||||
|
||||
if (!this.domRecentlyMutated && this.autofillFieldElements.size) {
|
||||
this.updateCachedAutofillFieldVisibility();
|
||||
|
||||
return this.getFormattedPageDetails(
|
||||
this.getFormattedAutofillFormsData(),
|
||||
this.getFormattedAutofillFieldsData(),
|
||||
@ -147,10 +149,9 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
|
||||
/**
|
||||
* Formats and returns the AutofillPageDetails object
|
||||
* @param {Record<string, AutofillForm>} autofillFormsData
|
||||
* @param {AutofillField[]} autofillFieldsData
|
||||
* @returns {AutofillPageDetails}
|
||||
* @private
|
||||
*
|
||||
* @param autofillFormsData - The data for all the forms found in the page
|
||||
* @param autofillFieldsData - The data for all the fields found in the page
|
||||
*/
|
||||
private getFormattedPageDetails(
|
||||
autofillFormsData: Record<string, AutofillForm>,
|
||||
@ -166,6 +167,20 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-checks the visibility for all form fields and updates the
|
||||
* cached data to reflect the most recent visibility state.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private updateCachedAutofillFieldVisibility() {
|
||||
this.autofillFieldElements.forEach(
|
||||
async (autofillField, element) =>
|
||||
(autofillField.viewable =
|
||||
await this.domElementVisibilityService.isFormFieldViewable(element)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the DOM for all the forms elements and
|
||||
* returns a collection of AutofillForm objects.
|
||||
|
Loading…
Reference in New Issue
Block a user