diff --git a/apps/browser/src/autofill/overlay/pages/button/autofill-overlay-button.spec.ts b/apps/browser/src/autofill/overlay/pages/button/autofill-overlay-button.spec.ts index d19a75c04a2..4a1cf47d1ed 100644 --- a/apps/browser/src/autofill/overlay/pages/button/autofill-overlay-button.spec.ts +++ b/apps/browser/src/autofill/overlay/pages/button/autofill-overlay-button.spec.ts @@ -1,7 +1,9 @@ +import { mock } from "jest-mock-extended"; + import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { createInitAutofillOverlayButtonMessageMock } from "../../../spec/autofill-mocks"; -import { postWindowMessage } from "../../../spec/testing-utils"; +import { flushPromises, postWindowMessage } from "../../../spec/testing-utils"; import AutofillOverlayButton from "./autofill-overlay-button"; @@ -9,13 +11,20 @@ describe("AutofillOverlayButton", () => { globalThis.customElements.define("autofill-overlay-button", AutofillOverlayButton); let autofillOverlayButton: AutofillOverlayButton; + let messageConnectorIframe: HTMLIFrameElement; + const portKey: string = "overlayButtonPortKey"; beforeEach(() => { document.body.innerHTML = ``; autofillOverlayButton = document.querySelector("autofill-overlay-button"); autofillOverlayButton["messageOrigin"] = "https://localhost/"; + messageConnectorIframe = mock({ + contentWindow: { postMessage: jest.fn() }, + }); + autofillOverlayButton["messageConnectorIframe"] = messageConnectorIframe; + jest.spyOn(autofillOverlayButton as any, "initMessageConnector").mockResolvedValue(undefined); jest.spyOn(globalThis.document, "createElement"); - jest.spyOn(globalThis.parent, "postMessage"); + jest.spyOn(messageConnectorIframe.contentWindow, "postMessage"); }); afterEach(() => { @@ -23,10 +32,14 @@ describe("AutofillOverlayButton", () => { }); describe("initAutofillOverlayButton", () => { - it("creates the button element with the locked icon when the user's auth status is not Unlocked", () => { + it("creates the button element with the locked icon when the user's auth status is not Unlocked", async () => { postWindowMessage( - createInitAutofillOverlayButtonMessageMock({ authStatus: AuthenticationStatus.Locked }), + createInitAutofillOverlayButtonMessageMock({ + authStatus: AuthenticationStatus.Locked, + portKey, + }), ); + await flushPromises(); expect(autofillOverlayButton["buttonElement"]).toMatchSnapshot(); expect(autofillOverlayButton["buttonElement"].querySelector("svg")).toBe( @@ -34,8 +47,9 @@ describe("AutofillOverlayButton", () => { ); }); - it("creates the button element with the normal icon when the user's auth status is Unlocked ", () => { - postWindowMessage(createInitAutofillOverlayButtonMessageMock()); + it("creates the button element with the normal icon when the user's auth status is Unlocked ", async () => { + postWindowMessage(createInitAutofillOverlayButtonMessageMock({ portKey })); + await flushPromises(); expect(autofillOverlayButton["buttonElement"]).toMatchSnapshot(); expect(autofillOverlayButton["buttonElement"].querySelector("svg")).toBe( @@ -43,55 +57,60 @@ describe("AutofillOverlayButton", () => { ); }); - it("posts a message to the background indicating that the icon was clicked", () => { - postWindowMessage(createInitAutofillOverlayButtonMessageMock()); + it("posts a message to the background indicating that the icon was clicked", async () => { + postWindowMessage(createInitAutofillOverlayButtonMessageMock({ portKey })); + await flushPromises(); + autofillOverlayButton["buttonElement"].click(); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "overlayButtonClicked" }, - "https://localhost/", + expect(messageConnectorIframe.contentWindow.postMessage).toHaveBeenCalledWith( + { command: "overlayButtonClicked", portKey }, + "*", ); }); }); describe("global event listeners", () => { beforeEach(() => { - postWindowMessage(createInitAutofillOverlayButtonMessageMock()); + postWindowMessage(createInitAutofillOverlayButtonMessageMock({ portKey })); }); - it("does not post a message to close the autofill overlay if the element is focused during the focus check", () => { + it("does not post a message to close the autofill overlay if the element is focused during the focus check", async () => { jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(true); postWindowMessage({ command: "checkAutofillOverlayButtonFocused" }); + await flushPromises(); - expect(globalThis.parent.postMessage).not.toHaveBeenCalledWith({ + expect(messageConnectorIframe.contentWindow.postMessage).not.toHaveBeenCalledWith({ command: "closeAutofillOverlay", }); }); - it("posts a message to close the autofill overlay if the element is not focused during the focus check", () => { + it("posts a message to close the autofill overlay if the element is not focused during the focus check", async () => { jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(false); postWindowMessage({ command: "checkAutofillOverlayButtonFocused" }); + await flushPromises(); - expect(globalThis.parent.postMessage).toHaveBeenCalledWith( - { command: "closeAutofillOverlay" }, - "https://localhost/", + expect(messageConnectorIframe.contentWindow.postMessage).toHaveBeenCalledWith( + { command: "closeAutofillOverlay", portKey }, + "*", ); }); - it("updates the user's auth status", () => { + it("updates the user's auth status", async () => { autofillOverlayButton["authStatus"] = AuthenticationStatus.Locked; postWindowMessage({ command: "updateAutofillOverlayButtonAuthStatus", authStatus: AuthenticationStatus.Unlocked, }); + await flushPromises(); expect(autofillOverlayButton["authStatus"]).toBe(AuthenticationStatus.Unlocked); }); - it("updates the page color scheme meta tag", () => { + it("updates the page color scheme meta tag", async () => { const colorSchemeMetaTag = globalThis.document.createElement("meta"); colorSchemeMetaTag.setAttribute("name", "color-scheme"); colorSchemeMetaTag.setAttribute("content", "light"); @@ -101,6 +120,7 @@ describe("AutofillOverlayButton", () => { command: "updateOverlayPageColorScheme", colorScheme: "dark", }); + await flushPromises(); expect(colorSchemeMetaTag.getAttribute("content")).toBe("dark"); }); diff --git a/apps/browser/src/autofill/overlay/pages/list/autofill-overlay-list.spec.ts b/apps/browser/src/autofill/overlay/pages/list/autofill-overlay-list.spec.ts index 3dc8613c2aa..ee4c3c73bfd 100644 --- a/apps/browser/src/autofill/overlay/pages/list/autofill-overlay-list.spec.ts +++ b/apps/browser/src/autofill/overlay/pages/list/autofill-overlay-list.spec.ts @@ -24,14 +24,11 @@ describe("AutofillOverlayList", () => { autofillOverlayList = document.querySelector("autofill-overlay-list"); autofillOverlayList["messageOrigin"] = "https://localhost/"; messageConnectorIframe = mock({ - contentWindow: { - postMessage: jest.fn(), - }, + contentWindow: { postMessage: jest.fn() }, }); autofillOverlayList["messageConnectorIframe"] = messageConnectorIframe; jest.spyOn(autofillOverlayList as any, "initMessageConnector").mockResolvedValue(undefined); jest.spyOn(globalThis.document, "createElement"); - jest.spyOn(globalThis.parent, "postMessage"); }); afterEach(() => {