bitwarden-browser/apps/browser/src/autofill/overlay/pages/shared/autofill-overlay-page-eleme...

220 lines
8.2 KiB
TypeScript

import { mock } from "jest-mock-extended";
import { OverlayButtonWindowMessageHandlers } from "../../abstractions/autofill-overlay-button";
import AutofillOverlayPageElement from "./autofill-overlay-page-element";
describe("AutofillOverlayPageElement", () => {
globalThis.customElements.define("autofill-overlay-page-element", AutofillOverlayPageElement);
let autofillOverlayPageElement: AutofillOverlayPageElement;
const translations = {
locale: "en",
buttonPageTitle: "buttonPageTitle",
listPageTitle: "listPageTitle",
};
beforeEach(() => {
jest.spyOn(globalThis.parent, "postMessage");
jest.spyOn(globalThis, "addEventListener");
jest.spyOn(globalThis.document, "addEventListener");
document.body.innerHTML = "<autofill-overlay-page-element></autofill-overlay-page-element>";
autofillOverlayPageElement = document.querySelector("autofill-overlay-page-element");
});
afterEach(() => {
jest.clearAllMocks();
});
describe("initOverlayPage", () => {
beforeEach(() => {
jest.spyOn(globalThis.document.documentElement, "setAttribute");
jest.spyOn(globalThis.document, "createElement");
});
it("initializes the button overlay page", () => {
const linkElement = autofillOverlayPageElement["initOverlayPage"](
"button",
"https://jest-testing-website.com",
translations,
);
expect(globalThis.document.documentElement.setAttribute).toHaveBeenCalledWith(
"lang",
translations.locale,
);
expect(globalThis.document.head.title).toEqual(translations.buttonPageTitle);
expect(globalThis.document.createElement).toHaveBeenCalledWith("link");
expect(linkElement.getAttribute("rel")).toEqual("stylesheet");
expect(linkElement.getAttribute("href")).toEqual("https://jest-testing-website.com");
});
});
describe("postMessageToParent", () => {
it("skips posting a message to the parent if the message origin in not set", () => {
autofillOverlayPageElement["postMessageToParent"]({ command: "test" });
expect(globalThis.parent.postMessage).not.toHaveBeenCalled();
});
it("posts a message to the parent", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["postMessageToParent"]({ command: "test" });
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "test" },
"https://jest-testing-website.com",
);
});
});
describe("getTranslation", () => {
it("returns an empty value if the translation doesn't exist in the translations object", () => {
autofillOverlayPageElement["translations"] = translations;
expect(autofillOverlayPageElement["getTranslation"]("test")).toEqual("");
});
});
describe("global event listeners", () => {
it("sets up global event listeners", () => {
const handleWindowMessageSpy = jest.spyOn(
autofillOverlayPageElement as any,
"handleWindowMessage",
);
const handleWindowBlurEventSpy = jest.spyOn(
autofillOverlayPageElement as any,
"handleWindowBlurEvent",
);
const handleDocumentKeyDownEventSpy = jest.spyOn(
autofillOverlayPageElement as any,
"handleDocumentKeyDownEvent",
);
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(),
);
expect(globalThis.addEventListener).toHaveBeenCalledWith("message", handleWindowMessageSpy);
expect(globalThis.addEventListener).toHaveBeenCalledWith("blur", handleWindowBlurEventSpy);
expect(globalThis.document.addEventListener).toHaveBeenCalledWith(
"keydown",
handleDocumentKeyDownEventSpy,
);
});
it("sets the message origin when handling the first passed window message", () => {
const initAutofillOverlayButtonSpy = jest.fn();
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>({
initAutofillOverlayButton: initAutofillOverlayButtonSpy,
}),
);
globalThis.dispatchEvent(
new MessageEvent("message", {
data: { command: "initAutofillOverlayButton" },
origin: "https://jest-testing-website.com",
}),
);
expect(autofillOverlayPageElement["messageOrigin"]).toEqual(
"https://jest-testing-website.com",
);
});
it("handles window messages that are part of the passed windowMessageHandlers object", () => {
const initAutofillOverlayButtonSpy = jest.fn();
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>({
initAutofillOverlayButton: initAutofillOverlayButtonSpy,
}),
);
const data = { command: "initAutofillOverlayButton" };
globalThis.dispatchEvent(new MessageEvent("message", { data }));
expect(initAutofillOverlayButtonSpy).toHaveBeenCalledWith({ message: data });
});
it("skips attempting to handle window messages that are not part of the passed windowMessageHandlers object", () => {
const initAutofillOverlayButtonSpy = jest.fn();
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>({
initAutofillOverlayButton: initAutofillOverlayButtonSpy,
}),
);
globalThis.dispatchEvent(new MessageEvent("message", { data: { command: "test" } }));
expect(initAutofillOverlayButtonSpy).not.toHaveBeenCalled();
});
it("posts a message to the parent when the window is blurred", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(),
);
globalThis.dispatchEvent(new Event("blur"));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "overlayPageBlurred" },
"https://jest-testing-website.com",
);
});
it("skips redirecting keyboard focus when a KeyDown event triggers and the key is not a `Tab` or `Escape` key", () => {
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(),
);
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "test" }));
expect(globalThis.parent.postMessage).not.toHaveBeenCalled();
});
it("redirects the overlay focus out to the previous element on KeyDown of the `Tab+Shift` keys", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(),
);
globalThis.document.dispatchEvent(
new KeyboardEvent("keydown", { code: "Tab", shiftKey: true }),
);
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "previous" },
"https://jest-testing-website.com",
);
});
it("redirects the overlay focus out to the next element on KeyDown of the `Tab` key", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(),
);
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Tab" }));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "next" },
"https://jest-testing-website.com",
);
});
it("redirects the overlay focus out to the current element on KeyDown of the `Escape` key", () => {
autofillOverlayPageElement["messageOrigin"] = "https://jest-testing-website.com";
autofillOverlayPageElement["setupGlobalListeners"](
mock<OverlayButtonWindowMessageHandlers>(),
);
globalThis.document.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" }));
expect(globalThis.parent.postMessage).toHaveBeenCalledWith(
{ command: "redirectOverlayFocusOut", direction: "current" },
"https://jest-testing-website.com",
);
});
});
});