1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 17:23:37 +00:00

[PM-5189] Fixing jest tests within AutofillOverlayPageElement

This commit is contained in:
Cesar Gonzalez
2024-04-08 11:04:16 -05:00
parent 4591d6ef9b
commit 6d1334b077
4 changed files with 62 additions and 56 deletions

View File

@@ -1,4 +1,4 @@
import { InlineMenuElements } from "../overlay/content/inline-menu-elements"; import { AutofillOverlayInlineMenuElements } from "../overlay/content/autofill-overlay-inline-menu-elements";
import AutofillOverlayContentService from "../services/autofill-overlay-content.service"; import AutofillOverlayContentService from "../services/autofill-overlay-content.service";
import { setupAutofillInitDisconnectAction } from "../utils"; import { setupAutofillInitDisconnectAction } from "../utils";
@@ -7,9 +7,9 @@ import AutofillInit from "./autofill-init";
(function (windowContext) { (function (windowContext) {
if (!windowContext.bitwardenAutofillInit) { if (!windowContext.bitwardenAutofillInit) {
const autofillOverlayContentService = new AutofillOverlayContentService(); const autofillOverlayContentService = new AutofillOverlayContentService();
let inlineMenuElements: InlineMenuElements; let inlineMenuElements: AutofillOverlayInlineMenuElements;
if (globalThis.self === globalThis.top) { if (globalThis.self === globalThis.top) {
inlineMenuElements = new InlineMenuElements(); inlineMenuElements = new AutofillOverlayInlineMenuElements();
} }
windowContext.bitwardenAutofillInit = new AutofillInit( windowContext.bitwardenAutofillInit = new AutofillInit(
autofillOverlayContentService, autofillOverlayContentService,

View File

@@ -12,7 +12,7 @@ import {
import AutofillOverlayButtonIframe from "../iframe-content/autofill-overlay-button-iframe"; import AutofillOverlayButtonIframe from "../iframe-content/autofill-overlay-button-iframe";
import AutofillOverlayListIframe from "../iframe-content/autofill-overlay-list-iframe"; import AutofillOverlayListIframe from "../iframe-content/autofill-overlay-list-iframe";
export class InlineMenuElements implements InlineMenuElementsInterface { export class AutofillOverlayInlineMenuElements implements InlineMenuElementsInterface {
private readonly sendExtensionMessage = sendExtensionMessage; private readonly sendExtensionMessage = sendExtensionMessage;
private readonly generateRandomCustomElementName = generateRandomCustomElementName; private readonly generateRandomCustomElementName = generateRandomCustomElementName;
private readonly setElementStyles = setElementStyles; private readonly setElementStyles = setElementStyles;

View File

@@ -12,6 +12,7 @@ describe("AutofillOverlayPageElement", () => {
buttonPageTitle: "buttonPageTitle", buttonPageTitle: "buttonPageTitle",
listPageTitle: "listPageTitle", listPageTitle: "listPageTitle",
}; };
const portKey = "portKey";
beforeEach(() => { beforeEach(() => {
jest.spyOn(globalThis.parent, "postMessage"); jest.spyOn(globalThis.parent, "postMessage");
@@ -19,6 +20,12 @@ describe("AutofillOverlayPageElement", () => {
jest.spyOn(globalThis.document, "addEventListener"); jest.spyOn(globalThis.document, "addEventListener");
document.body.innerHTML = "<autofill-overlay-page-element></autofill-overlay-page-element>"; document.body.innerHTML = "<autofill-overlay-page-element></autofill-overlay-page-element>";
autofillOverlayPageElement = document.querySelector("autofill-overlay-page-element"); autofillOverlayPageElement = document.querySelector("autofill-overlay-page-element");
autofillOverlayPageElement["messageConnectorIframe"] = mock<HTMLIFrameElement>({
contentWindow: {
postMessage: jest.fn(),
},
});
autofillOverlayPageElement["portKey"] = portKey;
}); });
afterEach(() => { afterEach(() => {
@@ -29,6 +36,9 @@ describe("AutofillOverlayPageElement", () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(globalThis.document.documentElement, "setAttribute"); jest.spyOn(globalThis.document.documentElement, "setAttribute");
jest.spyOn(globalThis.document, "createElement"); jest.spyOn(globalThis.document, "createElement");
jest
.spyOn(autofillOverlayPageElement as any, "initMessageConnector")
.mockResolvedValue(undefined);
}); });
it("initializes the button overlay page", async () => { it("initializes the button overlay page", async () => {
@@ -37,7 +47,7 @@ describe("AutofillOverlayPageElement", () => {
"https://jest-testing-website.com", "https://jest-testing-website.com",
translations, translations,
"https://jest-testing-website.com/message-connector", "https://jest-testing-website.com/message-connector",
"portKey", portKey,
); );
expect(globalThis.document.documentElement.setAttribute).toHaveBeenCalledWith( expect(globalThis.document.documentElement.setAttribute).toHaveBeenCalledWith(
@@ -52,20 +62,12 @@ describe("AutofillOverlayPageElement", () => {
}); });
describe("postMessageToConnector", () => { describe("postMessageToConnector", () => {
it("skips posting a message to the parent if the message origin in not set", () => {
autofillOverlayPageElement["postMessageToConnector"]({ command: "test" });
expect(globalThis.parent.postMessage).not.toHaveBeenCalled();
});
it("posts a message to the parent", () => { it("posts a message to the parent", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["postMessageToConnector"]({ command: "test" }); autofillOverlayPageElement["postMessageToConnector"]({ command: "test" });
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(
{ command: "test" }, autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage,
"https://jest-testing-website.com", ).toHaveBeenCalledWith({ command: "test", portKey }, "*");
);
}); });
}); });
@@ -151,17 +153,15 @@ describe("AutofillOverlayPageElement", () => {
}); });
it("posts a message to the parent when the window is blurred", () => { it("posts a message to the parent when the window is blurred", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["setupGlobalListeners"]( autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(), mock<OverlayButtonWindowMessageHandlers>(),
); );
globalThis.dispatchEvent(new Event("blur")); globalThis.dispatchEvent(new Event("blur"));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(
{ command: "overlayPageBlurred" }, autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage,
"https://jest-testing-website.com", ).toHaveBeenCalledWith({ command: "overlayPageBlurred", portKey }, "*");
);
}); });
it("skips redirecting keyboard focus when a KeyDown event triggers and the key is not a `Tab` or `Escape` key", () => { it("skips redirecting keyboard focus when a KeyDown event triggers and the key is not a `Tab` or `Escape` key", () => {
@@ -184,9 +184,11 @@ describe("AutofillOverlayPageElement", () => {
new KeyboardEvent("keydown", { code: "Tab", shiftKey: true }), new KeyboardEvent("keydown", { code: "Tab", shiftKey: true }),
); );
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(
{ command: "redirectOverlayFocusOut", direction: "previous" }, autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage,
"https://jest-testing-website.com", ).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "previous", portKey },
"*",
); );
}); });
@@ -198,9 +200,11 @@ describe("AutofillOverlayPageElement", () => {
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Tab" })); globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Tab" }));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(
{ command: "redirectOverlayFocusOut", direction: "next" }, autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage,
"https://jest-testing-website.com", ).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "next", portKey },
"*",
); );
}); });
@@ -212,9 +216,11 @@ describe("AutofillOverlayPageElement", () => {
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" })); globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" }));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith( expect(
{ command: "redirectOverlayFocusOut", direction: "current" }, autofillOverlayPageElement["messageConnectorIframe"].contentWindow.postMessage,
"https://jest-testing-website.com", ).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "current", portKey },
"*",
); );
}); });
}); });

View File

@@ -43,28 +43,7 @@ class AutofillOverlayPageElement extends HTMLElement {
globalThis.document.documentElement.setAttribute("lang", this.getTranslation("locale")); globalThis.document.documentElement.setAttribute("lang", this.getTranslation("locale"));
globalThis.document.head.title = this.getTranslation(`${elementName}PageTitle`); globalThis.document.head.title = this.getTranslation(`${elementName}PageTitle`);
this.messageConnectorIframe = globalThis.document.createElement("iframe"); await this.initMessageConnector(messageConnectorUrl, elementName);
this.messageConnectorIframe.src = messageConnectorUrl;
this.messageConnectorIframe.style.opacity = "0";
this.messageConnectorIframe.style.position = "absolute";
this.messageConnectorIframe.style.width = "0";
this.messageConnectorIframe.style.height = "0";
this.messageConnectorIframe.style.border = "none";
this.messageConnectorIframe.style.pointerEvents = "none";
globalThis.document.body.appendChild(this.messageConnectorIframe);
await new Promise<void>((resolve) => {
this.messageConnectorIframe.addEventListener(EVENTS.LOAD, () => {
this.postMessageToConnector({
command: `initAutofillOverlayPort`,
portName:
elementName === "list"
? AutofillOverlayPort.ListMessageConnector
: AutofillOverlayPort.ButtonMessageConnector,
});
resolve();
});
});
this.shadowDom.innerHTML = ""; this.shadowDom.innerHTML = "";
const linkElement = globalThis.document.createElement("link"); const linkElement = globalThis.document.createElement("link");
@@ -80,10 +59,6 @@ class AutofillOverlayPageElement extends HTMLElement {
* @param message - The message to post * @param message - The message to post
*/ */
protected postMessageToConnector(message: AutofillOverlayPageElementWindowMessage) { protected postMessageToConnector(message: AutofillOverlayPageElementWindowMessage) {
if (!this.messageOrigin) {
return;
}
this.messageConnectorIframe.contentWindow.postMessage( this.messageConnectorIframe.contentWindow.postMessage(
{ portKey: this.portKey, ...message }, { portKey: this.portKey, ...message },
"*", "*",
@@ -184,6 +159,31 @@ class AutofillOverlayPageElement extends HTMLElement {
private redirectOverlayFocusOutMessage(direction: string) { private redirectOverlayFocusOutMessage(direction: string) {
this.postMessageToConnector({ command: "redirectOverlayFocusOut", direction }); this.postMessageToConnector({ command: "redirectOverlayFocusOut", direction });
} }
private initMessageConnector(messageConnectorUrl: string, elementName: "button" | "list") {
this.messageConnectorIframe = globalThis.document.createElement("iframe");
this.messageConnectorIframe.src = messageConnectorUrl;
this.messageConnectorIframe.style.opacity = "0";
this.messageConnectorIframe.style.position = "absolute";
this.messageConnectorIframe.style.width = "0";
this.messageConnectorIframe.style.height = "0";
this.messageConnectorIframe.style.border = "none";
this.messageConnectorIframe.style.pointerEvents = "none";
globalThis.document.body.appendChild(this.messageConnectorIframe);
return new Promise<void>((resolve) => {
this.messageConnectorIframe.addEventListener(EVENTS.LOAD, () => {
this.postMessageToConnector({
command: `initAutofillOverlayPort`,
portName:
elementName === "list"
? AutofillOverlayPort.ListMessageConnector
: AutofillOverlayPort.ButtonMessageConnector,
});
resolve();
});
});
}
} }
export default AutofillOverlayPageElement; export default AutofillOverlayPageElement;