1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 01:33:33 +00:00

[PM-5189] Working through jest tests for the AutofillOverlayContentService

This commit is contained in:
Cesar Gonzalez
2024-06-07 14:11:01 -05:00
parent 794808529b
commit 191797e6c2
2 changed files with 82 additions and 13 deletions

View File

@@ -19,6 +19,7 @@ describe("AutofillOverlayContentService", () => {
let autofillInit: AutofillInit; let autofillInit: AutofillInit;
let autofillOverlayContentService: AutofillOverlayContentService; let autofillOverlayContentService: AutofillOverlayContentService;
let sendExtensionMessageSpy: jest.SpyInstance; let sendExtensionMessageSpy: jest.SpyInstance;
const sendResponseSpy = jest.fn();
beforeEach(() => { beforeEach(() => {
autofillOverlayContentService = new AutofillOverlayContentService(); autofillOverlayContentService = new AutofillOverlayContentService();
@@ -200,9 +201,8 @@ describe("AutofillOverlayContentService", () => {
expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled(); expect(autofillFieldElement.addEventListener).not.toHaveBeenCalled();
}); });
// CG - Test is invalid due to the fallback listener we set up for fields that are not visible it("ignores fields that do not appear as a login field", async () => {
it.skip("ignores fields that do not appear as a login field", async () => { autofillFieldData.placeholder = "another-type-of-field";
autofillFieldData.placeholder = "not-a-login-field";
await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField( await autofillOverlayContentService.setupAutofillInlineMenuListenerOnField(
autofillFieldElement, autofillFieldElement,
@@ -256,8 +256,7 @@ describe("AutofillOverlayContentService", () => {
}); });
describe("sets up form field element listeners", () => { describe("sets up form field element listeners", () => {
// TODO - Seems like we're setting up a focus listener on this when it is in a non-viewable state. This test needs to be updated. it("removes all cached event listeners from the form field element", async () => {
it.skip("removes all cached event listeners from the form field element", async () => {
jest.spyOn(autofillFieldElement, "removeEventListener"); jest.spyOn(autofillFieldElement, "removeEventListener");
const inputHandler = jest.fn(); const inputHandler = jest.fn();
const clickHandler = jest.fn(); const clickHandler = jest.fn();
@@ -275,16 +274,21 @@ describe("AutofillOverlayContentService", () => {
expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith( expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith(
1, 1,
"focus",
expect.any(Function),
);
expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith(
2,
"input", "input",
inputHandler, inputHandler,
); );
expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith( expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith(
2, 3,
"click", "click",
clickHandler, clickHandler,
); );
expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith( expect(autofillFieldElement.removeEventListener).toHaveBeenNthCalledWith(
3, 4,
"focus", "focus",
focusHandler, focusHandler,
); );
@@ -893,6 +897,11 @@ describe("AutofillOverlayContentService", () => {
}); });
describe("handleVisibilityChangeEvent", () => { describe("handleVisibilityChangeEvent", () => {
beforeEach(() => {
autofillOverlayContentService["mostRecentlyFocusedField"] =
mock<ElementWithOpId<FormFieldElement>>();
});
it("skips removing the overlay if the document is visible", () => { it("skips removing the overlay if the document is visible", () => {
autofillOverlayContentService["handleVisibilityChangeEvent"](); autofillOverlayContentService["handleVisibilityChangeEvent"]();
@@ -901,8 +910,7 @@ describe("AutofillOverlayContentService", () => {
}); });
}); });
// TODO CG = This test is failing, not entirely sure why but skipping to verify coverage on other files it("removes the overlay if the document is not visible", () => {
it.skip("removes the overlay if the document is not visible", () => {
Object.defineProperty(document, "visibilityState", { Object.defineProperty(document, "visibilityState", {
value: "hidden", value: "hidden",
writable: true, writable: true,
@@ -1381,5 +1389,66 @@ describe("AutofillOverlayContentService", () => {
); );
}); });
}); });
describe("getSubFrameOffsets message handler", () => {
const iframeSource = "https://example.com/";
beforeEach(() => {
document.body.innerHTML = `<iframe id="subframe" src="${iframeSource}"></iframe>`;
});
it("calculates the sub frame's offsets if a single frame with the referenced url exists", async () => {
sendMockExtensionMessage(
{
command: "getSubFrameOffsets",
subFrameUrl: iframeSource,
},
mock<chrome.runtime.MessageSender>(),
sendResponseSpy,
);
await flushPromises();
expect(sendResponseSpy).toHaveBeenCalledWith({
frameId: undefined,
left: 2,
top: 2,
url: "https://example.com/",
});
});
it("returns null if no iframe is found", async () => {
document.body.innerHTML = "";
sendMockExtensionMessage(
{
command: "getSubFrameOffsets",
subFrameUrl: "https://example.com/",
},
mock<chrome.runtime.MessageSender>(),
sendResponseSpy,
);
await flushPromises();
expect(sendResponseSpy).toHaveBeenCalledWith(null);
});
it("returns null if two or more iframes are found with the same src", async () => {
document.body.innerHTML = `
<iframe src="${iframeSource}"></iframe>
<iframe src="${iframeSource}"></iframe>
`;
sendMockExtensionMessage(
{
command: "getSubFrameOffsets",
subFrameUrl: iframeSource,
},
mock<chrome.runtime.MessageSender>(),
sendResponseSpy,
);
await flushPromises();
expect(sendResponseSpy).toHaveBeenCalledWith(null);
});
});
}); });
}); });

View File

@@ -997,10 +997,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
): SubFrameOffsetData { ): SubFrameOffsetData {
const iframeRect = iframeElement.getBoundingClientRect(); const iframeRect = iframeElement.getBoundingClientRect();
const iframeStyles = globalThis.getComputedStyle(iframeElement); const iframeStyles = globalThis.getComputedStyle(iframeElement);
const paddingLeft = parseInt(iframeStyles.getPropertyValue("padding-left")); const paddingLeft = parseInt(iframeStyles.getPropertyValue("padding-left")) || 0;
const paddingTop = parseInt(iframeStyles.getPropertyValue("padding-top")); const paddingTop = parseInt(iframeStyles.getPropertyValue("padding-top")) || 0;
const borderWidthLeft = parseInt(iframeStyles.getPropertyValue("border-left-width")); const borderWidthLeft = parseInt(iframeStyles.getPropertyValue("border-left-width")) || 0;
const borderWidthTop = parseInt(iframeStyles.getPropertyValue("border-top-width")); const borderWidthTop = parseInt(iframeStyles.getPropertyValue("border-top-width")) || 0;
return { return {
url: subFrameUrl, url: subFrameUrl,