mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 17:23:37 +00:00
[PM-5189] Reworking project structure to ensure we can better differentiate the inline menu feature from other features
This commit is contained in:
@@ -236,7 +236,7 @@ describe("OverlayBackground", () => {
|
|||||||
expect(overlayBackground["getOverlayCipherData"]).toHaveBeenCalled();
|
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>();
|
overlayBackground["inlineMenuListPort"] = mock<chrome.runtime.Port>();
|
||||||
cipherService.getAllDecryptedForUrl.mockResolvedValue([cipher1, cipher2]);
|
cipherService.getAllDecryptedForUrl.mockResolvedValue([cipher1, cipher2]);
|
||||||
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
|
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
|
||||||
@@ -246,7 +246,7 @@ describe("OverlayBackground", () => {
|
|||||||
await overlayBackground.updateOverlayCiphers();
|
await overlayBackground.updateOverlayCiphers();
|
||||||
|
|
||||||
expect(overlayBackground["inlineMenuListPort"].postMessage).toHaveBeenCalledWith({
|
expect(overlayBackground["inlineMenuListPort"].postMessage).toHaveBeenCalledWith({
|
||||||
command: "updateOverlayListCiphers",
|
command: "updateAutofillInlineMenuListCiphers",
|
||||||
ciphers: [
|
ciphers: [
|
||||||
{
|
{
|
||||||
card: null,
|
card: null,
|
||||||
|
|||||||
@@ -190,7 +190,10 @@ class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ciphers = await this.getOverlayCipherData();
|
const ciphers = await this.getOverlayCipherData();
|
||||||
this.inlineMenuListPort?.postMessage({ command: "updateOverlayListCiphers", ciphers });
|
this.inlineMenuListPort?.postMessage({
|
||||||
|
command: "updateAutofillInlineMenuListCiphers",
|
||||||
|
ciphers,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
const AutofillOverlayElement = {
|
const AutofillOverlayElement = {
|
||||||
Button: "autofill-inline-menu-button",
|
Button: "autofill-inline-menu-button",
|
||||||
List: "autofill-overlay-list",
|
List: "autofill-inline-menu-list",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const AutofillOverlayPort = {
|
const AutofillOverlayPort = {
|
||||||
Button: "autofill-inline-menu-button-port",
|
Button: "autofill-inline-menu-button-port",
|
||||||
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
|
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
|
||||||
List: "autofill-overlay-list-port",
|
List: "autofill-inline-menu-list-port",
|
||||||
ListMessageConnector: "autofill-overlay-list-message-connector",
|
ListMessageConnector: "autofill-inline-menu-list-message-connector",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const RedirectFocusDirection = {
|
const RedirectFocusDirection = {
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
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;
|
authStatus: AuthenticationStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
type InitAutofillInlineMenuButtonMessage = UpdateAuthStatusMessage & {
|
export type InitAutofillInlineMenuButtonMessage = UpdateAuthStatusMessage & {
|
||||||
styleSheetUrl: string;
|
styleSheetUrl: string;
|
||||||
translations: Record<string, string>;
|
translations: Record<string, string>;
|
||||||
portKey: string;
|
portKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type AutofillInlineMenuButtonWindowMessageHandlers = {
|
export type AutofillInlineMenuButtonWindowMessageHandlers = {
|
||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
initAutofillInlineMenuButton: ({
|
initAutofillInlineMenuButton: ({
|
||||||
message,
|
message,
|
||||||
@@ -31,10 +31,3 @@ type AutofillInlineMenuButtonWindowMessageHandlers = {
|
|||||||
message: AutofillInlineMenuButtonMessage;
|
message: AutofillInlineMenuButtonMessage;
|
||||||
}) => void;
|
}) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
|
||||||
UpdateAuthStatusMessage,
|
|
||||||
AutofillInlineMenuButtonMessage,
|
|
||||||
InitAutofillInlineMenuButtonMessage,
|
|
||||||
AutofillInlineMenuButtonWindowMessageHandlers,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
|
|||||||
|
|
||||||
import { OverlayCipherData } from "../../../background/abstractions/overlay.background";
|
import { OverlayCipherData } from "../../../background/abstractions/overlay.background";
|
||||||
|
|
||||||
type AutofillOverlayMenuContainerMessage = {
|
type AutofillInlineMenuMenuContainerMessage = {
|
||||||
command: string;
|
command: string;
|
||||||
portKey: string;
|
portKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InitOverlayElementMessage = AutofillOverlayMenuContainerMessage & {
|
export type InitInlineMenuElementMessage = AutofillInlineMenuMenuContainerMessage & {
|
||||||
iframeUrl?: string;
|
iframeUrl?: string;
|
||||||
pageTitle?: string;
|
pageTitle?: string;
|
||||||
authStatus?: AuthenticationStatus;
|
authStatus?: AuthenticationStatus;
|
||||||
@@ -18,8 +18,8 @@ export type InitOverlayElementMessage = AutofillOverlayMenuContainerMessage & {
|
|||||||
portName?: string;
|
portName?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AutofillOverlayMenuContainerWindowMessageHandlers = {
|
export type AutofillInlineMenuMenuContainerWindowMessageHandlers = {
|
||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
initAutofillInlineMenuList: (message: InitOverlayElementMessage) => void;
|
initAutofillInlineMenuList: (message: InitInlineMenuElementMessage) => void;
|
||||||
initAutofillInlineMenuButton: (message: InitOverlayElementMessage) => void;
|
initAutofillInlineMenuButton: (message: InitInlineMenuElementMessage) => void;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,35 +1,25 @@
|
|||||||
type AutofillOverlayIframeExtensionMessage = {
|
export type AutofillInlineMenuIframeExtensionMessage = {
|
||||||
command: string;
|
command: string;
|
||||||
styles?: Partial<CSSStyleDeclaration>;
|
styles?: Partial<CSSStyleDeclaration>;
|
||||||
theme?: string;
|
theme?: string;
|
||||||
portKey?: string;
|
portKey?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type AutofillOverlayIframeWindowMessageHandlers = {
|
export type AutofillInlineMenuIframeExtensionMessageParam = {
|
||||||
[key: string]: CallableFunction;
|
message: AutofillInlineMenuIframeExtensionMessage;
|
||||||
updateAutofillInlineMenuListHeight: (message: AutofillOverlayIframeExtensionMessage) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type AutofillOverlayIframeExtensionMessageParam = {
|
export type BackgroundPortMessageHandlers = {
|
||||||
message: AutofillOverlayIframeExtensionMessage;
|
|
||||||
};
|
|
||||||
|
|
||||||
type BackgroundPortMessageHandlers = {
|
|
||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
initAutofillInlineMenuButton: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
|
initAutofillInlineMenuButton: ({
|
||||||
initAutofillInlineMenuList: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
|
message,
|
||||||
updateIframePosition: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
|
}: AutofillInlineMenuIframeExtensionMessageParam) => void;
|
||||||
updateInlineMenuHidden: ({ message }: AutofillOverlayIframeExtensionMessageParam) => void;
|
initAutofillInlineMenuList: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
|
||||||
|
updateIframePosition: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
|
||||||
|
updateInlineMenuHidden: ({ message }: AutofillInlineMenuIframeExtensionMessageParam) => void;
|
||||||
updateAutofillInlineMenuColorScheme: () => void;
|
updateAutofillInlineMenuColorScheme: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface AutofillInlineMenuIframeService {
|
export interface AutofillInlineMenuIframeService {
|
||||||
initMenuIframe(): void;
|
initMenuIframe(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
|
||||||
AutofillOverlayIframeExtensionMessage,
|
|
||||||
AutofillOverlayIframeWindowMessageHandlers,
|
|
||||||
BackgroundPortMessageHandlers,
|
|
||||||
AutofillInlineMenuIframeService,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
|
|||||||
|
|
||||||
import { OverlayCipherData } from "../../../background/abstractions/overlay.background";
|
import { OverlayCipherData } from "../../../background/abstractions/overlay.background";
|
||||||
|
|
||||||
type OverlayListMessage = { command: string };
|
type AutofillInlineMenuListMessage = { command: string };
|
||||||
|
|
||||||
type UpdateOverlayListCiphersMessage = OverlayListMessage & {
|
export type UpdateAutofillInlineMenuListCiphersMessage = AutofillInlineMenuListMessage & {
|
||||||
ciphers: OverlayCipherData[];
|
ciphers: OverlayCipherData[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type InitAutofillOverlayListMessage = OverlayListMessage & {
|
export type InitAutofillInlineMenuListMessage = AutofillInlineMenuListMessage & {
|
||||||
authStatus: AuthenticationStatus;
|
authStatus: AuthenticationStatus;
|
||||||
styleSheetUrl: string;
|
styleSheetUrl: string;
|
||||||
theme: string;
|
theme: string;
|
||||||
@@ -17,16 +17,14 @@ type InitAutofillOverlayListMessage = OverlayListMessage & {
|
|||||||
portKey: string;
|
portKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OverlayListWindowMessageHandlers = {
|
export type AutofillInlineMenuListWindowMessageHandlers = {
|
||||||
[key: string]: CallableFunction;
|
[key: string]: CallableFunction;
|
||||||
initAutofillInlineMenuList: ({ message }: { message: InitAutofillOverlayListMessage }) => void;
|
initAutofillInlineMenuList: ({ message }: { message: InitAutofillInlineMenuListMessage }) => void;
|
||||||
checkAutofillInlineMenuListFocused: () => void;
|
checkAutofillInlineMenuListFocused: () => void;
|
||||||
updateOverlayListCiphers: ({ message }: { message: UpdateOverlayListCiphersMessage }) => void;
|
updateAutofillInlineMenuListCiphers: ({
|
||||||
|
message,
|
||||||
|
}: {
|
||||||
|
message: UpdateAutofillInlineMenuListCiphersMessage;
|
||||||
|
}) => void;
|
||||||
focusInlineMenuList: () => void;
|
focusInlineMenuList: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
|
||||||
UpdateOverlayListCiphersMessage,
|
|
||||||
InitAutofillOverlayListMessage,
|
|
||||||
OverlayListWindowMessageHandlers,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
import { AutofillInlineMenuButtonWindowMessageHandlers } from "./autofill-inline-menu-button";
|
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
|
| AutofillInlineMenuButtonWindowMessageHandlers
|
||||||
| OverlayListWindowMessageHandlers;
|
| AutofillInlineMenuListWindowMessageHandlers;
|
||||||
|
|
||||||
type AutofillInlineMenuPageElementWindowMessage = {
|
export type AutofillInlineMenuPageElementWindowMessage = {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
command: string;
|
command: string;
|
||||||
overlayCipherId?: string;
|
overlayCipherId?: string;
|
||||||
height?: number;
|
height?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
|
||||||
AutofillInlineMenuPageElementWindowMessageHandlers,
|
|
||||||
AutofillInlineMenuPageElementWindowMessage,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
AutofillInlineMenuContentService as AutofillInlineMenuContentServiceInterface,
|
AutofillInlineMenuContentService as AutofillInlineMenuContentServiceInterface,
|
||||||
} from "../abstractions/autofill-inline-menu-content.service";
|
} from "../abstractions/autofill-inline-menu-content.service";
|
||||||
import { AutofillInlineMenuButtonIframe } from "../iframe-content/autofill-inline-menu-button-iframe";
|
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 {
|
export class AutofillInlineMenuContentService implements AutofillInlineMenuContentServiceInterface {
|
||||||
private readonly sendExtensionMessage = sendExtensionMessage;
|
private readonly sendExtensionMessage = sendExtensionMessage;
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// 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`] = `
|
exports[`AutofillOverlayIframeService initMenuIframe sets up the iframe's attributes 1`] = `
|
||||||
<iframe
|
<iframe
|
||||||
allowtransparency="true"
|
allowtransparency="true"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe("AutofillInlineMenuIframeElement", () => {
|
|||||||
this,
|
this,
|
||||||
AutofillOverlayPort.Button,
|
AutofillOverlayPort.Button,
|
||||||
{ background: "transparent", border: "none" },
|
{ background: "transparent", border: "none" },
|
||||||
"bitwardenOverlayButton",
|
"bitwardenInlineMenuButton",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -41,7 +41,7 @@ describe("AutofillInlineMenuIframeElement", () => {
|
|||||||
expect(iframe.shadowRoot).toBeNull();
|
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);
|
expect(AutofillInlineMenuIframeService).toHaveBeenCalledTimes(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ export class AutofillInlineMenuIframeElement {
|
|||||||
ariaAlert?: string,
|
ariaAlert?: string,
|
||||||
) {
|
) {
|
||||||
const shadow: ShadowRoot = element.attachShadow({ mode: "closed" });
|
const shadow: ShadowRoot = element.attachShadow({ mode: "closed" });
|
||||||
const autofillOverlayIframeService = new AutofillInlineMenuIframeService(
|
const autofillInlineMenuIframeService = new AutofillInlineMenuIframeService(
|
||||||
shadow,
|
shadow,
|
||||||
portName,
|
portName,
|
||||||
initStyles,
|
initStyles,
|
||||||
iframeTitle,
|
iframeTitle,
|
||||||
ariaAlert,
|
ariaAlert,
|
||||||
);
|
);
|
||||||
autofillOverlayIframeService.initMenuIframe();
|
autofillInlineMenuIframeService.initMenuIframe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import {
|
|||||||
|
|
||||||
import { AutofillInlineMenuIframeService } from "./autofill-inline-menu-iframe.service";
|
import { AutofillInlineMenuIframeService } from "./autofill-inline-menu-iframe.service";
|
||||||
|
|
||||||
describe("AutofillOverlayIframeService", () => {
|
describe("AutofillInlineMenuIframeService", () => {
|
||||||
let autofillOverlayIframeService: AutofillInlineMenuIframeService;
|
let autofillInlineMenuIframeService: AutofillInlineMenuIframeService;
|
||||||
let portSpy: chrome.runtime.Port;
|
let portSpy: chrome.runtime.Port;
|
||||||
let shadowAppendSpy: jest.SpyInstance;
|
let shadowAppendSpy: jest.SpyInstance;
|
||||||
let handlePortDisconnectSpy: jest.SpyInstance;
|
let handlePortDisconnectSpy: jest.SpyInstance;
|
||||||
@@ -23,7 +23,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const shadow = document.createElement("div").attachShadow({ mode: "open" });
|
const shadow = document.createElement("div").attachShadow({ mode: "open" });
|
||||||
autofillOverlayIframeService = new AutofillInlineMenuIframeService(
|
autofillInlineMenuIframeService = new AutofillInlineMenuIframeService(
|
||||||
shadow,
|
shadow,
|
||||||
AutofillOverlayPort.Button,
|
AutofillOverlayPort.Button,
|
||||||
{ height: "0px" },
|
{ height: "0px" },
|
||||||
@@ -32,15 +32,15 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
);
|
);
|
||||||
shadowAppendSpy = jest.spyOn(shadow, "appendChild");
|
shadowAppendSpy = jest.spyOn(shadow, "appendChild");
|
||||||
handlePortDisconnectSpy = jest.spyOn(
|
handlePortDisconnectSpy = jest.spyOn(
|
||||||
autofillOverlayIframeService as any,
|
autofillInlineMenuIframeService as any,
|
||||||
"handlePortDisconnect",
|
"handlePortDisconnect",
|
||||||
);
|
);
|
||||||
handlePortMessageSpy = jest.spyOn(autofillOverlayIframeService as any, "handlePortMessage");
|
handlePortMessageSpy = jest.spyOn(autofillInlineMenuIframeService as any, "handlePortMessage");
|
||||||
chrome.runtime.connect = jest.fn((connectInfo: chrome.runtime.ConnectInfo) =>
|
chrome.runtime.connect = jest.fn((connectInfo: chrome.runtime.ConnectInfo) =>
|
||||||
createPortSpyMock(connectInfo.name),
|
createPortSpyMock(connectInfo.name),
|
||||||
) as unknown as typeof chrome.runtime.connect;
|
) as unknown as typeof chrome.runtime.connect;
|
||||||
sendExtensionMessageSpy = jest.spyOn(
|
sendExtensionMessageSpy = jest.spyOn(
|
||||||
autofillOverlayIframeService as any,
|
autofillInlineMenuIframeService as any,
|
||||||
"sendExtensionMessage",
|
"sendExtensionMessage",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -51,44 +51,44 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
describe("initMenuIframe", () => {
|
describe("initMenuIframe", () => {
|
||||||
it("sets up the iframe's attributes", () => {
|
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", () => {
|
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(
|
expect(autofillInlineMenuIframeService["shadow"].appendChild).toHaveBeenCalledWith(
|
||||||
autofillOverlayIframeService["iframe"],
|
autofillInlineMenuIframeService["iframe"],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO CG - This test is brittle and failing due to how we are calling the private method. This needs to be reworked
|
// 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", () => {
|
it.skip("creates an aria alert element if the ariaAlert param is passed", () => {
|
||||||
const ariaAlert = "aria alert";
|
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,
|
ariaAlert,
|
||||||
);
|
);
|
||||||
expect(autofillOverlayIframeService["ariaAlertElement"]).toMatchSnapshot();
|
expect(autofillInlineMenuIframeService["ariaAlertElement"]).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("on load of the iframe source", () => {
|
describe("on load of the iframe source", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
autofillOverlayIframeService.initMenuIframe();
|
autofillInlineMenuIframeService.initMenuIframe();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets up and connects the port message listener to the extension background", () => {
|
it("sets up and connects the port message listener to the extension background", () => {
|
||||||
jest.spyOn(globalThis, "addEventListener");
|
jest.spyOn(globalThis, "addEventListener");
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
||||||
portSpy = autofillOverlayIframeService["port"];
|
portSpy = autofillInlineMenuIframeService["port"];
|
||||||
|
|
||||||
expect(chrome.runtime.connect).toHaveBeenCalledWith({ name: AutofillOverlayPort.Button });
|
expect(chrome.runtime.connect).toHaveBeenCalledWith({ name: AutofillOverlayPort.Button });
|
||||||
expect(portSpy.onDisconnect.addListener).toHaveBeenCalledWith(handlePortDisconnectSpy);
|
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", () => {
|
it("skips announcing the aria alert if the aria alert element is not populated", () => {
|
||||||
jest.spyOn(globalThis, "setTimeout");
|
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();
|
expect(globalThis.setTimeout).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@@ -107,16 +107,16 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
it("announces the aria alert if the aria alert element is populated", () => {
|
it("announces the aria alert if the aria alert element is populated", () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
jest.spyOn(globalThis, "setTimeout");
|
jest.spyOn(globalThis, "setTimeout");
|
||||||
autofillOverlayIframeService["ariaAlertElement"] = document.createElement("div");
|
autofillInlineMenuIframeService["ariaAlertElement"] = document.createElement("div");
|
||||||
autofillOverlayIframeService["ariaAlertTimeout"] = setTimeout(jest.fn(), 2000);
|
autofillInlineMenuIframeService["ariaAlertTimeout"] = setTimeout(jest.fn(), 2000);
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
||||||
|
|
||||||
expect(globalThis.setTimeout).toHaveBeenCalled();
|
expect(globalThis.setTimeout).toHaveBeenCalled();
|
||||||
jest.advanceTimersByTime(2000);
|
jest.advanceTimersByTime(2000);
|
||||||
|
|
||||||
expect(shadowAppendSpy).toHaveBeenCalledWith(
|
expect(shadowAppendSpy).toHaveBeenCalledWith(
|
||||||
autofillOverlayIframeService["ariaAlertElement"],
|
autofillInlineMenuIframeService["ariaAlertElement"],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -124,16 +124,16 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
describe("event listeners", () => {
|
describe("event listeners", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
autofillOverlayIframeService.initMenuIframe();
|
autofillInlineMenuIframeService.initMenuIframe();
|
||||||
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
||||||
Object.defineProperty(autofillOverlayIframeService["iframe"], "contentWindow", {
|
Object.defineProperty(autofillInlineMenuIframeService["iframe"], "contentWindow", {
|
||||||
value: {
|
value: {
|
||||||
postMessage: jest.fn(),
|
postMessage: jest.fn(),
|
||||||
},
|
},
|
||||||
writable: true,
|
writable: true,
|
||||||
});
|
});
|
||||||
jest.spyOn(autofillOverlayIframeService["iframe"].contentWindow, "postMessage");
|
jest.spyOn(autofillInlineMenuIframeService["iframe"].contentWindow, "postMessage");
|
||||||
portSpy = autofillOverlayIframeService["port"];
|
portSpy = autofillInlineMenuIframeService["port"];
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("handlePortDisconnect", () => {
|
describe("handlePortDisconnect", () => {
|
||||||
@@ -141,15 +141,15 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
portSpy.name = "wrong-port-name";
|
portSpy.name = "wrong-port-name";
|
||||||
triggerPortOnDisconnectEvent(portSpy);
|
triggerPortOnDisconnectEvent(portSpy);
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["port"]).not.toBeNull();
|
expect(autofillInlineMenuIframeService["port"]).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("resets the iframe element's opacity, height, and display styles", () => {
|
it("resets the iframe element's opacity, height, and display styles", () => {
|
||||||
triggerPortOnDisconnectEvent(portSpy);
|
triggerPortOnDisconnectEvent(portSpy);
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["iframe"].style.opacity).toBe("0");
|
expect(autofillInlineMenuIframeService["iframe"].style.opacity).toBe("0");
|
||||||
expect(autofillOverlayIframeService["iframe"].style.height).toBe("0px");
|
expect(autofillInlineMenuIframeService["iframe"].style.height).toBe("0px");
|
||||||
expect(autofillOverlayIframeService["iframe"].style.display).toBe("block");
|
expect(autofillInlineMenuIframeService["iframe"].style.display).toBe("block");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("removes the port's onMessage listener", () => {
|
it("removes the port's onMessage listener", () => {
|
||||||
@@ -168,7 +168,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
triggerPortOnDisconnectEvent(portSpy);
|
triggerPortOnDisconnectEvent(portSpy);
|
||||||
|
|
||||||
expect(portSpy.disconnect).toHaveBeenCalled();
|
expect(portSpy.disconnect).toHaveBeenCalled();
|
||||||
expect(autofillOverlayIframeService["port"]).toBeNull();
|
expect(autofillInlineMenuIframeService["port"]).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
sendPortMessage(portSpy, {});
|
sendPortMessage(portSpy, {});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).not.toHaveBeenCalled();
|
).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -188,22 +188,22 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
sendPortMessage(portSpy, message);
|
sendPortMessage(portSpy, message);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).toHaveBeenCalledWith(message, "*");
|
).toHaveBeenCalledWith(message, "*");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles port messages that are registered with the message handlers and does not pass the message on to the iframe", () => {
|
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" });
|
sendPortMessage(portSpy, { command: "updateIframePosition" });
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).not.toHaveBeenCalled();
|
).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("initializing the overlay button", () => {
|
describe("initializing the inline menu button", () => {
|
||||||
it("sets the port key and posts the message to the overlay page iframe", () => {
|
it("sets the port key and posts the message to the inline menu page iframe", () => {
|
||||||
const portKey = "portKey";
|
const portKey = "portKey";
|
||||||
const message = {
|
const message = {
|
||||||
command: "initAutofillInlineMenuButton",
|
command: "initAutofillInlineMenuButton",
|
||||||
@@ -212,19 +212,19 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
sendPortMessage(portSpy, message);
|
sendPortMessage(portSpy, message);
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["portKey"]).toBe(portKey);
|
expect(autofillInlineMenuIframeService["portKey"]).toBe(portKey);
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).toHaveBeenCalledWith(message, "*");
|
).toHaveBeenCalledWith(message, "*");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("initializing the overlay list", () => {
|
describe("initializing the inline menu list", () => {
|
||||||
let updateElementStylesSpy: jest.SpyInstance;
|
let updateElementStylesSpy: jest.SpyInstance;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
updateElementStylesSpy = jest.spyOn(
|
updateElementStylesSpy = jest.spyOn(
|
||||||
autofillOverlayIframeService as any,
|
autofillInlineMenuIframeService as any,
|
||||||
"updateElementStyles",
|
"updateElementStyles",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -239,7 +239,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
expect(updateElementStylesSpy).not.toHaveBeenCalled();
|
expect(updateElementStylesSpy).not.toHaveBeenCalled();
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).toHaveBeenCalledWith(message, "*");
|
).toHaveBeenCalledWith(message, "*");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
|
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).toHaveBeenCalledWith(
|
).toHaveBeenCalledWith(
|
||||||
{
|
{
|
||||||
command: "initAutofillInlineMenuList",
|
command: "initAutofillInlineMenuList",
|
||||||
@@ -275,7 +275,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
|
expect(window.matchMedia).toHaveBeenCalledWith("(prefers-color-scheme: dark)");
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).toHaveBeenCalledWith(
|
).toHaveBeenCalledWith(
|
||||||
{
|
{
|
||||||
command: "initAutofillInlineMenuList",
|
command: "initAutofillInlineMenuList",
|
||||||
@@ -294,7 +294,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
sendPortMessage(portSpy, message);
|
sendPortMessage(portSpy, message);
|
||||||
|
|
||||||
expect(updateElementStylesSpy).toHaveBeenCalledWith(
|
expect(updateElementStylesSpy).toHaveBeenCalledWith(
|
||||||
autofillOverlayIframeService["iframe"],
|
autofillInlineMenuIframeService["iframe"],
|
||||||
{
|
{
|
||||||
borderColor: "#4c525f",
|
borderColor: "#4c525f",
|
||||||
},
|
},
|
||||||
@@ -310,7 +310,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
sendPortMessage(portSpy, message);
|
sendPortMessage(portSpy, message);
|
||||||
|
|
||||||
expect(updateElementStylesSpy).toHaveBeenCalledWith(
|
expect(updateElementStylesSpy).toHaveBeenCalledWith(
|
||||||
autofillOverlayIframeService["iframe"],
|
autofillInlineMenuIframeService["iframe"],
|
||||||
{
|
{
|
||||||
borderColor: "#2E3440",
|
borderColor: "#2E3440",
|
||||||
},
|
},
|
||||||
@@ -326,7 +326,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
sendPortMessage(portSpy, message);
|
sendPortMessage(portSpy, message);
|
||||||
|
|
||||||
expect(updateElementStylesSpy).toHaveBeenCalledWith(
|
expect(updateElementStylesSpy).toHaveBeenCalledWith(
|
||||||
autofillOverlayIframeService["iframe"],
|
autofillInlineMenuIframeService["iframe"],
|
||||||
{
|
{
|
||||||
borderColor: "#073642",
|
borderColor: "#073642",
|
||||||
},
|
},
|
||||||
@@ -340,7 +340,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("ignores updating the iframe position if the document does not have focus", () => {
|
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);
|
jest.spyOn(globalThis.document, "hasFocus").mockReturnValue(false);
|
||||||
|
|
||||||
sendPortMessage(portSpy, {
|
sendPortMessage(portSpy, {
|
||||||
@@ -348,7 +348,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
styles: { top: 100, left: 100 },
|
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", () => {
|
it("updates the iframe position if the document has focus", () => {
|
||||||
@@ -359,8 +359,8 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
styles,
|
styles,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["iframe"].style.top).toBe(styles.top);
|
expect(autofillInlineMenuIframeService["iframe"].style.top).toBe(styles.top);
|
||||||
expect(autofillOverlayIframeService["iframe"].style.left).toBe(styles.left);
|
expect(autofillInlineMenuIframeService["iframe"].style.left).toBe(styles.left);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fades the iframe element in after positioning the element", () => {
|
it("fades the iframe element in after positioning the element", () => {
|
||||||
@@ -372,9 +372,9 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
styles,
|
styles,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["iframe"].style.opacity).toBe("0");
|
expect(autofillInlineMenuIframeService["iframe"].style.opacity).toBe("0");
|
||||||
jest.advanceTimersByTime(10);
|
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", () => {
|
it("announces the opening of the iframe using an aria alert", () => {
|
||||||
@@ -388,7 +388,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
jest.advanceTimersByTime(2000);
|
jest.advanceTimersByTime(2000);
|
||||||
expect(shadowAppendSpy).toHaveBeenCalledWith(
|
expect(shadowAppendSpy).toHaveBeenCalledWith(
|
||||||
autofillOverlayIframeService["ariaAlertElement"],
|
autofillInlineMenuIframeService["ariaAlertElement"],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -399,7 +399,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
styles: { display: "none" },
|
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", () => {
|
it("updates the button based on the web page's color scheme", () => {
|
||||||
@@ -408,7 +408,7 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
autofillOverlayIframeService["iframe"].contentWindow.postMessage,
|
autofillInlineMenuIframeService["iframe"].contentWindow.postMessage,
|
||||||
).toHaveBeenCalledWith(
|
).toHaveBeenCalledWith(
|
||||||
{
|
{
|
||||||
command: "updateAutofillInlineMenuColorScheme",
|
command: "updateAutofillInlineMenuColorScheme",
|
||||||
@@ -422,41 +422,41 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
describe("mutation observer", () => {
|
describe("mutation observer", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
autofillOverlayIframeService.initMenuIframe();
|
autofillInlineMenuIframeService.initMenuIframe();
|
||||||
autofillOverlayIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
autofillInlineMenuIframeService["iframe"].dispatchEvent(new Event(EVENTS.LOAD));
|
||||||
portSpy = autofillOverlayIframeService["port"];
|
portSpy = autofillInlineMenuIframeService["port"];
|
||||||
});
|
});
|
||||||
|
|
||||||
it("skips handling found mutations if excessive mutations are triggering", async () => {
|
it("skips handling found mutations if excessive mutations are triggering", async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
jest
|
jest
|
||||||
.spyOn(
|
.spyOn(
|
||||||
autofillOverlayIframeService as any,
|
autofillInlineMenuIframeService as any,
|
||||||
"isTriggeringExcessiveMutationObserverIterations",
|
"isTriggeringExcessiveMutationObserverIterations",
|
||||||
)
|
)
|
||||||
.mockReturnValue(true);
|
.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();
|
await flushPromises();
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["updateElementStyles"]).not.toHaveBeenCalled();
|
expect(autofillInlineMenuIframeService["updateElementStyles"]).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("reverts any styles changes made directly to the iframe", async () => {
|
it("reverts any styles changes made directly to the iframe", async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].style.visibility = "hidden";
|
autofillInlineMenuIframeService["iframe"].style.visibility = "hidden";
|
||||||
await flushPromises();
|
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();
|
jest.useFakeTimers();
|
||||||
autofillOverlayIframeService["foreignMutationsCount"] = 10;
|
autofillInlineMenuIframeService["foreignMutationsCount"] = 10;
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].src = "http://malicious-site.com";
|
autofillInlineMenuIframeService["iframe"].src = "http://malicious-site.com";
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
|
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();
|
jest.useFakeTimers();
|
||||||
autofillOverlayIframeService["mutationObserverIterations"] = 20;
|
autofillInlineMenuIframeService["mutationObserverIterations"] = 20;
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].src = "http://malicious-site.com";
|
autofillInlineMenuIframeService["iframe"].src = "http://malicious-site.com";
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
|
expect(sendExtensionMessageSpy).toHaveBeenCalledWith("closeAutofillInlineMenu", {
|
||||||
@@ -478,24 +478,24 @@ describe("AutofillOverlayIframeService", () => {
|
|||||||
|
|
||||||
it("resets the excessive mutations and foreign mutation counters", async () => {
|
it("resets the excessive mutations and foreign mutation counters", async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
autofillOverlayIframeService["foreignMutationsCount"] = 9;
|
autofillInlineMenuIframeService["foreignMutationsCount"] = 9;
|
||||||
autofillOverlayIframeService["mutationObserverIterations"] = 19;
|
autofillInlineMenuIframeService["mutationObserverIterations"] = 19;
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].src = "http://malicious-site.com";
|
autofillInlineMenuIframeService["iframe"].src = "http://malicious-site.com";
|
||||||
jest.advanceTimersByTime(2001);
|
jest.advanceTimersByTime(2001);
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["foreignMutationsCount"]).toBe(0);
|
expect(autofillInlineMenuIframeService["foreignMutationsCount"]).toBe(0);
|
||||||
expect(autofillOverlayIframeService["mutationObserverIterations"]).toBe(0);
|
expect(autofillInlineMenuIframeService["mutationObserverIterations"]).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("resets any mutated default attributes for the iframe", async () => {
|
it("resets any mutated default attributes for the iframe", async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
autofillOverlayIframeService["iframe"].title = "some-other-title";
|
autofillInlineMenuIframeService["iframe"].title = "some-other-title";
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
expect(autofillOverlayIframeService["iframe"].title).toBe("title");
|
expect(autofillInlineMenuIframeService["iframe"].title).toBe("title");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import { ThemeType } from "@bitwarden/common/platform/enums";
|
|||||||
import { sendExtensionMessage, setElementStyles } from "../../../utils";
|
import { sendExtensionMessage, setElementStyles } from "../../../utils";
|
||||||
import {
|
import {
|
||||||
BackgroundPortMessageHandlers,
|
BackgroundPortMessageHandlers,
|
||||||
AutofillInlineMenuIframeService as AutofillOverlayIframeServiceInterface,
|
AutofillInlineMenuIframeService as AutofillInlineMenuIframeServiceInterface,
|
||||||
AutofillOverlayIframeExtensionMessage,
|
AutofillInlineMenuIframeExtensionMessage,
|
||||||
} from "../abstractions/autofill-inline-menu-iframe.service";
|
} from "../abstractions/autofill-inline-menu-iframe.service";
|
||||||
|
|
||||||
export class AutofillInlineMenuIframeService implements AutofillOverlayIframeServiceInterface {
|
export class AutofillInlineMenuIframeService implements AutofillInlineMenuIframeServiceInterface {
|
||||||
private sendExtensionMessage = sendExtensionMessage;
|
private sendExtensionMessage = sendExtensionMessage;
|
||||||
private port: chrome.runtime.Port | null = null;
|
private port: chrome.runtime.Port | null = null;
|
||||||
private portKey: string;
|
private portKey: string;
|
||||||
@@ -167,7 +167,7 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
|
|||||||
* @param port
|
* @param port
|
||||||
*/
|
*/
|
||||||
private handlePortMessage = (
|
private handlePortMessage = (
|
||||||
message: AutofillOverlayIframeExtensionMessage,
|
message: AutofillInlineMenuIframeExtensionMessage,
|
||||||
port: chrome.runtime.Port,
|
port: chrome.runtime.Port,
|
||||||
) => {
|
) => {
|
||||||
if (port.name !== this.portName) {
|
if (port.name !== this.portName) {
|
||||||
@@ -183,13 +183,13 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the initialization of the autofill overlay. This includes setting
|
* Handles the initialization of the autofill inline menu. This includes setting
|
||||||
* the port key and sending a message to the iframe to initialize the overlay.
|
* the port key and sending a message to the iframe to initialize the inline menu.
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private initAutofillInlineMenu(message: AutofillOverlayIframeExtensionMessage) {
|
private initAutofillInlineMenu(message: AutofillInlineMenuIframeExtensionMessage) {
|
||||||
this.portKey = message.portKey;
|
this.portKey = message.portKey;
|
||||||
if (message.command === "initAutofillInlineMenuList") {
|
if (message.command === "initAutofillInlineMenuList") {
|
||||||
this.initAutofillInlineMenuList(message);
|
this.initAutofillInlineMenuList(message);
|
||||||
@@ -200,12 +200,12 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles initialization of the autofill overlay list. This includes setting
|
* Handles initialization of the autofill inline menu list. This includes setting
|
||||||
* the theme and sending a message to the iframe to initialize the overlay.
|
* the theme and sending a message to the iframe to initialize the inline menu.
|
||||||
*
|
*
|
||||||
* @param message - The message sent from the iframe
|
* @param message - The message sent from the iframe
|
||||||
*/
|
*/
|
||||||
private initAutofillInlineMenuList(message: AutofillOverlayIframeExtensionMessage) {
|
private initAutofillInlineMenuList(message: AutofillInlineMenuIframeExtensionMessage) {
|
||||||
const { theme } = message;
|
const { theme } = message;
|
||||||
let borderColor: string;
|
let borderColor: string;
|
||||||
let verifiedTheme = theme;
|
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.
|
* mutation observer is triggered excessively.
|
||||||
*/
|
*/
|
||||||
private forceCloseAutofillInlineMenu() {
|
private forceCloseAutofillInlineMenu() {
|
||||||
@@ -378,7 +378,7 @@ export class AutofillInlineMenuIframeService implements AutofillOverlayIframeSer
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifies if the mutation observer is triggering excessive iterations.
|
* 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.
|
* triggering excessive iterations.
|
||||||
*/
|
*/
|
||||||
private isTriggeringExcessiveMutationObserverIterations() {
|
private isTriggeringExcessiveMutationObserverIterations() {
|
||||||
|
|||||||
@@ -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(
|
window.customElements.define(
|
||||||
"autofill-overlay-list-iframe",
|
"autofill-inline-menu-list-iframe",
|
||||||
class extends HTMLElement {
|
class extends HTMLElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@@ -16,9 +16,10 @@ describe("AutofillOverlayListIframe", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("creates a custom element that is an instance of the AutofillIframeElement parent class", () => {
|
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).toBeInstanceOf(HTMLElement);
|
||||||
expect(iframe.shadowRoot).toBeDefined();
|
expect(iframe.shadowRoot).toBeDefined();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { AutofillOverlayPort } from "../../../enums/autofill-overlay.enum";
|
|||||||
|
|
||||||
import { AutofillInlineMenuIframeElement } from "./autofill-inline-menu-iframe-element";
|
import { AutofillInlineMenuIframeElement } from "./autofill-inline-menu-iframe-element";
|
||||||
|
|
||||||
class AutofillInlineMenuListIframe extends AutofillInlineMenuIframeElement {
|
export class AutofillInlineMenuListIframe extends AutofillInlineMenuIframeElement {
|
||||||
constructor(element: HTMLElement) {
|
constructor(element: HTMLElement) {
|
||||||
super(
|
super(
|
||||||
element,
|
element,
|
||||||
@@ -21,5 +21,3 @@ class AutofillInlineMenuListIframe extends AutofillInlineMenuIframeElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AutofillInlineMenuListIframe;
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
`;
|
||||||
@@ -5,22 +5,22 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
|
|||||||
import { createInitAutofillOverlayListMessageMock } from "../../../../spec/autofill-mocks";
|
import { createInitAutofillOverlayListMessageMock } from "../../../../spec/autofill-mocks";
|
||||||
import { flushPromises, postWindowMessage } from "../../../../spec/testing-utils";
|
import { flushPromises, postWindowMessage } from "../../../../spec/testing-utils";
|
||||||
|
|
||||||
import AutofillOverlayList from "./autofill-overlay-list";
|
import { AutofillInlineMenuList } from "./autofill-inline-menu-list";
|
||||||
|
|
||||||
describe("AutofillOverlayList", () => {
|
describe("AutofillOverlayList", () => {
|
||||||
globalThis.customElements.define("autofill-overlay-list", AutofillOverlayList);
|
globalThis.customElements.define("autofill-inline-menu-list", AutofillInlineMenuList);
|
||||||
global.ResizeObserver = jest.fn().mockImplementation(() => ({
|
global.ResizeObserver = jest.fn().mockImplementation(() => ({
|
||||||
observe: jest.fn(),
|
observe: jest.fn(),
|
||||||
unobserve: jest.fn(),
|
unobserve: jest.fn(),
|
||||||
disconnect: jest.fn(),
|
disconnect: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let autofillOverlayList: AutofillOverlayList;
|
let autofillOverlayList: AutofillInlineMenuList;
|
||||||
const portKey: string = "overlayListPortKey";
|
const portKey: string = "overlayListPortKey";
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
document.body.innerHTML = `<autofill-overlay-list></autofill-overlay-list>`;
|
document.body.innerHTML = `<autofill-inline-menu-list></autofill-inline-menu-list>`;
|
||||||
autofillOverlayList = document.querySelector("autofill-overlay-list");
|
autofillOverlayList = document.querySelector("autofill-inline-menu-list");
|
||||||
jest.spyOn(globalThis.document, "createElement");
|
jest.spyOn(globalThis.document, "createElement");
|
||||||
jest.spyOn(globalThis.parent, "postMessage");
|
jest.spyOn(globalThis.parent, "postMessage");
|
||||||
});
|
});
|
||||||
@@ -312,7 +312,7 @@ describe("AutofillOverlayList", () => {
|
|||||||
postWindowMessage(createInitAutofillOverlayListMessageMock());
|
postWindowMessage(createInitAutofillOverlayListMessageMock());
|
||||||
const updateCiphersSpy = jest.spyOn(autofillOverlayList as any, "updateListItems");
|
const updateCiphersSpy = jest.spyOn(autofillOverlayList as any, "updateListItems");
|
||||||
|
|
||||||
postWindowMessage({ command: "updateOverlayListCiphers" });
|
postWindowMessage({ command: "updateAutofillInlineMenuListCiphers" });
|
||||||
|
|
||||||
expect(updateCiphersSpy).toHaveBeenCalled();
|
expect(updateCiphersSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@@ -7,12 +7,12 @@ import { OverlayCipherData } from "../../../../background/abstractions/overlay.b
|
|||||||
import { buildSvgDomElement } from "../../../../utils";
|
import { buildSvgDomElement } from "../../../../utils";
|
||||||
import { globeIcon, lockIcon, plusIcon, viewCipherIcon } from "../../../../utils/svg-icons";
|
import { globeIcon, lockIcon, plusIcon, viewCipherIcon } from "../../../../utils/svg-icons";
|
||||||
import {
|
import {
|
||||||
InitAutofillOverlayListMessage,
|
InitAutofillInlineMenuListMessage,
|
||||||
OverlayListWindowMessageHandlers,
|
AutofillInlineMenuListWindowMessageHandlers,
|
||||||
} from "../../abstractions/autofill-inline-menu-list";
|
} from "../../abstractions/autofill-inline-menu-list";
|
||||||
import { AutofillInlineMenuPageElement } from "../shared/autofill-inline-menu-page-element";
|
import { AutofillInlineMenuPageElement } from "../shared/autofill-inline-menu-page-element";
|
||||||
|
|
||||||
class AutofillOverlayList extends AutofillInlineMenuPageElement {
|
export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
|
||||||
private overlayListContainer: HTMLDivElement;
|
private overlayListContainer: HTMLDivElement;
|
||||||
private resizeObserver: ResizeObserver;
|
private resizeObserver: ResizeObserver;
|
||||||
private eventHandlersMemo: { [key: string]: EventListener } = {};
|
private eventHandlersMemo: { [key: string]: EventListener } = {};
|
||||||
@@ -22,10 +22,10 @@ class AutofillOverlayList extends AutofillInlineMenuPageElement {
|
|||||||
private cipherListScrollDebounceTimeout: number | NodeJS.Timeout;
|
private cipherListScrollDebounceTimeout: number | NodeJS.Timeout;
|
||||||
private currentCipherIndex = 0;
|
private currentCipherIndex = 0;
|
||||||
private readonly showCiphersPerPage = 6;
|
private readonly showCiphersPerPage = 6;
|
||||||
private readonly overlayListWindowMessageHandlers: OverlayListWindowMessageHandlers = {
|
private readonly overlayListWindowMessageHandlers: AutofillInlineMenuListWindowMessageHandlers = {
|
||||||
initAutofillInlineMenuList: ({ message }) => this.initAutofillInlineMenuList(message),
|
initAutofillInlineMenuList: ({ message }) => this.initAutofillInlineMenuList(message),
|
||||||
checkAutofillInlineMenuListFocused: () => this.checkInlineMenuListFocused(),
|
checkAutofillInlineMenuListFocused: () => this.checkInlineMenuListFocused(),
|
||||||
updateOverlayListCiphers: ({ message }) => this.updateListItems(message.ciphers),
|
updateAutofillInlineMenuListCiphers: ({ message }) => this.updateListItems(message.ciphers),
|
||||||
focusInlineMenuList: () => this.focusInlineMenuList(),
|
focusInlineMenuList: () => this.focusInlineMenuList(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ class AutofillOverlayList extends AutofillInlineMenuPageElement {
|
|||||||
authStatus,
|
authStatus,
|
||||||
ciphers,
|
ciphers,
|
||||||
portKey,
|
portKey,
|
||||||
}: InitAutofillOverlayListMessage) {
|
}: InitAutofillInlineMenuListMessage) {
|
||||||
const linkElement = await this.initAutofillInlineMenuPage(
|
const linkElement = await this.initAutofillInlineMenuPage(
|
||||||
"list",
|
"list",
|
||||||
styleSheetUrl,
|
styleSheetUrl,
|
||||||
@@ -619,5 +619,3 @@ class AutofillOverlayList extends AutofillInlineMenuPageElement {
|
|||||||
nextSibling?.focus();
|
nextSibling?.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AutofillOverlayList;
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { AutofillOverlayElement } from "../../../../enums/autofill-overlay.enum";
|
import { AutofillOverlayElement } from "../../../../enums/autofill-overlay.enum";
|
||||||
|
|
||||||
import AutofillOverlayList from "./autofill-overlay-list";
|
import { AutofillInlineMenuList } from "./autofill-inline-menu-list";
|
||||||
|
|
||||||
require("./list.scss");
|
require("./list.scss");
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
globalThis.customElements.define(AutofillOverlayElement.List, AutofillOverlayList);
|
globalThis.customElements.define(AutofillOverlayElement.List, AutofillInlineMenuList);
|
||||||
})();
|
})();
|
||||||
@@ -7,6 +7,6 @@
|
|||||||
<meta name="color-scheme" content="normal" />
|
<meta name="color-scheme" content="normal" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<autofill-overlay-list></autofill-overlay-list>
|
<autofill-inline-menu-list></autofill-inline-menu-list>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { EVENTS } from "@bitwarden/common/autofill/constants";
|
|||||||
|
|
||||||
import { setElementStyles } from "../../../../utils";
|
import { setElementStyles } from "../../../../utils";
|
||||||
import {
|
import {
|
||||||
InitOverlayElementMessage,
|
InitInlineMenuElementMessage,
|
||||||
AutofillOverlayMenuContainerWindowMessageHandlers,
|
AutofillInlineMenuMenuContainerWindowMessageHandlers,
|
||||||
} from "../../abstractions/autofill-inline-menu-container";
|
} from "../../abstractions/autofill-inline-menu-container";
|
||||||
|
|
||||||
export class AutofillOverlayMenuContainer {
|
export class AutofillInlineMenuContainer {
|
||||||
private extensionOriginsSet: Set<string>;
|
private extensionOriginsSet: Set<string>;
|
||||||
private port: chrome.runtime.Port | null = null;
|
private port: chrome.runtime.Port | null = null;
|
||||||
private portName: string;
|
private portName: string;
|
||||||
@@ -36,9 +36,9 @@ export class AutofillOverlayMenuContainer {
|
|||||||
allowtransparency: "true",
|
allowtransparency: "true",
|
||||||
tabIndex: "-1",
|
tabIndex: "-1",
|
||||||
};
|
};
|
||||||
private windowMessageHandlers: AutofillOverlayMenuContainerWindowMessageHandlers = {
|
private windowMessageHandlers: AutofillInlineMenuMenuContainerWindowMessageHandlers = {
|
||||||
initAutofillInlineMenuList: (message) => this.handleInitOverlayIframe(message),
|
initAutofillInlineMenuList: (message) => this.handleInitInlineMenuIframe(message),
|
||||||
initAutofillInlineMenuButton: (message) => this.handleInitOverlayIframe(message),
|
initAutofillInlineMenuButton: (message) => this.handleInitInlineMenuIframe(message),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -50,7 +50,7 @@ export class AutofillOverlayMenuContainer {
|
|||||||
globalThis.addEventListener("message", this.handleWindowMessage);
|
globalThis.addEventListener("message", this.handleWindowMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleInitOverlayIframe(message: InitOverlayElementMessage) {
|
private handleInitInlineMenuIframe(message: InitInlineMenuElementMessage) {
|
||||||
this.defaultIframeAttributes.src = message.iframeUrl;
|
this.defaultIframeAttributes.src = message.iframeUrl;
|
||||||
this.defaultIframeAttributes.title = message.pageTitle;
|
this.defaultIframeAttributes.title = message.pageTitle;
|
||||||
this.portName = message.portName;
|
this.portName = message.portName;
|
||||||
@@ -67,7 +67,7 @@ export class AutofillOverlayMenuContainer {
|
|||||||
globalThis.document.body.appendChild(this.overlayPageIframe);
|
globalThis.document.body.appendChild(this.overlayPageIframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupPortMessageListener = (message: InitOverlayElementMessage) => {
|
private setupPortMessageListener = (message: InitInlineMenuElementMessage) => {
|
||||||
this.port = chrome.runtime.connect({ name: this.portName });
|
this.port = chrome.runtime.connect({ name: this.portName });
|
||||||
this.port.onMessage.addListener(this.handlePortMessage);
|
this.port.onMessage.addListener(this.handlePortMessage);
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { AutofillInlineMenuContainer } from "./autofill-inline-menu-container";
|
||||||
|
|
||||||
|
(() => new AutofillInlineMenuContainer())();
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { AutofillOverlayMenuContainer } from "./autofill-overlay-menu-container";
|
|
||||||
|
|
||||||
(() => new AutofillOverlayMenuContainer())();
|
|
||||||
@@ -13,7 +13,7 @@ import AutofillForm from "../models/autofill-form";
|
|||||||
import AutofillPageDetails from "../models/autofill-page-details";
|
import AutofillPageDetails from "../models/autofill-page-details";
|
||||||
import AutofillScript, { FillScript } from "../models/autofill-script";
|
import AutofillScript, { FillScript } from "../models/autofill-script";
|
||||||
import { InitAutofillInlineMenuButtonMessage } from "../overlay/inline-menu/abstractions/autofill-inline-menu-button";
|
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";
|
import { GenerateFillScriptOptions, PageDetail } from "../services/abstractions/autofill.service";
|
||||||
|
|
||||||
function createAutofillFormMock(customFields = {}): AutofillForm {
|
function createAutofillFormMock(customFields = {}): AutofillForm {
|
||||||
@@ -197,7 +197,7 @@ function createAutofillOverlayCipherDataMock(index: number, customFields = {}):
|
|||||||
|
|
||||||
function createInitAutofillOverlayListMessageMock(
|
function createInitAutofillOverlayListMessageMock(
|
||||||
customFields = {},
|
customFields = {},
|
||||||
): InitAutofillOverlayListMessage {
|
): InitAutofillInlineMenuListMessage {
|
||||||
return {
|
return {
|
||||||
command: "initAutofillInlineMenuList",
|
command: "initAutofillInlineMenuList",
|
||||||
translations: overlayPagesTranslations,
|
translations: overlayPagesTranslations,
|
||||||
|
|||||||
@@ -177,9 +177,9 @@ const mainConfig = {
|
|||||||
"overlay/button":
|
"overlay/button":
|
||||||
"./src/autofill/overlay/inline-menu/pages/button/bootstrap-autofill-inline-menu-button.ts",
|
"./src/autofill/overlay/inline-menu/pages/button/bootstrap-autofill-inline-menu-button.ts",
|
||||||
"overlay/list":
|
"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":
|
"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",
|
"encrypt-worker": "../../libs/common/src/platform/services/cryptography/encrypt.worker.ts",
|
||||||
"content/lp-fileless-importer": "./src/tools/content/lp-fileless-importer.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",
|
"content/send-on-installed-message": "./src/vault/content/send-on-installed-message.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user