1
0
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:
Cesar Gonzalez 2023-12-13 15:17:47 -06:00 committed by GitHub
parent de4f9c723b
commit 12de4b1386
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 4 deletions

View File

@ -11,6 +11,7 @@ export class AutoFillConstants {
"user id",
"customer id",
"login id",
"login",
// German
"benutzername",
"benutzer name",

View File

@ -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";

View File

@ -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.