mirror of
https://github.com/bitwarden/browser
synced 2026-02-06 11:43:51 +00:00
add tests
This commit is contained in:
@@ -347,6 +347,18 @@ describe("AutofillInit", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("removes the LOAD event listener", () => {
|
||||
jest.spyOn(window, "removeEventListener");
|
||||
|
||||
autofillInit.init();
|
||||
autofillInit.destroy();
|
||||
|
||||
expect(window.removeEventListener).toHaveBeenCalledWith(
|
||||
"load",
|
||||
autofillInit["sendCollectDetailsMessage"],
|
||||
);
|
||||
});
|
||||
|
||||
it("removes the extension message listeners", () => {
|
||||
autofillInit.destroy();
|
||||
|
||||
|
||||
@@ -645,6 +645,292 @@ describe("AutofillInlineMenuContentService", () => {
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("unobserves custom elements", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["inlineMenuElementsMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService.destroy();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("unobserves the container element", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["containerElementMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService.destroy();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("clears the mutation observer iterations reset timeout", () => {
|
||||
jest.useFakeTimers();
|
||||
const clearTimeoutSpy = jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuContentService["mutationObserverIterationsResetTimeout"] = setTimeout(
|
||||
jest.fn(),
|
||||
1000,
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService.destroy();
|
||||
|
||||
expect(clearTimeoutSpy).toHaveBeenCalled();
|
||||
expect(autofillInlineMenuContentService["mutationObserverIterationsResetTimeout"]).toBeNull();
|
||||
});
|
||||
|
||||
it("destroys the button iframe", () => {
|
||||
const mockButtonIframe = { destroy: jest.fn() };
|
||||
autofillInlineMenuContentService["buttonIframe"] = mockButtonIframe as any;
|
||||
|
||||
autofillInlineMenuContentService.destroy();
|
||||
|
||||
expect(mockButtonIframe.destroy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("destroys the list iframe", () => {
|
||||
const mockListIframe = { destroy: jest.fn() };
|
||||
autofillInlineMenuContentService["listIframe"] = mockListIframe as any;
|
||||
|
||||
autofillInlineMenuContentService.destroy();
|
||||
|
||||
expect(mockListIframe.destroy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("observeCustomElements", () => {
|
||||
it("observes the button element for attribute mutations", () => {
|
||||
const buttonElement = document.createElement("div");
|
||||
autofillInlineMenuContentService["buttonElement"] = buttonElement;
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["inlineMenuElementsMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["observeCustomElements"]();
|
||||
|
||||
expect(observeSpy).toHaveBeenCalledWith(buttonElement, { attributes: true });
|
||||
});
|
||||
|
||||
it("observes the list element for attribute mutations", () => {
|
||||
const listElement = document.createElement("div");
|
||||
autofillInlineMenuContentService["listElement"] = listElement;
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["inlineMenuElementsMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["observeCustomElements"]();
|
||||
|
||||
expect(observeSpy).toHaveBeenCalledWith(listElement, { attributes: true });
|
||||
});
|
||||
|
||||
it("does not observe when no elements exist", () => {
|
||||
autofillInlineMenuContentService["buttonElement"] = undefined;
|
||||
autofillInlineMenuContentService["listElement"] = undefined;
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["inlineMenuElementsMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["observeCustomElements"]();
|
||||
|
||||
expect(observeSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("observeContainerElement", () => {
|
||||
it("observes the container element for child list mutations", () => {
|
||||
const containerElement = document.createElement("div");
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["containerElementMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["observeContainerElement"](containerElement);
|
||||
|
||||
expect(observeSpy).toHaveBeenCalledWith(containerElement, { childList: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("unobserveContainerElement", () => {
|
||||
it("disconnects the container element mutation observer", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["containerElementMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["unobserveContainerElement"]();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles the case when the mutation observer is undefined", () => {
|
||||
autofillInlineMenuContentService["containerElementMutationObserver"] = undefined as any;
|
||||
|
||||
expect(() => autofillInlineMenuContentService["unobserveContainerElement"]()).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("observePageAttributes", () => {
|
||||
it("observes the document element for attribute mutations", () => {
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["htmlMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["observePageAttributes"]();
|
||||
|
||||
expect(observeSpy).toHaveBeenCalledWith(document.documentElement, { attributes: true });
|
||||
});
|
||||
|
||||
it("observes the body element for attribute mutations", () => {
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["bodyMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["observePageAttributes"]();
|
||||
|
||||
expect(observeSpy).toHaveBeenCalledWith(document.body, { attributes: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("unobservePageAttributes", () => {
|
||||
it("disconnects the html mutation observer", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["htmlMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["unobservePageAttributes"]();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("disconnects the body mutation observer", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["bodyMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["unobservePageAttributes"]();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("checkPageRisks", () => {
|
||||
it("returns true and closes inline menu when page is not opaque", async () => {
|
||||
jest.spyOn(autofillInlineMenuContentService as any, "getPageIsOpaque").mockReturnValue(false);
|
||||
const closeInlineMenuSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService as any,
|
||||
"closeInlineMenu",
|
||||
);
|
||||
|
||||
const result = await autofillInlineMenuContentService["checkPageRisks"]();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(closeInlineMenuSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns true and closes inline menu when inline menu is disabled", async () => {
|
||||
jest.spyOn(autofillInlineMenuContentService as any, "getPageIsOpaque").mockReturnValue(true);
|
||||
autofillInlineMenuContentService["inlineMenuEnabled"] = false;
|
||||
const closeInlineMenuSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService as any,
|
||||
"closeInlineMenu",
|
||||
);
|
||||
|
||||
const result = await autofillInlineMenuContentService["checkPageRisks"]();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(closeInlineMenuSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns false when page is opaque and inline menu is enabled", async () => {
|
||||
jest.spyOn(autofillInlineMenuContentService as any, "getPageIsOpaque").mockReturnValue(true);
|
||||
autofillInlineMenuContentService["inlineMenuEnabled"] = true;
|
||||
const closeInlineMenuSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService as any,
|
||||
"closeInlineMenu",
|
||||
);
|
||||
|
||||
const result = await autofillInlineMenuContentService["checkPageRisks"]();
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(closeInlineMenuSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("handlePageMutations", () => {
|
||||
it("checks page risks when mutations include attribute changes", async () => {
|
||||
const checkPageRisksSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService as any,
|
||||
"checkPageRisks",
|
||||
);
|
||||
const mutations = [{ type: "attributes" } as MutationRecord];
|
||||
|
||||
await autofillInlineMenuContentService["handlePageMutations"](mutations);
|
||||
|
||||
expect(checkPageRisksSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not check page risks when mutations do not include attribute changes", async () => {
|
||||
const checkPageRisksSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService as any,
|
||||
"checkPageRisks",
|
||||
);
|
||||
const mutations = [{ type: "childList" } as MutationRecord];
|
||||
|
||||
await autofillInlineMenuContentService["handlePageMutations"](mutations);
|
||||
|
||||
expect(checkPageRisksSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearPersistentLastChildOverrideTimeout", () => {
|
||||
it("clears the timeout when it exists", () => {
|
||||
jest.useFakeTimers();
|
||||
const clearTimeoutSpy = jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuContentService["handlePersistentLastChildOverrideTimeout"] = setTimeout(
|
||||
jest.fn(),
|
||||
1000,
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["clearPersistentLastChildOverrideTimeout"]();
|
||||
|
||||
expect(clearTimeoutSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does nothing when the timeout is null", () => {
|
||||
const clearTimeoutSpy = jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuContentService["handlePersistentLastChildOverrideTimeout"] = null;
|
||||
|
||||
autofillInlineMenuContentService["clearPersistentLastChildOverrideTimeout"]();
|
||||
|
||||
expect(clearTimeoutSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("elementAtCenterOfInlineMenuPosition", () => {
|
||||
it("returns the element at the center of the given position", () => {
|
||||
const mockElement = document.createElement("div");
|
||||
jest.spyOn(globalThis.document, "elementFromPoint").mockReturnValue(mockElement);
|
||||
|
||||
const result = autofillInlineMenuContentService["elementAtCenterOfInlineMenuPosition"]({
|
||||
top: 100,
|
||||
left: 200,
|
||||
width: 50,
|
||||
height: 30,
|
||||
});
|
||||
|
||||
expect(globalThis.document.elementFromPoint).toHaveBeenCalledWith(225, 115);
|
||||
expect(result).toBe(mockElement);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getOwnedTagNames", () => {
|
||||
@@ -975,6 +1261,25 @@ describe("AutofillInlineMenuContentService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("unobserveCustomElements", () => {
|
||||
it("disconnects the inline menu elements mutation observer", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuContentService["inlineMenuElementsMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuContentService["unobserveCustomElements"]();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles the case when the mutation observer is undefined", () => {
|
||||
autofillInlineMenuContentService["inlineMenuElementsMutationObserver"] = undefined as any;
|
||||
|
||||
expect(() => autofillInlineMenuContentService["unobserveCustomElements"]()).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPageIsOpaque", () => {
|
||||
it("returns false when no page elements exist", () => {
|
||||
jest.spyOn(globalThis.document, "querySelectorAll").mockReturnValue([] as any);
|
||||
|
||||
@@ -752,4 +752,164 @@ describe("AutofillInlineMenuIframeService", () => {
|
||||
expect(autofillInlineMenuIframeService["iframe"].title).toBe("title");
|
||||
});
|
||||
});
|
||||
|
||||
describe("destroy", () => {
|
||||
beforeEach(() => {
|
||||
autofillInlineMenuIframeService.initMenuIframe();
|
||||
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
||||
portSpy = autofillInlineMenuIframeService["port"];
|
||||
});
|
||||
|
||||
it("removes the LOAD event listener from the iframe", () => {
|
||||
const removeEventListenerSpy = jest.spyOn(
|
||||
autofillInlineMenuIframeService["iframe"],
|
||||
"removeEventListener",
|
||||
);
|
||||
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(removeEventListenerSpy).toHaveBeenCalledWith(
|
||||
EVENTS.LOAD,
|
||||
autofillInlineMenuIframeService["setupPortMessageListener"],
|
||||
);
|
||||
});
|
||||
|
||||
it("clears the aria alert timeout", () => {
|
||||
jest.spyOn(autofillInlineMenuIframeService, "clearAriaAlert");
|
||||
autofillInlineMenuIframeService["ariaAlertTimeout"] = setTimeout(jest.fn(), 1000);
|
||||
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(autofillInlineMenuIframeService.clearAriaAlert).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("clears the fade in timeout", () => {
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuIframeService["fadeInTimeout"] = setTimeout(jest.fn(), 1000);
|
||||
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(globalThis.clearTimeout).toHaveBeenCalled();
|
||||
expect(autofillInlineMenuIframeService["fadeInTimeout"]).toBeNull();
|
||||
});
|
||||
|
||||
it("clears the delayed close timeout", () => {
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuIframeService["delayedCloseTimeout"] = setTimeout(jest.fn(), 1000);
|
||||
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(globalThis.clearTimeout).toHaveBeenCalled();
|
||||
expect(autofillInlineMenuIframeService["delayedCloseTimeout"]).toBeNull();
|
||||
});
|
||||
|
||||
it("clears the mutation observer iterations reset timeout", () => {
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuIframeService["mutationObserverIterationsResetTimeout"] = setTimeout(
|
||||
jest.fn(),
|
||||
1000,
|
||||
);
|
||||
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(globalThis.clearTimeout).toHaveBeenCalled();
|
||||
expect(autofillInlineMenuIframeService["mutationObserverIterationsResetTimeout"]).toBeNull();
|
||||
});
|
||||
|
||||
it("unobserves the iframe mutation observer", () => {
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuIframeService["iframeMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("removes the port message listeners and disconnects the port", () => {
|
||||
autofillInlineMenuIframeService.destroy();
|
||||
|
||||
expect(portSpy.onMessage.removeListener).toHaveBeenCalledWith(handlePortMessageSpy);
|
||||
expect(portSpy.onDisconnect.removeListener).toHaveBeenCalledWith(handlePortDisconnectSpy);
|
||||
expect(portSpy.disconnect).toHaveBeenCalled();
|
||||
expect(autofillInlineMenuIframeService["port"]).toBeNull();
|
||||
});
|
||||
|
||||
it("handles the case when the port is null", () => {
|
||||
autofillInlineMenuIframeService["port"] = null;
|
||||
|
||||
expect(() => autofillInlineMenuIframeService.destroy()).not.toThrow();
|
||||
});
|
||||
|
||||
it("handles the case when the iframe is undefined", () => {
|
||||
autofillInlineMenuIframeService["iframe"] = undefined as any;
|
||||
|
||||
expect(() => autofillInlineMenuIframeService.destroy()).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("clearAriaAlert", () => {
|
||||
it("clears the aria alert timeout when it exists", () => {
|
||||
jest.useFakeTimers();
|
||||
jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuIframeService["ariaAlertTimeout"] = setTimeout(jest.fn(), 1000);
|
||||
|
||||
autofillInlineMenuIframeService.clearAriaAlert();
|
||||
|
||||
expect(globalThis.clearTimeout).toHaveBeenCalled();
|
||||
expect(autofillInlineMenuIframeService["ariaAlertTimeout"]).toBeNull();
|
||||
});
|
||||
|
||||
it("does nothing when the aria alert timeout is null", () => {
|
||||
jest.spyOn(globalThis, "clearTimeout");
|
||||
autofillInlineMenuIframeService["ariaAlertTimeout"] = null;
|
||||
|
||||
autofillInlineMenuIframeService.clearAriaAlert();
|
||||
|
||||
expect(globalThis.clearTimeout).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("unobserveIframe", () => {
|
||||
it("disconnects the iframe mutation observer", () => {
|
||||
autofillInlineMenuIframeService.initMenuIframe();
|
||||
const disconnectSpy = jest.spyOn(
|
||||
autofillInlineMenuIframeService["iframeMutationObserver"],
|
||||
"disconnect",
|
||||
);
|
||||
|
||||
autofillInlineMenuIframeService["unobserveIframe"]();
|
||||
|
||||
expect(disconnectSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles the case when the mutation observer is undefined", () => {
|
||||
autofillInlineMenuIframeService["iframeMutationObserver"] = undefined as any;
|
||||
|
||||
expect(() => autofillInlineMenuIframeService["unobserveIframe"]()).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("observeIframe", () => {
|
||||
beforeEach(() => {
|
||||
autofillInlineMenuIframeService.initMenuIframe();
|
||||
});
|
||||
|
||||
it("observes the iframe for attribute mutations", () => {
|
||||
const observeSpy = jest.spyOn(
|
||||
autofillInlineMenuIframeService["iframeMutationObserver"],
|
||||
"observe",
|
||||
);
|
||||
|
||||
autofillInlineMenuIframeService["observeIframe"]();
|
||||
|
||||
expect(observeSpy).toHaveBeenCalledWith(autofillInlineMenuIframeService["iframe"], {
|
||||
attributes: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user