mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-17 20:31:50 +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",
|
"user id",
|
||||||
"customer id",
|
"customer id",
|
||||||
"login id",
|
"login id",
|
||||||
|
"login",
|
||||||
// German
|
// German
|
||||||
"benutzername",
|
"benutzername",
|
||||||
"benutzer name",
|
"benutzer name",
|
||||||
|
@ -162,6 +162,85 @@ describe("CollectAutofillContentService", () => {
|
|||||||
expect(collectAutofillContentService["buildAutofillFieldsData"]).not.toHaveBeenCalled();
|
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 () => {
|
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 documentTitle = "Test Page";
|
||||||
const formId = "validFormId";
|
const formId = "validFormId";
|
||||||
|
@ -54,6 +54,8 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.domRecentlyMutated && this.autofillFieldElements.size) {
|
if (!this.domRecentlyMutated && this.autofillFieldElements.size) {
|
||||||
|
this.updateCachedAutofillFieldVisibility();
|
||||||
|
|
||||||
return this.getFormattedPageDetails(
|
return this.getFormattedPageDetails(
|
||||||
this.getFormattedAutofillFormsData(),
|
this.getFormattedAutofillFormsData(),
|
||||||
this.getFormattedAutofillFieldsData(),
|
this.getFormattedAutofillFieldsData(),
|
||||||
@ -147,10 +149,9 @@ class CollectAutofillContentService implements CollectAutofillContentServiceInte
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats and returns the AutofillPageDetails object
|
* Formats and returns the AutofillPageDetails object
|
||||||
* @param {Record<string, AutofillForm>} autofillFormsData
|
*
|
||||||
* @param {AutofillField[]} autofillFieldsData
|
* @param autofillFormsData - The data for all the forms found in the page
|
||||||
* @returns {AutofillPageDetails}
|
* @param autofillFieldsData - The data for all the fields found in the page
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
private getFormattedPageDetails(
|
private getFormattedPageDetails(
|
||||||
autofillFormsData: Record<string, AutofillForm>,
|
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
|
* Queries the DOM for all the forms elements and
|
||||||
* returns a collection of AutofillForm objects.
|
* returns a collection of AutofillForm objects.
|
||||||
|
Loading…
Reference in New Issue
Block a user