[PM-4415] Refactoring DomElementVisibilityService

This commit is contained in:
Cesar Gonzalez 2024-10-08 08:40:47 -05:00
parent b4d6ccf291
commit 57776a32e5
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
5 changed files with 41 additions and 43 deletions

View File

@ -1,4 +1,4 @@
export interface DomElementVisibilityService {
isFormFieldViewable: (element: HTMLElement) => Promise<boolean>;
isElementViewable: (element: HTMLElement) => Promise<boolean>;
isElementHiddenByCss: (element: HTMLElement) => boolean;
}

View File

@ -263,8 +263,8 @@ describe("CollectAutofillContentService", () => {
collectAutofillContentService["autofillFieldElements"] = new Map([
[fieldElement, autofillField],
]);
const isFormFieldViewableSpy = jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
const isElementViewableSpy = jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
const setupAutofillOverlayListenerOnFieldSpy = jest.spyOn(
collectAutofillContentService["autofillOverlayContentService"],
@ -274,7 +274,7 @@ describe("CollectAutofillContentService", () => {
await collectAutofillContentService.getPageDetails();
expect(autofillField.viewable).toBe(true);
expect(isFormFieldViewableSpy).toHaveBeenCalledWith(fieldElement);
expect(isElementViewableSpy).toHaveBeenCalledWith(fieldElement);
expect(setupAutofillOverlayListenerOnFieldSpy).toHaveBeenCalled();
});
@ -302,7 +302,7 @@ describe("CollectAutofillContentService", () => {
jest.spyOn(collectAutofillContentService as any, "buildAutofillFormsData");
jest.spyOn(collectAutofillContentService as any, "buildAutofillFieldsData");
jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
const pageDetails = await collectAutofillContentService.getPageDetails();
@ -564,7 +564,7 @@ describe("CollectAutofillContentService", () => {
jest.spyOn(collectAutofillContentService as any, "getAutofillFieldElements");
jest.spyOn(collectAutofillContentService as any, "buildAutofillFieldItem");
jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
const { formFieldElements } =
@ -934,7 +934,7 @@ describe("CollectAutofillContentService", () => {
collectAutofillContentService["autofillFieldElements"].set(usernameInput, existingFieldData);
jest.spyOn(collectAutofillContentService as any, "getAutofillFieldMaxLength");
jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
jest.spyOn(collectAutofillContentService as any, "getPropertyOrAttribute");
jest.spyOn(collectAutofillContentService as any, "getElementValue");
@ -946,7 +946,7 @@ describe("CollectAutofillContentService", () => {
expect(collectAutofillContentService["getAutofillFieldMaxLength"]).not.toHaveBeenCalled();
expect(
collectAutofillContentService["domElementVisibilityService"].isFormFieldViewable,
collectAutofillContentService["domElementVisibilityService"].isElementViewable,
).not.toHaveBeenCalled();
expect(collectAutofillContentService["getPropertyOrAttribute"]).not.toHaveBeenCalled();
expect(collectAutofillContentService["getElementValue"]).not.toHaveBeenCalled();
@ -967,7 +967,7 @@ describe("CollectAutofillContentService", () => {
) as ElementWithOpId<FormFieldElement>;
jest.spyOn(collectAutofillContentService as any, "getAutofillFieldMaxLength");
jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
jest.spyOn(collectAutofillContentService as any, "getPropertyOrAttribute");
jest.spyOn(collectAutofillContentService as any, "getElementValue");
@ -981,7 +981,7 @@ describe("CollectAutofillContentService", () => {
spanElement,
);
expect(
collectAutofillContentService["domElementVisibilityService"].isFormFieldViewable,
collectAutofillContentService["domElementVisibilityService"].isElementViewable,
).toHaveBeenCalledWith(spanElement);
expect(collectAutofillContentService["getPropertyOrAttribute"]).toHaveBeenNthCalledWith(
1,
@ -1076,7 +1076,7 @@ describe("CollectAutofillContentService", () => {
) as ElementWithOpId<FillableFormFieldElement>;
jest.spyOn(collectAutofillContentService as any, "getAutofillFieldMaxLength");
jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
jest.spyOn(collectAutofillContentService as any, "getPropertyOrAttribute");
jest.spyOn(collectAutofillContentService as any, "getElementValue");
@ -1162,7 +1162,7 @@ describe("CollectAutofillContentService", () => {
) as ElementWithOpId<FillableFormFieldElement>;
jest.spyOn(collectAutofillContentService as any, "getAutofillFieldMaxLength");
jest
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isFormFieldViewable")
.spyOn(collectAutofillContentService["domElementVisibilityService"], "isElementViewable")
.mockResolvedValue(true);
jest.spyOn(collectAutofillContentService as any, "getPropertyOrAttribute");
jest.spyOn(collectAutofillContentService as any, "getElementValue");
@ -2507,13 +2507,13 @@ describe("CollectAutofillContentService", () => {
});
describe("handleFormElementIntersection", () => {
let isFormFieldViewableSpy: jest.SpyInstance;
let isElementViewableSpy: jest.SpyInstance;
let setupAutofillOverlayListenerOnFieldSpy: jest.SpyInstance;
beforeEach(() => {
isFormFieldViewableSpy = jest.spyOn(
isElementViewableSpy = jest.spyOn(
collectAutofillContentService["domElementVisibilityService"],
"isFormFieldViewable",
"isElementViewable",
);
setupAutofillOverlayListenerOnFieldSpy = jest.spyOn(
collectAutofillContentService["autofillOverlayContentService"],
@ -2532,7 +2532,7 @@ describe("CollectAutofillContentService", () => {
await collectAutofillContentService["handleFormElementIntersection"](entries);
expect(isFormFieldViewableSpy).not.toHaveBeenCalled();
expect(isElementViewableSpy).not.toHaveBeenCalled();
expect(setupAutofillOverlayListenerOnFieldSpy).not.toHaveBeenCalled();
});
@ -2543,11 +2543,11 @@ describe("CollectAutofillContentService", () => {
{ target: formFieldElement, isIntersecting: true },
] as unknown as IntersectionObserverEntry[];
collectAutofillContentService["autofillFieldElements"].set(formFieldElement, autofillField);
isFormFieldViewableSpy.mockReturnValueOnce(false);
isElementViewableSpy.mockReturnValueOnce(false);
await collectAutofillContentService["handleFormElementIntersection"](entries);
expect(isFormFieldViewableSpy).toHaveBeenCalledWith(formFieldElement);
expect(isElementViewableSpy).toHaveBeenCalledWith(formFieldElement);
expect(setupAutofillOverlayListenerOnFieldSpy).not.toHaveBeenCalled();
});
@ -2556,12 +2556,12 @@ describe("CollectAutofillContentService", () => {
const entries = [
{ target: formFieldElement, isIntersecting: true },
] as unknown as IntersectionObserverEntry[];
isFormFieldViewableSpy.mockReturnValueOnce(true);
isElementViewableSpy.mockReturnValueOnce(true);
collectAutofillContentService["intersectionObserver"] = mockIntersectionObserver;
await collectAutofillContentService["handleFormElementIntersection"](entries);
expect(isFormFieldViewableSpy).not.toHaveBeenCalled();
expect(isElementViewableSpy).not.toHaveBeenCalled();
expect(setupAutofillOverlayListenerOnFieldSpy).not.toHaveBeenCalled();
});
@ -2571,13 +2571,13 @@ describe("CollectAutofillContentService", () => {
const entries = [
{ target: formFieldElement, isIntersecting: true },
] as unknown as IntersectionObserverEntry[];
isFormFieldViewableSpy.mockReturnValueOnce(true);
isElementViewableSpy.mockReturnValueOnce(true);
collectAutofillContentService["autofillFieldElements"].set(formFieldElement, autofillField);
collectAutofillContentService["intersectionObserver"] = mockIntersectionObserver;
await collectAutofillContentService["handleFormElementIntersection"](entries);
expect(isFormFieldViewableSpy).toHaveBeenCalledWith(formFieldElement);
expect(isElementViewableSpy).toHaveBeenCalledWith(formFieldElement);
expect(setupAutofillOverlayListenerOnFieldSpy).toHaveBeenCalledWith(
formFieldElement,
autofillField,

View File

@ -196,7 +196,7 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
private updateCachedAutofillFieldVisibility() {
this.autofillFieldElements.forEach(async (autofillField, element) => {
const previouslyViewable = autofillField.viewable;
autofillField.viewable = await this.domElementVisibilityService.isFormFieldViewable(element);
autofillField.viewable = await this.domElementVisibilityService.isElementViewable(element);
if (!previouslyViewable && autofillField.viewable) {
this.setupOverlayOnField(element, autofillField);
@ -360,7 +360,7 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
opid: element.opid,
elementNumber: index,
maxLength: this.getAutofillFieldMaxLength(element),
viewable: await this.domElementVisibilityService.isFormFieldViewable(element),
viewable: await this.domElementVisibilityService.isElementViewable(element),
htmlID: this.getPropertyOrAttribute(element, "id"),
htmlName: this.getPropertyOrAttribute(element, "name"),
htmlClass: this.getPropertyOrAttribute(element, "class"),
@ -1332,8 +1332,7 @@ export class CollectAutofillContentService implements CollectAutofillContentServ
continue;
}
const isViewable =
await this.domElementVisibilityService.isFormFieldViewable(formFieldElement);
const isViewable = await this.domElementVisibilityService.isElementViewable(formFieldElement);
if (!isViewable) {
continue;
}

View File

@ -37,7 +37,7 @@ describe("DomElementVisibilityService", () => {
document.body.innerHTML = "";
});
describe("isFormFieldViewable", () => {
describe("isElementViewable", () => {
it("returns false if the element is outside viewport bounds", async () => {
const usernameElement = document.querySelector("input[name='username']") as FormFieldElement;
jest.spyOn(usernameElement, "getBoundingClientRect");
@ -47,10 +47,10 @@ describe("DomElementVisibilityService", () => {
jest.spyOn(domElementVisibilityService, "isElementHiddenByCss");
jest.spyOn(domElementVisibilityService as any, "formFieldIsNotHiddenBehindAnotherElement");
const isFormFieldViewable =
await domElementVisibilityService.isFormFieldViewable(usernameElement);
const isElementViewable =
await domElementVisibilityService.isElementViewable(usernameElement);
expect(isFormFieldViewable).toEqual(false);
expect(isElementViewable).toEqual(false);
expect(usernameElement.getBoundingClientRect).toHaveBeenCalled();
expect(domElementVisibilityService["isElementOutsideViewportBounds"]).toHaveBeenCalledWith(
usernameElement,
@ -71,10 +71,10 @@ describe("DomElementVisibilityService", () => {
jest.spyOn(domElementVisibilityService, "isElementHiddenByCss").mockReturnValueOnce(true);
jest.spyOn(domElementVisibilityService as any, "formFieldIsNotHiddenBehindAnotherElement");
const isFormFieldViewable =
await domElementVisibilityService.isFormFieldViewable(usernameElement);
const isElementViewable =
await domElementVisibilityService.isElementViewable(usernameElement);
expect(isFormFieldViewable).toEqual(false);
expect(isElementViewable).toEqual(false);
expect(usernameElement.getBoundingClientRect).toHaveBeenCalled();
expect(domElementVisibilityService["isElementOutsideViewportBounds"]).toHaveBeenCalledWith(
usernameElement,
@ -99,10 +99,10 @@ describe("DomElementVisibilityService", () => {
.spyOn(domElementVisibilityService as any, "formFieldIsNotHiddenBehindAnotherElement")
.mockReturnValueOnce(false);
const isFormFieldViewable =
await domElementVisibilityService.isFormFieldViewable(usernameElement);
const isElementViewable =
await domElementVisibilityService.isElementViewable(usernameElement);
expect(isFormFieldViewable).toEqual(false);
expect(isElementViewable).toEqual(false);
expect(usernameElement.getBoundingClientRect).toHaveBeenCalled();
expect(domElementVisibilityService["isElementOutsideViewportBounds"]).toHaveBeenCalledWith(
usernameElement,
@ -127,10 +127,10 @@ describe("DomElementVisibilityService", () => {
.spyOn(domElementVisibilityService as any, "formFieldIsNotHiddenBehindAnotherElement")
.mockReturnValueOnce(true);
const isFormFieldViewable =
await domElementVisibilityService.isFormFieldViewable(usernameElement);
const isElementViewable =
await domElementVisibilityService.isElementViewable(usernameElement);
expect(isFormFieldViewable).toEqual(true);
expect(isElementViewable).toEqual(true);
expect(usernameElement.getBoundingClientRect).toHaveBeenCalled();
expect(domElementVisibilityService["isElementOutsideViewportBounds"]).toHaveBeenCalledWith(
usernameElement,

View File

@ -9,12 +9,11 @@ class DomElementVisibilityService implements DomElementVisibilityServiceInterfac
constructor(private inlineMenuContentService?: AutofillInlineMenuContentService) {}
/**
* Checks if a form field is viewable. This is done by checking if the element is within the
* Checks if an element is viewable. This is done by checking if the element is within the
* viewport bounds, not hidden by CSS, and not hidden behind another element.
* @param {FormFieldElement} element
* @returns {Promise<boolean>}
* @param element
*/
async isFormFieldViewable(element: FormFieldElement): Promise<boolean> {
async isElementViewable(element: HTMLElement): Promise<boolean> {
const elementBoundingClientRect = element.getBoundingClientRect();
if (
this.isElementOutsideViewportBounds(element, elementBoundingClientRect) ||