[PM-8833] Fixing broken jest tests for OverlayBackground

This commit is contained in:
Cesar Gonzalez 2024-09-26 11:57:00 -05:00
parent da2dc3c66f
commit 23a369bdf6
No known key found for this signature in database
GPG Key ID: 3381A5457F8CCECF
1 changed files with 100 additions and 258 deletions

View File

@ -43,6 +43,7 @@ import { BrowserPlatformUtilsService } from "../../platform/services/platform-ut
import {
AutofillOverlayElement,
AutofillOverlayPort,
InlineMenuFillType,
MAX_SUB_FRAME_DEPTH,
RedirectFocusDirection,
} from "../enums/autofill-overlay.enum";
@ -121,6 +122,7 @@ describe("OverlayBackground", () => {
const { initList, initButton } = options;
if (initButton) {
triggerPortOnConnectEvent(createPortSpyMock(AutofillOverlayPort.Button));
await flushPromises();
buttonPortSpy = overlayBackground["inlineMenuButtonPort"];
buttonMessageConnectorSpy = createPortSpyMock(AutofillOverlayPort.ButtonMessageConnector);
@ -129,6 +131,7 @@ describe("OverlayBackground", () => {
if (initList) {
triggerPortOnConnectEvent(createPortSpyMock(AutofillOverlayPort.List));
await flushPromises();
listPortSpy = overlayBackground["inlineMenuListPort"];
listMessageConnectorSpy = createPortSpyMock(AutofillOverlayPort.ListMessageConnector);
@ -173,7 +176,9 @@ describe("OverlayBackground", () => {
selectedThemeMock$ = new BehaviorSubject(ThemeType.Light);
inlineMenuFieldQualificationService = mock<InlineMenuFieldQualificationService>();
themeStateService = mock<ThemeStateService>();
passwordGenerationService = mock<PasswordGenerationServiceAbstraction>();
passwordGenerationService = mock<PasswordGenerationServiceAbstraction>({
getOptions: jest.fn().mockResolvedValue([null, null]),
});
themeStateService.selectedTheme$ = selectedThemeMock$;
overlayBackground = new OverlayBackground(
logService,
@ -560,7 +565,10 @@ describe("OverlayBackground", () => {
command: "updateIsFieldCurrentlyFocused",
isFieldCurrentlyFocused: false,
},
mock<chrome.runtime.MessageSender>({ frameId: 20 }),
mock<chrome.runtime.MessageSender>({
tab: createChromeTabMock({ id: 1 }),
frameId: 20,
}),
);
sendMockExtensionMessage({ command: "triggerAutofillOverlayReposition" }, sender);
@ -800,21 +808,6 @@ describe("OverlayBackground", () => {
expect(cipherService.getAllDecryptedForUrl).not.toHaveBeenCalled();
});
it("closes the inline menu on the focused field's tab if the user's auth status is not unlocked", async () => {
activeAccountStatusMock$.next(AuthenticationStatus.Locked);
const previousTab = mock<chrome.tabs.Tab>({ id: 1 });
overlayBackground["focusedFieldData"] = createFocusedFieldDataMock({ tabId: 1 });
getTabSpy.mockResolvedValueOnce(previousTab);
await overlayBackground.updateOverlayCiphers();
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
previousTab,
{ command: "closeAutofillInlineMenu", overlayElement: undefined },
{ frameId: 0 },
);
});
it("closes the inline menu on the focused field's tab if current tab is different", async () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
cipherService.getAllDecryptedForUrl.mockResolvedValue([loginCipher1, cardCipher]);
@ -824,6 +817,7 @@ describe("OverlayBackground", () => {
getTabSpy.mockResolvedValueOnce(previousTab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
previousTab,
@ -838,6 +832,7 @@ describe("OverlayBackground", () => {
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(BrowserApi.getTabFromCurrentWindowId).toHaveBeenCalled();
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith(url, [
@ -860,6 +855,7 @@ describe("OverlayBackground", () => {
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
await overlayBackground.updateOverlayCiphers(false);
await flushPromises();
expect(BrowserApi.getTabFromCurrentWindowId).toHaveBeenCalled();
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith(url);
@ -878,6 +874,7 @@ describe("OverlayBackground", () => {
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
await overlayBackground.updateOverlayCiphers(false);
await flushPromises();
expect(BrowserApi.getTabFromCurrentWindowId).toHaveBeenCalled();
expect(cipherService.getAllDecryptedForUrl).toHaveBeenCalledWith(url, [
@ -893,18 +890,20 @@ describe("OverlayBackground", () => {
);
});
it("posts an `updateOverlayListCiphers` message to the overlay list port, and send a `updateAutofillInlineMenuListCiphers` message to the tab indicating that the list of ciphers is populated", async () => {
it("posts an `updateAutofillInlineMenuListCiphers` message to the overlay list port, and send a `updateAutofillInlineMenuListCiphers` message to the tab indicating that the list of ciphers is populated", async () => {
overlayBackground["focusedFieldData"] = createFocusedFieldDataMock({ tabId: tab.id });
cipherService.getAllDecryptedForUrl.mockResolvedValue([loginCipher1]);
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
showInlineMenuAccountCreation: false,
showPasskeysLabels: false,
focusedFieldHasValue: false,
ciphers: [
{
accountCreationFieldType: undefined,
@ -938,11 +937,13 @@ describe("OverlayBackground", () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
showInlineMenuAccountCreation: false,
showPasskeysLabels: false,
focusedFieldHasValue: false,
ciphers: [
{
accountCreationFieldType: undefined,
@ -974,11 +975,13 @@ describe("OverlayBackground", () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
showInlineMenuAccountCreation: true,
showPasskeysLabels: false,
focusedFieldHasValue: false,
ciphers: [
{
accountCreationFieldType: "text",
@ -1006,17 +1009,20 @@ describe("OverlayBackground", () => {
overlayBackground["focusedFieldData"] = createFocusedFieldDataMock({
tabId: tab.id,
accountCreationFieldType: "text",
inlineMenuFillType: InlineMenuFillType.AccountCreationUsername,
});
cipherService.getAllDecryptedForUrl.mockResolvedValue([loginCipher1, identityCipher]);
cipherService.sortCiphersByLastUsedThenName.mockReturnValue(-1);
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
showInlineMenuAccountCreation: true,
showPasskeysLabels: false,
focusedFieldHasValue: false,
ciphers: [
{
accountCreationFieldType: "text",
@ -1081,11 +1087,13 @@ describe("OverlayBackground", () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
showInlineMenuAccountCreation: true,
showPasskeysLabels: false,
focusedFieldHasValue: false,
ciphers: [
{
accountCreationFieldType: "email",
@ -1119,11 +1127,13 @@ describe("OverlayBackground", () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
showInlineMenuAccountCreation: true,
showPasskeysLabels: false,
focusedFieldHasValue: false,
ciphers: [],
});
});
@ -1145,6 +1155,7 @@ describe("OverlayBackground", () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
@ -1209,6 +1220,7 @@ describe("OverlayBackground", () => {
],
showInlineMenuAccountCreation: false,
showPasskeysLabels: true,
focusedFieldHasValue: false,
});
});
@ -1229,6 +1241,7 @@ describe("OverlayBackground", () => {
neverDomainsMock$.next({ "jest-testing-website.com": null });
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
@ -1272,6 +1285,7 @@ describe("OverlayBackground", () => {
],
showInlineMenuAccountCreation: false,
showPasskeysLabels: false,
focusedFieldHasValue: false,
});
});
@ -1292,6 +1306,7 @@ describe("OverlayBackground", () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(tab);
await overlayBackground.updateOverlayCiphers();
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuListCiphers",
@ -1335,6 +1350,7 @@ describe("OverlayBackground", () => {
],
showInlineMenuAccountCreation: false,
showPasskeysLabels: false,
focusedFieldHasValue: false,
});
});
});
@ -1888,6 +1904,7 @@ describe("OverlayBackground", () => {
ciphers: [],
showInlineMenuAccountCreation: true,
showPasskeysLabels: false,
focusedFieldHasValue: false,
});
});
@ -2009,45 +2026,51 @@ describe("OverlayBackground", () => {
let sender: chrome.runtime.MessageSender;
beforeEach(() => {
sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
sender = mock<chrome.runtime.MessageSender>({
tab: createChromeTabMock({ id: 1, url: "https://jest-testing-website.com" }),
});
getTabFromCurrentWindowIdSpy.mockResolvedValue(sender.tab);
tabsSendMessageSpy.mockImplementation();
});
it("opens the autofill inline menu by sending a message to the current tab", async () => {
sendMockExtensionMessage({ command: "openAutofillInlineMenu" }, sender);
await flushPromises();
it.todo(
"updates the inline menu position of both button and list elements if the inline menu is being forced open",
);
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
sender.tab,
{
command: "openAutofillInlineMenu",
isFocusingFieldElement: false,
isOpeningFullInlineMenu: false,
authStatus: AuthenticationStatus.Unlocked,
},
{ frameId: 0 },
describe("when the focused field does not have a value", () => {
beforeEach(() => {
jest
.spyOn(overlayBackground as any, "checkMostRecentlyFocusedFieldHasValue")
.mockResolvedValue(true);
});
it.todo(
"updates the position of the both button and list elements if the user has the inline menu set to show on field focus",
);
it.todo(
"closes the list if the user has the inline menu set to show on button click and the list is open",
);
it.todo(
"updates the position of the button if the user has the inline menu set to show on button click",
);
});
it("sends the open menu message to the focused field's frameId", async () => {
sender.frameId = 10;
sendMockExtensionMessage({ command: "updateFocusedFieldData" }, sender);
await flushPromises();
describe("when the focused field has a value", () => {
beforeEach(() => {
jest
.spyOn(overlayBackground as any, "checkMostRecentlyFocusedFieldHasValue")
.mockResolvedValue(false);
});
sendMockExtensionMessage({ command: "openAutofillInlineMenu" }, sender);
await flushPromises();
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
sender.tab,
{
command: "openAutofillInlineMenu",
isFocusingFieldElement: false,
isOpeningFullInlineMenu: false,
authStatus: AuthenticationStatus.Unlocked,
},
{ frameId: 10 },
it.todo(
"updates the position of both button and list elements if the inline menu is showing an account creation view",
);
it.todo("closes the inline menu list if it is visible");
it.todo("updates the position of the inline menu button");
});
});
@ -2242,195 +2265,6 @@ describe("OverlayBackground", () => {
});
});
describe("updateAutofillInlineMenuPosition message handler", () => {
beforeEach(async () => {
await initOverlayElementPorts();
});
it("ignores updating the position if the overlay element type is not provided", () => {
sendMockExtensionMessage({ command: "updateAutofillInlineMenuPosition" });
expect(listPortSpy.postMessage).not.toHaveBeenCalledWith({
command: "updateIframePosition",
styles: expect.anything(),
});
expect(buttonPortSpy.postMessage).not.toHaveBeenCalledWith({
command: "updateIframePosition",
styles: expect.anything(),
});
});
it("skips updating the position if the most recently focused field is different than the message sender", () => {
const sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
const focusedFieldData = createFocusedFieldDataMock({ tabId: 2 });
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({ command: "updateAutofillInlineMenuPosition" }, sender);
expect(listPortSpy.postMessage).not.toHaveBeenCalledWith({
command: "updateIframePosition",
styles: expect.anything(),
});
expect(buttonPortSpy.postMessage).not.toHaveBeenCalledWith({
command: "updateIframePosition",
styles: expect.anything(),
});
});
it("updates the inline menu button's position", async () => {
const focusedFieldData = createFocusedFieldDataMock();
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button,
});
await flushPromises();
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuPosition",
styles: { height: "2px", left: "4px", top: "2px", width: "2px" },
});
});
it("modifies the inline menu button's height for medium sized input elements", async () => {
const focusedFieldData = createFocusedFieldDataMock({
focusedFieldRects: { top: 1, left: 2, height: 35, width: 4 },
});
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button,
});
await flushPromises();
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuPosition",
styles: { height: "20px", left: "-22px", top: "8px", width: "20px" },
});
});
it("modifies the inline menu button's height for large sized input elements", async () => {
const focusedFieldData = createFocusedFieldDataMock({
focusedFieldRects: { top: 1, left: 2, height: 50, width: 4 },
});
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button,
});
await flushPromises();
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuPosition",
styles: { height: "27px", left: "-32px", top: "13px", width: "27px" },
});
});
it("takes into account the right padding of the focused field in positioning the button if the right padding of the field is larger than the left padding", async () => {
const focusedFieldData = createFocusedFieldDataMock({
focusedFieldStyles: { paddingRight: "20px", paddingLeft: "6px" },
});
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.Button,
});
await flushPromises();
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuPosition",
styles: { height: "2px", left: "-18px", top: "2px", width: "2px" },
});
});
it("updates the inline menu list's position", async () => {
const focusedFieldData = createFocusedFieldDataMock();
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.List,
});
await flushPromises();
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "updateAutofillInlineMenuPosition",
styles: { left: "2px", top: "4px", width: "4px" },
});
});
it("sends a message that triggers a simultaneous fade in for both inline menu elements", async () => {
jest.useFakeTimers();
const focusedFieldData = createFocusedFieldDataMock();
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
sendMockExtensionMessage({
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.List,
});
await flushPromises();
jest.advanceTimersByTime(150);
expect(buttonPortSpy.postMessage).toHaveBeenCalledWith({
command: "fadeInAutofillInlineMenuIframe",
});
expect(listPortSpy.postMessage).toHaveBeenCalledWith({
command: "fadeInAutofillInlineMenuIframe",
});
});
describe("getAutofillInlineMenuPosition", () => {
it("returns the current inline menu position", async () => {
overlayBackground["inlineMenuPosition"] = {
button: { left: 1, top: 2, width: 3, height: 4 },
};
sendMockExtensionMessage(
{ command: "getAutofillInlineMenuPosition" },
mock<chrome.runtime.MessageSender>(),
sendResponse,
);
await flushPromises();
expect(sendResponse).toHaveBeenCalledWith({
button: { left: 1, top: 2, width: 3, height: 4 },
});
});
});
it("triggers a debounced reposition of the inline menu if the sender frame has a `null` sub frame offsets value", async () => {
jest.useFakeTimers();
const focusedFieldData = createFocusedFieldDataMock();
const sender = mock<chrome.runtime.MessageSender>({
tab: { id: focusedFieldData.tabId },
frameId: focusedFieldData.frameId,
});
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData }, sender);
overlayBackground["subFrameOffsetsForTab"][focusedFieldData.tabId] = new Map([
[focusedFieldData.frameId, null],
]);
jest.spyOn(overlayBackground as any, "updateInlineMenuPositionAfterRepositionEvent");
sendMockExtensionMessage(
{
command: "updateAutofillInlineMenuPosition",
overlayElement: AutofillOverlayElement.List,
},
sender,
);
await flushPromises();
jest.advanceTimersByTime(150);
expect(
overlayBackground["updateInlineMenuPositionAfterRepositionEvent"],
).toHaveBeenCalled();
});
});
describe("updateAutofillInlineMenuElementIsVisibleStatus message handler", () => {
let sender: chrome.runtime.MessageSender;
let focusedFieldData: FocusedFieldData;
@ -2556,10 +2390,8 @@ describe("OverlayBackground", () => {
});
describe("unlockCompleted", () => {
let updateInlineMenuCiphersSpy: jest.SpyInstance;
beforeEach(async () => {
updateInlineMenuCiphersSpy = jest.spyOn(overlayBackground, "updateOverlayCiphers");
jest.spyOn(overlayBackground, "updateOverlayCiphers");
await initOverlayElementPorts();
});
@ -2581,8 +2413,9 @@ describe("OverlayBackground", () => {
expect(updateInlineMenuCiphersSpy).toHaveBeenCalled();
});
it("opens the inline menu if a retry command is present in the message", async () => {
updateInlineMenuCiphersSpy.mockImplementation();
it("focuses the most recently focused field if a retry command is present in the message", async () => {
activeAccountStatusMock$.next(AuthenticationStatus.Unlocked);
cipherService.getAllDecryptedForUrl.mockResolvedValue([]);
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(createChromeTabMock({ id: 1 }));
sendMockExtensionMessage({
command: "unlockCompleted",
@ -2592,16 +2425,9 @@ describe("OverlayBackground", () => {
});
await flushPromises();
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
expect.any(Object),
{
command: "openAutofillInlineMenu",
isFocusingFieldElement: true,
isOpeningFullInlineMenu: false,
authStatus: AuthenticationStatus.Unlocked,
},
{ frameId: 0 },
);
expect(tabsSendMessageSpy).toHaveBeenCalledWith(expect.any(Object), {
command: "focusMostRecentlyFocusedField",
});
});
});
@ -2670,12 +2496,13 @@ describe("OverlayBackground", () => {
const portKey = "inlineMenuButtonPort";
beforeEach(async () => {
sender = mock<chrome.runtime.MessageSender>({ tab: { id: 1 } });
sender = mock<chrome.runtime.MessageSender>({ tab: createChromeTabMock({ id: 1 }) });
portKeyForTabSpy[sender.tab.id] = portKey;
activeAccountStatusMock$.next(AuthenticationStatus.Unlocked);
await initOverlayElementPorts();
buttonMessageConnectorSpy.sender = sender;
openUnlockPopoutSpy.mockImplementation();
cipherService.getAllDecryptedForUrl.mockResolvedValue([]);
});
describe("autofillInlineMenuButtonClicked message handler", () => {
@ -2706,6 +2533,16 @@ describe("OverlayBackground", () => {
it("opens the inline menu if the user auth status is unlocked", async () => {
getTabFromCurrentWindowIdSpy.mockResolvedValueOnce(sender.tab);
sendMockExtensionMessage(
{
command: "updateFocusedFieldData",
focusedFieldData: mock<FocusedFieldData>(),
},
mock<chrome.runtime.MessageSender>({ tab: buttonMessageConnectorSpy.sender.tab }),
);
jest
.spyOn(overlayBackground as any, "getInlineMenuButtonPosition")
.mockReturnValueOnce({ x: 0, y: 0 });
sendPortMessage(buttonMessageConnectorSpy, {
command: "autofillInlineMenuButtonClicked",
portKey,
@ -2715,10 +2552,8 @@ describe("OverlayBackground", () => {
expect(tabsSendMessageSpy).toHaveBeenCalledWith(
sender.tab,
{
command: "openAutofillInlineMenu",
isFocusingFieldElement: false,
isOpeningFullInlineMenu: true,
authStatus: AuthenticationStatus.Unlocked,
command: "appendAutofillInlineMenuToDom",
overlayElement: AutofillOverlayElement.List,
},
{ frameId: 0 },
);
@ -3105,10 +2940,17 @@ describe("OverlayBackground", () => {
sendMockExtensionMessage({ command: "updateFocusedFieldData", focusedFieldData });
await flushPromises();
sendPortMessage(listMessageConnectorSpy, { command: "addNewVaultItem", portKey });
sendPortMessage(listMessageConnectorSpy, {
command: "addNewVaultItem",
portKey,
addNewCipherType: CipherType.Login,
});
await flushPromises();
expect(tabsSendMessageSpy).not.toHaveBeenCalled();
expect(tabsSendMessageSpy).not.toHaveBeenCalledWith(sender.tab, {
command: "addNewVaultItemFromOverlay",
addNewCipherType: CipherType.Login,
});
});
it("sends a message to the tab to add a new vault item", async () => {