[PM-5189] Reworking project structure to ensure we can better differentiate the inline menu feature from other features

This commit is contained in:
Cesar Gonzalez 2024-05-03 14:08:03 -05:00
parent 4aebbc0a64
commit 4038939f46
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
26 changed files with 725 additions and 203 deletions

View File

@ -236,7 +236,7 @@ describe("OverlayBackground", () => {
expect(overlayBackground["getOverlayCipherData"]).toHaveBeenCalled();
});
it("posts an `updateOverlayListCiphers` message to the overlay list port with the updated ciphers", async () => {
it("posts an `updateAutofillInlineMenuListCiphers` message to the overlay list port with the updated ciphers", async () => {
overlayBackground["inlineMenuListPort"] = mock<chrome.runtime.Port>();
cipherService.getAllDecryptedForUrl.mockResolvedValue([cipher1, cipher2]);
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
@ -246,7 +246,7 @@ describe("OverlayBackground", () => {
await overlayBackground.updateOverlayCiphers();
expect(overlayBackground["inlineMenuListPort"].postMessage).toHaveBeenCalledWith({
command: "updateOverlayListCiphers",
command: "updateAutofillInlineMenuListCiphers",
ciphers: [
{
card: null,

View File

@ -190,7 +190,10 @@ class OverlayBackground implements OverlayBackgroundInterface {
}
const ciphers = await this.getOverlayCipherData();
this.inlineMenuListPort?.postMessage({ command: "updateOverlayListCiphers", ciphers });
this.inlineMenuListPort?.postMessage({
command: "updateAutofillInlineMenuListCiphers",
ciphers,
});
}
/**

View File

@ -1,13 +1,13 @@
const AutofillOverlayElement = {
Button: "autofill-inline-menu-button",
List: "autofill-overlay-list",
List: "autofill-inline-menu-list",
} as const;
const AutofillOverlayPort = {
Button: "autofill-inline-menu-button-port",
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
List: "autofill-overlay-list-port",
ListMessageConnector: "autofill-overlay-list-message-connector",
List: "autofill-inline-menu-list-port",
ListMessageConnector: "autofill-inline-menu-list-message-connector",
} as const;
const RedirectFocusDirection = {

View File

@ -1,18 +1,18 @@
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
type AutofillInlineMenuButtonMessage = { command: string; colorScheme?: string };
export type AutofillInlineMenuButtonMessage = { command: string; colorScheme?: string };
type UpdateAuthStatusMessage = AutofillInlineMenuButtonMessage & {
export type UpdateAuthStatusMessage = AutofillInlineMenuButtonMessage & {
authStatus: AuthenticationStatus;
};
type InitAutofillInlineMenuButtonMessage = UpdateAuthStatusMessage & {
export type InitAutofillInlineMenuButtonMessage = UpdateAuthStatusMessage & {
styleSheetUrl: string;
translations: Record<string, string>;
portKey: string;
};
type AutofillInlineMenuButtonWindowMessageHandlers = {
export type AutofillInlineMenuButtonWindowMessageHandlers = {
[key: string]: CallableFunction;
initAutofillInlineMenuButton: ({
message,
@ -31,10 +31,3 @@ type AutofillInlineMenuButtonWindowMessageHandlers = {
message: AutofillInlineMenuButtonMessage;
}) => void;
};
export {
UpdateAuthStatusMessage,
AutofillInlineMenuButtonMessage,
InitAutofillInlineMenuButtonMessage,
AutofillInlineMenuButtonWindowMessageHandlers,
};

View File

@ -2,12 +2,12 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { OverlayCipherData } from "../../../background/abstractions/overlay.background";
type AutofillOverlayMenuContainerMessage = {
type AutofillInlineMenuMenuContainerMessage = {
command: string;
portKey: string;
};
export type InitOverlayElementMessage = AutofillOverlayMenuContainerMessage & {
export type InitInlineMenuElementMessage = AutofillInlineMenuMenuContainerMessage & {
iframeUrl?: string;
pageTitle?: string;
authStatus?: AuthenticationStatus;
@ -18,8 +18,8 @@ export type InitOverlayElementMessage = AutofillOverlayMenuContainerMessage & {
portName?: string;
};
export type AutofillOverlayMenuContainerWindowMessageHandlers = {
export type AutofillInlineMenuMenuContainerWindowMessageHandlers = {
[key: string]: CallableFunction;
initAutofillInlineMenuList: (message: InitOverlayElementMessage) => void;
initAutofillInlineMenuButton: (message: InitOverlayElementMessage) => void;
initAutofillInlineMenuList: (message: InitInlineMenuElementMessage) => void;
initAutofillInlineMenuButton: (message: InitInlineMenuElementMessage) => void;
};

View File

@ -1,35 +1,25 @@
type AutofillOverlayIframeExtensionMessage = {
export type AutofillInlineMenuIframeExtensionMessage = {
command: string;
styles?: Partial<CSSStyleDeclaration>;
theme?: string;
portKey?: string;
};
type AutofillOverlayIframeWindowMessageHandlers = {
[key: string]: CallableFunction;
updateAutofillInlineMenuListHeight: (message: AutofillOverlayIframeExtensionMessage) => void;
export type AutofillInlineMenuIframeExtensionMessageParam = {
message: AutofillInlineMenuIframeExtensionMessage;
};
type AutofillOverlayIframeExtensionMessageParam = {
message: AutofillOverlayIframeExtensionMessage;
};
type BackgroundPortMessageHandlers = {
export type BackgroundPortMessageHandlers = {
[key: string]: CallableFunction;
initAutofillInlineMenuButton: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
initAutofillInlineMenuList: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
updateIframePosition: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
updateInlineMenuHidden: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
initAutofillInlineMenuButton: ({
message,
}: AutofillInlineMenuIframeExtensionMessageParam) => void;
initAutofillInlineMenuList: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateIframePosition: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateInlineMenuHidden: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
updateAutofillInlineMenuColorScheme: () => void;
};
interface AutofillInlineMenuIframeService {
export interface AutofillInlineMenuIframeService {
initMenuIframe(): void;
}
export {
AutofillOverlayIframeExtensionMessage,
AutofillOverlayIframeWindowMessageHandlers,
BackgroundPortMessageHandlers,
AutofillInlineMenuIframeService,
};

View File

@ -2,13 +2,13 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { OverlayCipherData } from "../../../background/abstractions/overlay.background";
type OverlayListMessage = { command: string };
type AutofillInlineMenuListMessage = { command: string };
type UpdateOverlayListCiphersMessage = OverlayListMessage & {
export type UpdateAutofillInlineMenuListCiphersMessage = AutofillInlineMenuListMessage & {
ciphers: OverlayCipherData[];
};
type InitAutofillOverlayListMessage = OverlayListMessage & {
export type InitAutofillInlineMenuListMessage = AutofillInlineMenuListMessage & {
authStatus: AuthenticationStatus;
styleSheetUrl: string;
theme: string;
@ -17,16 +17,14 @@ type InitAutofillOverlayListMessage = OverlayListMessage & {
portKey: string;
};
type OverlayListWindowMessageHandlers = {
export type AutofillInlineMenuListWindowMessageHandlers = {
[key: string]: CallableFunction;
initAutofillInlineMenuList: ({ message }: { message: InitAutofillOverlayListMessage }) => void;
initAutofillInlineMenuList: ({ message }: { message: InitAutofillInlineMenuListMessage }) => void;
checkAutofillInlineMenuListFocused: () => void;
updateOverlayListCiphers: ({ message }: { message: UpdateOverlayListCiphersMessage }) => void;
updateAutofillInlineMenuListCiphers: ({
message,
}: {
message: UpdateAutofillInlineMenuListCiphersMessage;
}) => void;
focusInlineMenuList: () => void;
};
export {
UpdateOverlayListCiphersMessage,
InitAutofillOverlayListMessage,
OverlayListWindowMessageHandlers,
};

View File

@ -1,18 +1,13 @@
import { AutofillInlineMenuButtonWindowMessageHandlers } from "./autofill-inline-menu-button";
import { OverlayListWindowMessageHandlers } from "./autofill-inline-menu-list";
import { AutofillInlineMenuListWindowMessageHandlers } from "./autofill-inline-menu-list";
type AutofillInlineMenuPageElementWindowMessageHandlers =
export type AutofillInlineMenuPageElementWindowMessageHandlers =
| AutofillInlineMenuButtonWindowMessageHandlers
| OverlayListWindowMessageHandlers;
| AutofillInlineMenuListWindowMessageHandlers;
type AutofillInlineMenuPageElementWindowMessage = {
export type AutofillInlineMenuPageElementWindowMessage = {
[key: string]: any;
command: string;
overlayCipherId?: string;
height?: number;
};
export {
AutofillInlineMenuPageElementWindowMessageHandlers,
AutofillInlineMenuPageElementWindowMessage,
};

View File

@ -10,7 +10,7 @@ import {
AutofillInlineMenuContentService as AutofillInlineMenuContentServiceInterface,
} from "../abstractions/autofill-inline-menu-content.service";
import { AutofillInlineMenuButtonIframe } from "../iframe-content/autofill-inline-menu-button-iframe";
import AutofillInlineMenuListIframe from "../iframe-content/autofill-inline-menu-list-iframe";
import { AutofillInlineMenuListIframe } from "../iframe-content/autofill-inline-menu-list-iframe";
export class AutofillInlineMenuContentService implements AutofillInlineMenuContentServiceInterface {
private readonly sendExtensionMessage = sendExtensionMessage;

View File

@ -1,5 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AutofillInlineMenuIframeService initMenuIframe sets up the iframe's attributes 1`] = `
<iframe
allowtransparency="true"
src="chrome-extension://id/overlay/menu.html"
style="all: initial !important; position: fixed !important; display: block !important; z-index: 2147483647 !important; line-height: 0 !important; overflow: hidden !important; transition: opacity 125ms ease-out 0s !important; visibility: visible !important; clip-path: none !important; pointer-events: auto !important; margin: 0px !important; padding: 0px !important; color-scheme: normal !important; opacity: 0 !important; height: 0px;"
tabindex="-1"
title="title"
/>
`;
exports[`AutofillOverlayIframeService initMenuIframe sets up the iframe's attributes 1`] = `
<iframe
allowtransparency="true"

View File

@ -15,7 +15,7 @@ describe("AutofillInlineMenuIframeElement", () => {
this,
AutofillOverlayPort.Button,
{ background: "transparent", border: "none" },
"bitwardenOverlayButton",
"bitwardenInlineMenuButton",
);
}
},
@ -41,7 +41,7 @@ describe("AutofillInlineMenuIframeElement", () => {
expect(iframe.shadowRoot).toBeNull();
});
it("instantiates the autofill overlay iframe service for each attached custom element", () => {
it("instantiates the autofill inline menu iframe service for each attached custom element", () => {
expect(AutofillInlineMenuIframeService).toHaveBeenCalledTimes(2);
});
});

View File

@ -9,13 +9,13 @@ export class AutofillInlineMenuIframeElement {
ariaAlert?: string,
) {
const shadow: ShadowRoot = element.attachShadow({ mode: "closed" });
const autofillOverlayIframeService = new AutofillInlineMenuIframeService(
const autofillInlineMenuIframeService = new AutofillInlineMenuIframeService(
shadow,
portName,
initStyles,
iframeTitle,
ariaAlert,
);
autofillOverlayIframeService.initMenuIframe();
autofillInlineMenuIframeService.initMenuIframe();
}
}

View File

@ -13,8 +13,8 @@ import {
import { AutofillInlineMenuIframeService } from "./autofill-inline-menu-iframe.service";
describe("AutofillOverlayIframeService", () => {
let autofillOverlayIframeService: AutofillInlineMenuIframeService;
describe("AutofillInlineMenuIframeService", () => {
let autofillInlineMenuIframeService: AutofillInlineMenuIframeService;
let portSpy: chrome.runtime.Port;
let shadowAppendSpy: jest.SpyInstance;
let handlePortDisconnectSpy: jest.SpyInstance;
@ -23,7 +23,7 @@ describe("AutofillOverlayIframeService", () => {
beforeEach(() => {
const shadow = document.createElement("div").attachShadow({ mode: "open" });
autofillOverlayIframeService = new AutofillInlineMenuIframeService(
autofillInlineMenuIframeService = new AutofillInlineMenuIframeService(
shadow,
AutofillOverlayPort.Button,
{ height: "0px" },
@ -32,15 +32,15 @@ describe("AutofillOverlayIframeService", () => {
);
shadowAppendSpy = jest.spyOn(shadow, "appendChild");
handlePortDisconnectSpy = jest.spyOn(
autofillOverlayIframeService as any,
autofillInlineMenuIframeService as any,
"handlePortDisconnect",
);
handlePortMessageSpy = jest.spyOn(autofillOverlayIframeService as any, "handlePortMessage");
handlePortMessageSpy = jest.spyOn(autofillInlineMenuIframeService as any, "handlePortMessage");
chrome.runtime.connect = jest.fn((connectInfo: chrome.runtime.ConnectInfo) =>
createPortSpyMock(connectInfo.name),
) as unknown as typeof chrome.runtime.connect;
sendExtensionMessageSpy = jest.spyOn(
autofillOverlayIframeService as any,
autofillInlineMenuIframeService as any,
"sendExtensionMessage",
);
});
@ -51,44 +51,44 @@ describe("AutofillOverlayIframeService", () => {
describe("initMenuIframe", () => {
it("sets up the iframe's attributes", () => {
autofillOverlayIframeService.initMenuIframe();
autofillInlineMenuIframeService.initMenuIframe();
expect(autofillOverlayIframeService["iframe"]).toMatchSnapshot();
expect(autofillInlineMenuIframeService["iframe"]).toMatchSnapshot();
});
it("appends the iframe to the shadowDom", () => {
jest.spyOn(autofillOverlayIframeService["shadow"], "appendChild");
jest.spyOn(autofillInlineMenuIframeService["shadow"], "appendChild");
autofillOverlayIframeService.initMenuIframe();
autofillInlineMenuIframeService.initMenuIframe();
expect(autofillOverlayIframeService["shadow"].appendChild).toHaveBeenCalledWith(
autofillOverlayIframeService["iframe"],
expect(autofillInlineMenuIframeService["shadow"].appendChild).toHaveBeenCalledWith(
autofillInlineMenuIframeService["iframe"],
);
});
// TODO CG - This test is brittle and failing due to how we are calling the private method. This needs to be reworked
it.skip("creates an aria alert element if the ariaAlert param is passed", () => {
const ariaAlert = "aria alert";
jest.spyOn(autofillOverlayIframeService as any, "createAriaAlertElement");
jest.spyOn(autofillInlineMenuIframeService as any, "createAriaAlertElement");
autofillOverlayIframeService.initMenuIframe();
autofillInlineMenuIframeService.initMenuIframe();
expect(autofillOverlayIframeService["createAriaAlertElement"]).toHaveBeenCalledWith(
expect(autofillInlineMenuIframeService["createAriaAlertElement"]).toHaveBeenCalledWith(
ariaAlert,
);
expect(autofillOverlayIframeService["ariaAlertElement"]).toMatchSnapshot();
expect(autofillInlineMenuIframeService["ariaAlertElement"]).toMatchSnapshot();
});
describe("on load of the iframe source", () => {
beforeEach(() => {
autofillOverlayIframeService.initMenuIframe();
autofillInlineMenuIframeService.initMenuIframe();
});
it("sets up and connects the port message listener to the extension background", () => {
jest.spyOn(globalThis, "addEventListener");
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
portSpy = autofillOverlayIframeService["port"];
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
portSpy = autofillInlineMenuIframeService["port"];
expect(chrome.runtime.connect).toHaveBeenCalledWith({ name: AutofillOverlayPort.Button });
expect(portSpy.onDisconnect.addListener).toHaveBeenCalledWith(handlePortDisconnectSpy);
@ -97,9 +97,9 @@ describe("AutofillOverlayIframeService", () => {
it("skips announcing the aria alert if the aria alert element is not populated", () => {
jest.spyOn(globalThis, "setTimeout");
autofillOverlayIframeService["ariaAlertElement"] = undefined;
autofillInlineMenuIframeService["ariaAlertElement"] = undefined;
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
expect(globalThis.setTimeout).not.toHaveBeenCalled();
});
@ -107,16 +107,16 @@ describe("AutofillOverlayIframeService", () => {
it("announces the aria alert if the aria alert element is populated", () => {
jest.useFakeTimers();
jest.spyOn(globalThis, "setTimeout");
autofillOverlayIframeService["ariaAlertElement"] = document.createElement("div");
autofillOverlayIframeService["ariaAlertTimeout"] = setTimeout(jest.fn(), 2000);
autofillInlineMenuIframeService["ariaAlertElement"] = document.createElement("div");
autofillInlineMenuIframeService["ariaAlertTimeout"] = setTimeout(jest.fn(), 2000);
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
expect(globalThis.setTimeout).toHaveBeenCalled();
jest.advanceTimersByTime(2000);
expect(shadowAppendSpy).toHaveBeenCalledWith(
autofillOverlayIframeService["ariaAlertElement"],
autofillInlineMenuIframeService["ariaAlertElement"],
);
});
});
@ -124,16 +124,16 @@ describe("AutofillOverlayIframeService", () => {
describe("event listeners", () => {
beforeEach(() => {
autofillOverlayIframeService.initMenuIframe();
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
Object.defineProperty(autofillOverlayIframeService["iframe"], "contentWindow", {
autofillInlineMenuIframeService.initMenuIframe();
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
Object.defineProperty(autofillInlineMenuIframeService["iframe"], "contentWindow", {
value: {
postMessage: jest.fn(),
},
writable: true,
});
jest.spyOn(autofillOverlayIframeService["iframe"].contentWindow, "postMessage");
portSpy = autofillOverlayIframeService["port"];
jest.spyOn(autofillInlineMenuIframeService["iframe"].contentWindow, "postMessage");
portSpy = autofillInlineMenuIframeService["port"];
});
describe("handlePortDisconnect", () => {
@ -141,15 +141,15 @@ describe("AutofillOverlayIframeService", () => {
portSpy.name = "wrong-port-name";
triggerPortOnDisconnectEvent(portSpy);
expect(autofillOverlayIframeService["port"]).not.toBeNull();
expect(autofillInlineMenuIframeService["port"]).not.toBeNull();
});
it("resets the iframe element's opacity, height, and display styles", () => {
triggerPortOnDisconnectEvent(portSpy);
expect(autofillOverlayIframeService["iframe"].style.opacity).toBe("0");
expect(autofillOverlayIframeService["iframe"].style.height).toBe("0px");
expect(autofillOverlayIframeService["iframe"].style.display).toBe("block");
expect(autofillInlineMenuIframeService["iframe"].style.opacity).toBe("0");
expect(autofillInlineMenuIframeService["iframe"].style.height).toBe("0px");
expect(autofillInlineMenuIframeService["iframe"].style.display).toBe("block");
});
it("removes the port's onMessage listener", () => {
@ -168,7 +168,7 @@ describe("AutofillOverlayIframeService", () => {
triggerPortOnDisconnectEvent(portSpy);
expect(portSpy.disconnect).toHaveBeenCalled();
expect(autofillOverlayIframeService["port"]).toBeNull();
expect(autofillInlineMenuIframeService["port"]).toBeNull();
});
});
@ -178,7 +178,7 @@ describe("AutofillOverlayIframeService", () => {
sendPortMessage(portSpy, {});
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).not.toHaveBeenCalled();
});
@ -188,22 +188,22 @@ describe("AutofillOverlayIframeService", () => {
sendPortMessage(portSpy, message);
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).toHaveBeenCalledWith(message, "*");
});
it("handles port messages that are registered with the message handlers and does not pass the message on to the iframe", () => {
jest.spyOn(autofillOverlayIframeService as any, "updateIframePosition");
jest.spyOn(autofillInlineMenuIframeService as any, "updateIframePosition");
sendPortMessage(portSpy, { command: "updateIframePosition" });
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).not.toHaveBeenCalled();
});
describe("initializing the overlay button", () => {
it("sets the port key and posts the message to the overlay page iframe", () => {
describe("initializing the inline menu button", () => {
it("sets the port key and posts the message to the inline menu page iframe", () => {
const portKey = "portKey";
const message = {
command: "initAutofillInlineMenuButton",
@ -212,19 +212,19 @@ describe("AutofillOverlayIframeService", () => {
sendPortMessage(portSpy, message);
expect(autofillOverlayIframeService["portKey"]).toBe(portKey);
expect(autofillInlineMenuIframeService["portKey"]).toBe(portKey);
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).toHaveBeenCalledWith(message, "*");
});
});
describe("initializing the overlay list", () => {
describe("initializing the inline menu list", () => {
let updateElementStylesSpy: jest.SpyInstance;
beforeEach(() => {
updateElementStylesSpy = jest.spyOn(
autofillOverlayIframeService as any,
autofillInlineMenuIframeService as any,
"updateElementStyles",
);
});
@ -239,7 +239,7 @@ describe("AutofillOverlayIframeService", () => {
expect(updateElementStylesSpy).not.toHaveBeenCalled();
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).toHaveBeenCalledWith(message, "*");
});
@ -254,7 +254,7 @@ describe("AutofillOverlayIframeService", () => {
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).toHaveBeenCalledWith(
{
command: "initAutofillInlineMenuList",
@ -275,7 +275,7 @@ describe("AutofillOverlayIframeService", () => {
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).toHaveBeenCalledWith(
{
command: "initAutofillInlineMenuList",
@ -294,7 +294,7 @@ describe("AutofillOverlayIframeService", () => {
sendPortMessage(portSpy, message);
expect(updateElementStylesSpy).toHaveBeenCalledWith(
autofillOverlayIframeService["iframe"],
autofillInlineMenuIframeService["iframe"],
{
borderColor: "#4c525f",
},
@ -310,7 +310,7 @@ describe("AutofillOverlayIframeService", () => {
sendPortMessage(portSpy, message);
expect(updateElementStylesSpy).toHaveBeenCalledWith(
autofillOverlayIframeService["iframe"],
autofillInlineMenuIframeService["iframe"],
{
borderColor: "#2E3440",
},
@ -326,7 +326,7 @@ describe("AutofillOverlayIframeService", () => {
sendPortMessage(portSpy, message);
expect(updateElementStylesSpy).toHaveBeenCalledWith(
autofillOverlayIframeService["iframe"],
autofillInlineMenuIframeService["iframe"],
{
borderColor: "#073642",
},
@ -340,7 +340,7 @@ describe("AutofillOverlayIframeService", () => {
});
it("ignores updating the iframe position if the document does not have focus", () => {
jest.spyOn(autofillOverlayIframeService as any, "updateElementStyles");
jest.spyOn(autofillInlineMenuIframeService as any, "updateElementStyles");
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(false);
sendPortMessage(portSpy, {
@ -348,7 +348,7 @@ describe("AutofillOverlayIframeService", () => {
styles: { top: 100, left: 100 },
});
expect(autofillOverlayIframeService["updateElementStyles"]).not.toHaveBeenCalled();
expect(autofillInlineMenuIframeService["updateElementStyles"]).not.toHaveBeenCalled();
});
it("updates the iframe position if the document has focus", () => {
@ -359,8 +359,8 @@ describe("AutofillOverlayIframeService", () => {
styles,
});
expect(autofillOverlayIframeService["iframe"].style.top).toBe(styles.top);
expect(autofillOverlayIframeService["iframe"].style.left).toBe(styles.left);
expect(autofillInlineMenuIframeService["iframe"].style.top).toBe(styles.top);
expect(autofillInlineMenuIframeService["iframe"].style.left).toBe(styles.left);
});
it("fades the iframe element in after positioning the element", () => {
@ -372,9 +372,9 @@ describe("AutofillOverlayIframeService", () => {
styles,
});
expect(autofillOverlayIframeService["iframe"].style.opacity).toBe("0");
expect(autofillInlineMenuIframeService["iframe"].style.opacity).toBe("0");
jest.advanceTimersByTime(10);
expect(autofillOverlayIframeService["iframe"].style.opacity).toBe("1");
expect(autofillInlineMenuIframeService["iframe"].style.opacity).toBe("1");
});
it("announces the opening of the iframe using an aria alert", () => {
@ -388,7 +388,7 @@ describe("AutofillOverlayIframeService", () => {
jest.advanceTimersByTime(2000);
expect(shadowAppendSpy).toHaveBeenCalledWith(
autofillOverlayIframeService["ariaAlertElement"],
autofillInlineMenuIframeService["ariaAlertElement"],
);
});
});
@ -399,7 +399,7 @@ describe("AutofillOverlayIframeService", () => {
styles: { display: "none" },
});
expect(autofillOverlayIframeService["iframe"].style.display).toBe("none");
expect(autofillInlineMenuIframeService["iframe"].style.display).toBe("none");
});
it("updates the button based on the web page's color scheme", () => {
@ -408,7 +408,7 @@ describe("AutofillOverlayIframeService", () => {
});
expect(
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
).toHaveBeenCalledWith(
{
command: "updateAutofillInlineMenuColorScheme",
@ -422,41 +422,41 @@ describe("AutofillOverlayIframeService", () => {
describe("mutation observer", () => {
beforeEach(() => {
autofillOverlayIframeService.initMenuIframe();
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
portSpy = autofillOverlayIframeService["port"];
autofillInlineMenuIframeService.initMenuIframe();
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
portSpy = autofillInlineMenuIframeService["port"];
});
it("skips handling found mutations if excessive mutations are triggering", async () => {
jest.useFakeTimers();
jest
.spyOn(
autofillOverlayIframeService as any,
autofillInlineMenuIframeService as any,
"isTriggeringExcessiveMutationObserverIterations",
)
.mockReturnValue(true);
jest.spyOn(autofillOverlayIframeService as any, "updateElementStyles");
jest.spyOn(autofillInlineMenuIframeService as any, "updateElementStyles");
autofillOverlayIframeService["iframe"].style.visibility = "hidden";
autofillInlineMenuIframeService["iframe"].style.visibility = "hidden";
await flushPromises();
expect(autofillOverlayIframeService["updateElementStyles"]).not.toHaveBeenCalled();
expect(autofillInlineMenuIframeService["updateElementStyles"]).not.toHaveBeenCalled();
});
it("reverts any styles changes made directly to the iframe", async () => {
jest.useFakeTimers();
autofillOverlayIframeService["iframe"].style.visibility = "hidden";
autofillInlineMenuIframeService["iframe"].style.visibility = "hidden";
await flushPromises();
expect(autofillOverlayIframeService["iframe"].style.visibility).toBe("visible");
expect(autofillInlineMenuIframeService["iframe"].style.visibility).toBe("visible");
});
it("force closes the autofill overlay if more than 9 foreign mutations are triggered", async () => {
it("force closes the autofill inline menu if more than 9 foreign mutations are triggered", async () => {
jest.useFakeTimers();
autofillOverlayIframeService["foreignMutationsCount"] = 10;
autofillInlineMenuIframeService["foreignMutationsCount"] = 10;
autofillOverlayIframeService["iframe"].src = "http://malicious-site.com";
autofillInlineMenuIframeService["iframe"].src = "http://malicious-site.com";
await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
@ -464,11 +464,11 @@ describe("AutofillOverlayIframeService", () => {
});
});
it("force closes the autofill overlay if excessive mutations are being triggered", async () => {
it("force closes the autofill overinline menulay if excessive mutations are being triggered", async () => {
jest.useFakeTimers();
autofillOverlayIframeService["mutationObserverIterations"] = 20;
autofillInlineMenuIframeService["mutationObserverIterations"] = 20;
autofillOverlayIframeService["iframe"].src = "http://malicious-site.com";
autofillInlineMenuIframeService["iframe"].src = "http://malicious-site.com";
await flushPromises();
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
@ -478,24 +478,24 @@ describe("AutofillOverlayIframeService", () => {
it("resets the excessive mutations and foreign mutation counters", async () => {
jest.useFakeTimers();
autofillOverlayIframeService["foreignMutationsCount"] = 9;
autofillOverlayIframeService["mutationObserverIterations"] = 19;
autofillInlineMenuIframeService["foreignMutationsCount"] = 9;
autofillInlineMenuIframeService["mutationObserverIterations"] = 19;
autofillOverlayIframeService["iframe"].src = "http://malicious-site.com";
autofillInlineMenuIframeService["iframe"].src = "http://malicious-site.com";
jest.advanceTimersByTime(2001);
await flushPromises();
expect(autofillOverlayIframeService["foreignMutationsCount"]).toBe(0);
expect(autofillOverlayIframeService["mutationObserverIterations"]).toBe(0);
expect(autofillInlineMenuIframeService["foreignMutationsCount"]).toBe(0);
expect(autofillInlineMenuIframeService["mutationObserverIterations"]).toBe(0);
});
it("resets any mutated default attributes for the iframe", async () => {
jest.useFakeTimers();
autofillOverlayIframeService["iframe"].title = "some-other-title";
autofillInlineMenuIframeService["iframe"].title = "some-other-title";
await flushPromises();
expect(autofillOverlayIframeService["iframe"].title).toBe("title");
expect(autofillInlineMenuIframeService["iframe"].title).toBe("title");
});
});
});

View File

@ -4,11 +4,11 @@ import { ThemeType } from "@bitwarden/common/platform/enums";
import { sendExtensionMessage, setElementStyles } from "../../../utils";
import {
BackgroundPortMessageHandlers,
AutofillInlineMenuIframeService as AutofillOverlayIframeServiceInterface,
AutofillOverlayIframeExtensionMessage,
AutofillInlineMenuIframeService as AutofillInlineMenuIframeServiceInterface,
AutofillInlineMenuIframeExtensionMessage,
} from "../abstractions/autofill-inline-menu-iframe.service";
export class AutofillInlineMenuIframeService implements AutofillOverlayIframeServiceInterface {
export class AutofillInlineMenuIframeService implements AutofillInlineMenuIframeServiceInterface {
private sendExtensionMessage = sendExtensionMessage;
private port: chrome.runtime.Port | null = null;
private portKey: string;
@ -167,7 +167,7 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
* @param port
*/
private handlePortMessage = (
message: AutofillOverlayIframeExtensionMessage,
message: AutofillInlineMenuIframeExtensionMessage,
port: chrome.runtime.Port,
) => {
if (port.name !== this.portName) {
@ -183,13 +183,13 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
};
/**
* Handles the initialization of the autofill overlay. This includes setting
* the port key and sending a message to the iframe to initialize the overlay.
* Handles the initialization of the autofill inline menu. This includes setting
* the port key and sending a message to the iframe to initialize the inline menu.
*
* @param message
* @private
*/
private initAutofillInlineMenu(message: AutofillOverlayIframeExtensionMessage) {
private initAutofillInlineMenu(message: AutofillInlineMenuIframeExtensionMessage) {
this.portKey = message.portKey;
if (message.command === "initAutofillInlineMenuList") {
this.initAutofillInlineMenuList(message);
@ -200,12 +200,12 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
}
/**
* Handles initialization of the autofill overlay list. This includes setting
* the theme and sending a message to the iframe to initialize the overlay.
* Handles initialization of the autofill inline menu list. This includes setting
* the theme and sending a message to the iframe to initialize the inline menu.
*
* @param message - The message sent from the iframe
*/
private initAutofillInlineMenuList(message: AutofillOverlayIframeExtensionMessage) {
private initAutofillInlineMenuList(message: AutofillInlineMenuIframeExtensionMessage) {
const { theme } = message;
let borderColor: string;
let verifiedTheme = theme;
@ -320,7 +320,7 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
};
/**
* Triggers a forced closure of the autofill overlay. This is used when the
* Triggers a forced closure of the autofill inline menu. This is used when the
* mutation observer is triggered excessively.
*/
private forceCloseAutofillInlineMenu() {
@ -378,7 +378,7 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
/**
* Identifies if the mutation observer is triggering excessive iterations.
* Will remove the autofill overlay if any set mutation observer is
* Will remove the autofill inline menu if any set mutation observer is
* triggering excessive iterations.
*/
private isTriggeringExcessiveMutationObserverIterations() {

View File

@ -1,8 +1,8 @@
import AutofillInlineMenuListIframe from "./autofill-inline-menu-list-iframe";
import { AutofillInlineMenuListIframe } from "./autofill-inline-menu-list-iframe";
describe("AutofillOverlayListIframe", () => {
describe("AutofillInlineMenuListIframe", () => {
window.customElements.define(
"autofill-overlay-list-iframe",
"autofill-inline-menu-list-iframe",
class extends HTMLElement {
constructor() {
super();
@ -16,9 +16,10 @@ describe("AutofillOverlayListIframe", () => {
});
it("creates a custom element that is an instance of the AutofillIframeElement parent class", () => {
document.body.innerHTML = "<autofill-overlay-list-iframe></autofill-overlay-list-iframe>";
document.body.innerHTML =
"<autofill-inline-menu-list-iframe></autofill-inline-menu-list-iframe>";
const iframe = document.querySelector("autofill-overlay-list-iframe");
const iframe = document.querySelector("autofill-inline-menu-list-iframe");
expect(iframe).toBeInstanceOf(HTMLElement);
expect(iframe.shadowRoot).toBeDefined();

View File

@ -2,7 +2,7 @@ import { AutofillOverlayPort } from "../../../enums/autofill-overlay.enum";
import { AutofillInlineMenuIframeElement } from "./autofill-inline-menu-iframe-element";
class AutofillInlineMenuListIframe extends AutofillInlineMenuIframeElement {
export class AutofillInlineMenuListIframe extends AutofillInlineMenuIframeElement {
constructor(element: HTMLElement) {
super(
element,
@ -21,5 +21,3 @@ class AutofillInlineMenuListIframe extends AutofillInlineMenuIframeElement {
);
}
}
export default AutofillInlineMenuListIframe;

View File

@ -0,0 +1,536 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AutofillOverlayList initAutofillInlineMenuList the list of ciphers for an authenticated user creates the view for a list of ciphers 1`] = `
<div
class="overlay-list-container theme_light"
>
<ul
class="overlay-actions-list"
role="list"
>
<li
class="overlay-actions-list-item"
role="listitem"
>
<div
class="cipher-container"
>
<button
aria-description="partialUsername, username1"
aria-label="fillCredentialsFor website login 1"
class="fill-cipher-button"
tabindex="-1"
>
<span
aria-hidden="true"
class="cipher-icon"
style="background-image: url(https://jest-testing-website.com/image.png);"
/>
<span
class="cipher-details"
>
<span
class="cipher-name"
title="website login 1"
>
website login 1
</span>
<span
class="cipher-user-login"
title="username1"
>
username1
</span>
</span>
</button>
<button
aria-label="view website login 1, opensInANewWindow"
class="view-cipher-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 20 20"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .113h20v19.773H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
</button>
</div>
</li>
<li
class="overlay-actions-list-item"
role="listitem"
>
<div
class="cipher-container"
>
<button
aria-description="partialUsername, username2"
aria-label="fillCredentialsFor website login 2"
class="fill-cipher-button"
tabindex="-1"
>
<span
aria-hidden="true"
class="cipher-icon bwi bw-icon"
/>
<span
class="cipher-details"
>
<span
class="cipher-name"
title="website login 2"
>
website login 2
</span>
<span
class="cipher-user-login"
title="username2"
>
username2
</span>
</span>
</button>
<button
aria-label="view website login 2, opensInANewWindow"
class="view-cipher-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 20 20"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .113h20v19.773H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
</button>
</div>
</li>
<li
class="overlay-actions-list-item"
role="listitem"
>
<div
class="cipher-container"
>
<button
aria-description="partialUsername, "
aria-label="fillCredentialsFor "
class="fill-cipher-button"
tabindex="-1"
>
<span
aria-hidden="true"
class="cipher-icon bwi bw-icon"
/>
<span
class="cipher-details"
/>
</button>
<button
aria-label="view , opensInANewWindow"
class="view-cipher-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 20 20"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .113h20v19.773H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
</button>
</div>
</li>
<li
class="overlay-actions-list-item"
role="listitem"
>
<div
class="cipher-container"
>
<button
aria-description="partialUsername, username4"
aria-label="fillCredentialsFor website login 4"
class="fill-cipher-button"
tabindex="-1"
>
<span
aria-hidden="true"
class="cipher-icon"
>
<svg
aria-hidden="true"
fill="none"
height="25"
viewBox="0 0 24 25"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
clip-rule="evenodd"
d="M18.026 17.842c-1.418 1.739-3.517 2.84-5.86 2.84a7.364 7.364 0 0 1-3.431-.848l.062-.15.062-.151.063-.157c.081-.203.17-.426.275-.646.133-.28.275-.522.426-.68.026-.028.101-.075.275-.115.165-.037.376-.059.629-.073.138-.008.288-.014.447-.02.399-.016.847-.034 1.266-.092.314-.044.566-.131.755-.271a.884.884 0 0 0 .352-.555c.037-.2.008-.392-.03-.543-.035-.135-.084-.264-.12-.355l-.01-.03a4.26 4.26 0 0 0-.145-.33c-.126-.264-.237-.497-.288-1.085-.03-.344.09-.73.251-1.138l.089-.22c.05-.123.1-.247.14-.355.064-.171.129-.375.129-.566a1.51 1.51 0 0 0-.134-.569 2.573 2.573 0 0 0-.319-.547c-.246-.323-.635-.669-1.093-.669-.44 0-1.006.169-1.487.368-.246.102-.48.216-.68.33-.192.111-.372.235-.492.359-.93.96-1.48 1.239-1.81 1.258-.277.017-.478-.15-.736-.525a9.738 9.738 0 0 1-.19-.29l-.006-.01a11.568 11.568 0 0 0-.198-.305 2.76 2.76 0 0 0-.521-.6 1.39 1.39 0 0 0-1.088-.314 8.302 8.302 0 0 1 1.987-3.936c.055.342.146.626.272.856.23.42.561.64.926.716.406.086.857-.061 1.26-.216.125-.047.248-.097.372-.147.309-.125.618-.25.947-.341.26-.072.581-.057.959.012.264.049.529.118.8.19l.36.091c.379.094.782.178 1.135.148.374-.032.733-.197.934-.623a.874.874 0 0 0 .024-.752c-.087-.197-.24-.355-.35-.47-.26-.267-.412-.427-.412-.685 0-.125.037-.2.09-.263a.982.982 0 0 1 .303-.211c.059-.03.119-.058.183-.089l.036-.016a3.79 3.79 0 0 0 .236-.118c.047-.026.098-.056.148-.093 1.936.747 3.51 2.287 4.368 4.249a7.739 7.739 0 0 0-.031-.004c-.38-.047-.738-.056-1.063.061-.34.123-.603.368-.817.74-.122.211-.284.43-.463.67l-.095.129c-.207.281-.431.595-.58.92-.15.326-.245.705-.142 1.103.104.397.387.738.837 1.036.099.065.225.112.314.145l.02.008c.108.04.195.074.268.117.07.042.106.08.124.114.017.03.037.087.022.206-.047.376-.069.73-.052 1.034.017.292.071.59.218.809.118.174.12.421.108.786v.01a2.46 2.46 0 0 0 .021.518.809.809 0 0 0 .15.35Zm1.357.059a9.654 9.654 0 0 0 1.62-5.386c0-5.155-3.957-9.334-8.836-9.334-4.88 0-8.836 4.179-8.836 9.334 0 3.495 1.82 6.543 4.513 8.142v.093h.161a8.426 8.426 0 0 0 4.162 1.098c2.953 0 5.568-1.53 7.172-3.882a.569.569 0 0 0 .048-.062l-.004-.003ZM8.152 19.495a43.345 43.345 0 0 1 .098-.238l.057-.142c.082-.205.182-.455.297-.698.143-.301.323-.624.552-.864.163-.172.392-.254.602-.302.219-.05.473-.073.732-.088.162-.01.328-.016.495-.023.386-.015.782-.03 1.168-.084.255-.036.392-.099.461-.15.06-.045.076-.084.083-.12a.534.534 0 0 0-.02-.223 2.552 2.552 0 0 0-.095-.278l-.01-.027a3.128 3.128 0 0 0-.104-.232c-.134-.282-.31-.65-.374-1.381-.046-.533.138-1.063.3-1.472.035-.09.069-.172.1-.249.046-.11.086-.21.123-.31.062-.169.083-.264.083-.312a.812.812 0 0 0-.076-.283 1.867 1.867 0 0 0-.23-.394c-.21-.274-.428-.408-.577-.408-.315 0-.788.13-1.246.32a5.292 5.292 0 0 0-.603.293 1.727 1.727 0 0 0-.347.244c-.936.968-1.641 1.421-2.235 1.457-.646.04-1.036-.413-1.31-.813-.07-.103-.139-.21-.203-.311l-.005-.007c-.064-.101-.125-.197-.188-.29a2.098 2.098 0 0 0-.387-.453.748.748 0 0 0-.436-.18c-.1-.006-.22.005-.365.046a8.707 8.707 0 0 0-.056.992c0 2.957 1.488 5.547 3.716 6.98Zm10.362-2.316.003-.192.002-.046c.01-.305.026-.786-.232-1.169-.036-.054-.082-.189-.096-.444-.014-.243.003-.55.047-.9a1.051 1.051 0 0 0-.105-.649.987.987 0 0 0-.374-.374 2.285 2.285 0 0 0-.367-.166h-.003a1.243 1.243 0 0 1-.205-.088c-.369-.244-.505-.46-.549-.629-.044-.168-.015-.364.099-.61.115-.25.297-.511.507-.796l.089-.12c.178-.239.368-.495.512-.745.152-.263.302-.382.466-.441.18-.065.416-.073.77-.03.142.018.275.04.397.063.274.837.423 1.736.423 2.671a8.45 8.45 0 0 1-1.384 4.665Zm-4.632-12.63a7.362 7.362 0 0 0-1.715-.201c-1.89 0-3.621.716-4.965 1.905.025.54.12.887.24 1.105.13.238.295.34.482.38.2.042.484-.027.905-.188l.328-.13c.32-.13.681-.275 1.048-.377.398-.111.833-.075 1.24 0 .289.053.59.132.871.205l.326.084c.383.094.694.151.932.13.216-.017.326-.092.395-.237.039-.083.027-.114.014-.144-.027-.062-.088-.136-.212-.264l-.043-.044c-.218-.222-.567-.578-.567-1.142 0-.305.101-.547.262-.734.137-.159.308-.267.46-.347Z"
fill="#777"
fill-rule="evenodd"
/>
</svg>
</span>
<span
class="cipher-details"
>
<span
class="cipher-name"
title="website login 4"
>
website login 4
</span>
<span
class="cipher-user-login"
title="username4"
>
username4
</span>
</span>
</button>
<button
aria-label="view website login 4, opensInANewWindow"
class="view-cipher-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 20 20"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .113h20v19.773H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
</button>
</div>
</li>
<li
class="overlay-actions-list-item"
role="listitem"
>
<div
class="cipher-container"
>
<button
aria-description="partialUsername, username5"
aria-label="fillCredentialsFor website login 5"
class="fill-cipher-button"
tabindex="-1"
>
<span
aria-hidden="true"
class="cipher-icon"
style="background-image: url(https://jest-testing-website.com/image.png);"
/>
<span
class="cipher-details"
>
<span
class="cipher-name"
title="website login 5"
>
website login 5
</span>
<span
class="cipher-user-login"
title="username5"
>
username5
</span>
</span>
</button>
<button
aria-label="view website login 5, opensInANewWindow"
class="view-cipher-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 20 20"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .113h20v19.773H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
</button>
</div>
</li>
<li
class="overlay-actions-list-item"
role="listitem"
>
<div
class="cipher-container"
>
<button
aria-description="partialUsername, username6"
aria-label="fillCredentialsFor website login 6"
class="fill-cipher-button"
tabindex="-1"
>
<span
aria-hidden="true"
class="cipher-icon"
style="background-image: url(https://jest-testing-website.com/image.png);"
/>
<span
class="cipher-details"
>
<span
class="cipher-name"
title="website login 6"
>
website login 6
</span>
<span
class="cipher-user-login"
title="username6"
>
username6
</span>
</span>
</button>
<button
aria-label="view website login 6, opensInANewWindow"
class="view-cipher-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 20 20"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M16.587 7.932H5.9a.455.455 0 0 1-.31-.12.393.393 0 0 1-.127-.287c0-.108.046-.211.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.076.128.179.128.287a.393.393 0 0 1-.128.288.455.455 0 0 1-.31.119Zm0 2.474H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm0 2.468H5.9a.455.455 0 0 1-.31-.119.393.393 0 0 1-.127-.287c0-.108.046-.212.128-.288a.455.455 0 0 1 .309-.119h10.687c.117 0 .228.043.31.12.082.075.128.179.128.287a.393.393 0 0 1-.128.287.455.455 0 0 1-.31.12Zm2.163-8.103v10.457H1.25V4.771h17.5Zm0-1.162H1.25a1.3 1.3 0 0 0-.884.34A1.122 1.122 0 0 0 0 4.772v10.457c0 .308.132.604.366.822a1.3 1.3 0 0 0 .884.34h17.5a1.3 1.3 0 0 0 .884-.34c.234-.218.366-.514.366-.822V4.771c0-.308-.132-.603-.366-.821a1.3 1.3 0 0 0-.884-.34ZM3.213 8.01c.287 0 .52-.217.52-.484s-.234-.483-.52-.483c-.288 0-.52.216-.52.483s.233.483.52.483Zm0 4.903c.287 0 .52-.217.52-.484 0-.266-.234-.483-.52-.483-.287 0-.52.216-.52.483s.233.484.52.484Zm0-2.452c.287 0 .52-.216.52-.483 0-.268-.234-.484-.52-.484-.288 0-.52.216-.52.484 0 .267.233.483.52.483Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .113h20v19.773H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
</button>
</div>
</li>
</ul>
</div>
`;
exports[`AutofillOverlayList initAutofillInlineMenuList the locked overlay for an unauthenticated user creates the views for the locked overlay 1`] = `
<div
class="overlay-list-container theme_light"
>
<div
class="locked-overlay overlay-list-message"
id="locked-overlay-description"
>
unlockYourAccount
</div>
<div
class="overlay-list-button-container"
>
<button
aria-label="unlockAccount, opensInANewWindow"
class="unlock-button overlay-list-button"
id="unlock-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="17"
viewBox="0 0 17 17"
width="17"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M8.799 11.633a.68.68 0 0 0-.639.422.695.695 0 0 0-.054.264.682.682 0 0 0 .374.6v1.13a.345.345 0 1 0 .693 0v-1.17a.68.68 0 0 0 .315-.56.695.695 0 0 0-.204-.486.682.682 0 0 0-.485-.2Zm4.554-4.657h-7.11a.438.438 0 0 1-.406-.26A3.81 3.81 0 0 1 5.584 4.3c.112-.435.312-.842.588-1.195A3.196 3.196 0 0 1 7.19 2.25a3.468 3.468 0 0 1 3.225-.059A3.62 3.62 0 0 1 11.94 3.71l.327.59a.502.502 0 1 0 .885-.483l-.307-.552a4.689 4.689 0 0 0-2.209-2.078 4.466 4.466 0 0 0-3.936.185A4.197 4.197 0 0 0 5.37 2.49a4.234 4.234 0 0 0-.768 1.565 4.714 4.714 0 0 0 .162 2.682.182.182 0 0 1-.085.22.173.173 0 0 1-.082.02h-.353a1.368 1.368 0 0 0-1.277.842c-.07.168-.107.348-.109.53v7.1a1.392 1.392 0 0 0 .412.974 1.352 1.352 0 0 0 .974.394h9.117c.363.001.711-.142.97-.4a1.39 1.39 0 0 0 .407-.972v-7.1a1.397 1.397 0 0 0-.414-.973 1.368 1.368 0 0 0-.972-.396Zm.37 8.469a.373.373 0 0 1-.11.26.364.364 0 0 1-.26.107H4.246a.366.366 0 0 1-.26-.107.374.374 0 0 1-.11-.261V8.349a.374.374 0 0 1 .11-.26.366.366 0 0 1 .26-.108h9.116a.366.366 0 0 1 .37.367l-.008 7.097Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M.798.817h16v16h-16z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
unlockAccount
</button>
</div>
</div>
`;
exports[`AutofillOverlayList initAutofillInlineMenuList the overlay with an empty list of ciphers creates the views for the no results overlay 1`] = `
<div
class="overlay-list-container theme_light"
>
<div
class="no-items overlay-list-message"
>
noItemsToShow
</div>
<div
class="overlay-list-button-container"
>
<button
aria-label="addNewVaultItem, opensInANewWindow"
class="add-new-item-button overlay-list-button"
id="new-item-button"
tabindex="-1"
>
<svg
aria-hidden="true"
fill="none"
height="17"
viewBox="0 0 16 17"
width="16"
xmlns="http://www.w3.org/2000/svg"
>
<g
clip-path="url(#a)"
>
<path
d="M15.222 7.914H8.963a.471.471 0 0 1-.34-.147.512.512 0 0 1-.142-.353V.99c0-.133-.05-.26-.14-.354a.471.471 0 0 0-.68 0 .51.51 0 0 0-.142.354v6.424c0 .132-.051.26-.142.353a.474.474 0 0 1-.34.147H.777a.47.47 0 0 0-.34.146.5.5 0 0 0-.14.354.522.522 0 0 0 .14.353.48.48 0 0 0 .34.147h6.26c.128 0 .25.052.34.146.09.094.142.221.142.354v6.576c0 .132.05.26.14.353a.471.471 0 0 0 .68 0 .512.512 0 0 0 .142-.353V9.414c0-.133.051-.26.142-.354a.474.474 0 0 1 .34-.146h6.26c.127 0 .25-.053.34-.147a.511.511 0 0 0 0-.707.472.472 0 0 0-.34-.146Z"
fill="#175DDC"
/>
</g>
<defs>
<clippath
id="a"
>
<path
d="M0 .49h16v16H0z"
fill="#fff"
/>
</clippath>
</defs>
</svg>
newItem
</button>
</div>
</div>
`;

View File

@ -5,22 +5,22 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { createInitAutofillOverlayListMessageMock } from "../../../../spec/autofill-mocks";
import { flushPromises, postWindowMessage } from "../../../../spec/testing-utils";
import AutofillOverlayList from "./autofill-overlay-list";
import { AutofillInlineMenuList } from "./autofill-inline-menu-list";
describe("AutofillOverlayList", () => {
globalThis.customElements.define("autofill-overlay-list", AutofillOverlayList);
globalThis.customElements.define("autofill-inline-menu-list", AutofillInlineMenuList);
global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));
let autofillOverlayList: AutofillOverlayList;
let autofillOverlayList: AutofillInlineMenuList;
const portKey: string = "overlayListPortKey";
beforeEach(() => {
document.body.innerHTML = `<autofill-overlay-list></autofill-overlay-list>`;
autofillOverlayList = document.querySelector("autofill-overlay-list");
document.body.innerHTML = `<autofill-inline-menu-list></autofill-inline-menu-list>`;
autofillOverlayList = document.querySelector("autofill-inline-menu-list");
jest.spyOn(globalThis.document, "createElement");
jest.spyOn(globalThis.parent, "postMessage");
});
@ -312,7 +312,7 @@ describe("AutofillOverlayList", () => {
postWindowMessage(createInitAutofillOverlayListMessageMock());
const updateCiphersSpy = jest.spyOn(autofillOverlayList as any, "updateListItems");
postWindowMessage({ command: "updateOverlayListCiphers" });
postWindowMessage({ command: "updateAutofillInlineMenuListCiphers" });
expect(updateCiphersSpy).toHaveBeenCalled();
});

View File

@ -7,12 +7,12 @@ import { OverlayCipherData } from "../../../../background/abstractions/overlay.b
import { buildSvgDomElement } from "../../../../utils";
import { globeIcon, lockIcon, plusIcon, viewCipherIcon } from "../../../../utils/svg-icons";
import {
InitAutofillOverlayListMessage,
OverlayListWindowMessageHandlers,
InitAutofillInlineMenuListMessage,
AutofillInlineMenuListWindowMessageHandlers,
} from "../../abstractions/autofill-inline-menu-list";
import { AutofillInlineMenuPageElement } from "../shared/autofill-inline-menu-page-element";
class AutofillOverlayList extends AutofillInlineMenuPageElement {
export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
private overlayListContainer: HTMLDivElement;
private resizeObserver: ResizeObserver;
private eventHandlersMemo: { [key: string]: EventListener } = {};
@ -22,10 +22,10 @@ class AutofillOverlayList extends AutofillInlineMenuPageElement {
private cipherListScrollDebounceTimeout: number | NodeJS.Timeout;
private currentCipherIndex = 0;
private readonly showCiphersPerPage = 6;
private readonly overlayListWindowMessageHandlers: OverlayListWindowMessageHandlers = {
private readonly overlayListWindowMessageHandlers: AutofillInlineMenuListWindowMessageHandlers = {
initAutofillInlineMenuList: ({ message }) => this.initAutofillInlineMenuList(message),
checkAutofillInlineMenuListFocused: () => this.checkInlineMenuListFocused(),
updateOverlayListCiphers: ({ message }) => this.updateListItems(message.ciphers),
updateAutofillInlineMenuListCiphers: ({ message }) => this.updateListItems(message.ciphers),
focusInlineMenuList: () => this.focusInlineMenuList(),
};
@ -53,7 +53,7 @@ class AutofillOverlayList extends AutofillInlineMenuPageElement {
authStatus,
ciphers,
portKey,
}: InitAutofillOverlayListMessage) {
}: InitAutofillInlineMenuListMessage) {
const linkElement = await this.initAutofillInlineMenuPage(
"list",
styleSheetUrl,
@ -619,5 +619,3 @@ class AutofillOverlayList extends AutofillInlineMenuPageElement {
nextSibling?.focus();
}
}
export default AutofillOverlayList;

View File

@ -1,9 +1,9 @@
import { AutofillOverlayElement } from "../../../../enums/autofill-overlay.enum";
import AutofillOverlayList from "./autofill-overlay-list";
import { AutofillInlineMenuList } from "./autofill-inline-menu-list";
require("./list.scss");
(function () {
globalThis.customElements.define(AutofillOverlayElement.List, AutofillOverlayList);
globalThis.customElements.define(AutofillOverlayElement.List, AutofillInlineMenuList);
})();

View File

@ -7,6 +7,6 @@
<meta name="color-scheme" content="normal" />
</head>
<body>
<autofill-overlay-list></autofill-overlay-list>
<autofill-inline-menu-list></autofill-inline-menu-list>
</body>
</html>

View File

@ -2,11 +2,11 @@ import { EVENTS } from "@bitwarden/common/autofill/constants";
import { setElementStyles } from "../../../../utils";
import {
InitOverlayElementMessage,
AutofillOverlayMenuContainerWindowMessageHandlers,
InitInlineMenuElementMessage,
AutofillInlineMenuMenuContainerWindowMessageHandlers,
} from "../../abstractions/autofill-inline-menu-container";
export class AutofillOverlayMenuContainer {
export class AutofillInlineMenuContainer {
private extensionOriginsSet: Set<string>;
private port: chrome.runtime.Port | null = null;
private portName: string;
@ -36,9 +36,9 @@ export class AutofillOverlayMenuContainer {
allowtransparency: "true",
tabIndex: "-1",
};
private windowMessageHandlers: AutofillOverlayMenuContainerWindowMessageHandlers = {
initAutofillInlineMenuList: (message) => this.handleInitOverlayIframe(message),
initAutofillInlineMenuButton: (message) => this.handleInitOverlayIframe(message),
private windowMessageHandlers: AutofillInlineMenuMenuContainerWindowMessageHandlers = {
initAutofillInlineMenuList: (message) => this.handleInitInlineMenuIframe(message),
initAutofillInlineMenuButton: (message) => this.handleInitInlineMenuIframe(message),
};
constructor() {
@ -50,7 +50,7 @@ export class AutofillOverlayMenuContainer {
globalThis.addEventListener("message", this.handleWindowMessage);
}
private handleInitOverlayIframe(message: InitOverlayElementMessage) {
private handleInitInlineMenuIframe(message: InitInlineMenuElementMessage) {
this.defaultIframeAttributes.src = message.iframeUrl;
this.defaultIframeAttributes.title = message.pageTitle;
this.portName = message.portName;
@ -67,7 +67,7 @@ export class AutofillOverlayMenuContainer {
globalThis.document.body.appendChild(this.overlayPageIframe);
}
private setupPortMessageListener = (message: InitOverlayElementMessage) => {
private setupPortMessageListener = (message: InitInlineMenuElementMessage) => {
this.port = chrome.runtime.connect({ name: this.portName });
this.port.onMessage.addListener(this.handlePortMessage);

View File

@ -0,0 +1,3 @@
import { AutofillInlineMenuContainer } from "./autofill-inline-menu-container";
(() => new AutofillInlineMenuContainer())();

View File

@ -1,3 +0,0 @@
import { AutofillOverlayMenuContainer } from "./autofill-overlay-menu-container";
(() => new AutofillOverlayMenuContainer())();

View File

@ -13,7 +13,7 @@ import AutofillForm from "../models/autofill-form";
import AutofillPageDetails from "../models/autofill-page-details";
import AutofillScript, { FillScript } from "../models/autofill-script";
import { InitAutofillInlineMenuButtonMessage } from "../overlay/inline-menu/abstractions/autofill-inline-menu-button";
import { InitAutofillOverlayListMessage } from "../overlay/inline-menu/abstractions/autofill-inline-menu-list";
import { InitAutofillInlineMenuListMessage } from "../overlay/inline-menu/abstractions/autofill-inline-menu-list";
import { GenerateFillScriptOptions, PageDetail } from "../services/abstractions/autofill.service";
function createAutofillFormMock(customFields = {}): AutofillForm {
@ -197,7 +197,7 @@ function createAutofillOverlayCipherDataMock(index: number, customFields = {}):
function createInitAutofillOverlayListMessageMock(
customFields = {},
): InitAutofillOverlayListMessage {
): InitAutofillInlineMenuListMessage {
return {
command: "initAutofillInlineMenuList",
translations: overlayPagesTranslations,

View File

@ -177,9 +177,9 @@ const mainConfig = {
"overlay/button":
"./src/autofill/overlay/inline-menu/pages/button/bootstrap-autofill-inline-menu-button.ts",
"overlay/list":
"./src/autofill/overlay/inline-menu/pages/list/bootstrap-autofill-overlay-list.ts",
"./src/autofill/overlay/inline-menu/pages/list/bootstrap-autofill-inline-menu-list.ts",
"overlay/menu":
"./src/autofill/overlay/inline-menu/pages/menu/bootstrap-autofill-overlay-menu-container.ts",
"./src/autofill/overlay/inline-menu/pages/menu/bootstrap-autofill-inline-menu-container.ts",
"encrypt-worker": "../../libs/common/src/platform/services/cryptography/encrypt.worker.ts",
"content/lp-fileless-importer": "./src/tools/content/lp-fileless-importer.ts",
"content/send-on-installed-message": "./src/vault/content/send-on-installed-message.ts",