mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-13 00:51:45 +01:00
[PM-5189] Working through jest tests for OverlayBackground
This commit is contained in:
parent
b9d257046c
commit
07713511e4
@ -35,6 +35,7 @@ import { createChromeTabMock, createAutofillPageDetailsMock } from "../spec/auto
|
|||||||
import { flushPromises, sendMockExtensionMessage } from "../spec/testing-utils";
|
import { flushPromises, sendMockExtensionMessage } from "../spec/testing-utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
FocusedFieldData,
|
||||||
PageDetailsForTab,
|
PageDetailsForTab,
|
||||||
SubFrameOffsetData,
|
SubFrameOffsetData,
|
||||||
SubFrameOffsetsForTab,
|
SubFrameOffsetsForTab,
|
||||||
@ -66,6 +67,7 @@ describe("OverlayBackground", () => {
|
|||||||
let subFrameOffsetsSpy: SubFrameOffsetsForTab;
|
let subFrameOffsetsSpy: SubFrameOffsetsForTab;
|
||||||
let getFrameDetailsSpy: jest.SpyInstance;
|
let getFrameDetailsSpy: jest.SpyInstance;
|
||||||
let tabsSendMessageSpy: jest.SpyInstance;
|
let tabsSendMessageSpy: jest.SpyInstance;
|
||||||
|
let getFrameCounter: number = 2;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
accountService = mockAccountServiceWith(mockUserId);
|
accountService = mockAccountServiceWith(mockUserId);
|
||||||
@ -112,13 +114,21 @@ describe("OverlayBackground", () => {
|
|||||||
pageDetailsForTabSpy = overlayBackground["pageDetailsForTab"];
|
pageDetailsForTabSpy = overlayBackground["pageDetailsForTab"];
|
||||||
subFrameOffsetsSpy = overlayBackground["subFrameOffsetsForTab"];
|
subFrameOffsetsSpy = overlayBackground["subFrameOffsetsForTab"];
|
||||||
getFrameDetailsSpy = jest.spyOn(BrowserApi, "getFrameDetails");
|
getFrameDetailsSpy = jest.spyOn(BrowserApi, "getFrameDetails");
|
||||||
|
getFrameDetailsSpy.mockImplementation((_details: chrome.webNavigation.GetFrameDetails) => {
|
||||||
|
getFrameCounter--;
|
||||||
|
return mock<chrome.webNavigation.GetFrameResultDetails>({
|
||||||
|
parentFrameId: getFrameCounter,
|
||||||
|
});
|
||||||
|
});
|
||||||
tabsSendMessageSpy = jest.spyOn(BrowserApi, "tabSendMessage");
|
tabsSendMessageSpy = jest.spyOn(BrowserApi, "tabSendMessage");
|
||||||
|
|
||||||
void overlayBackground.init();
|
void overlayBackground.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
getFrameCounter = 2;
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
jest.useRealTimers();
|
||||||
mockReset(cipherService);
|
mockReset(cipherService);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -141,23 +151,17 @@ describe("OverlayBackground", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("building sub frame offsets", () => {
|
describe("building sub frame offsets", () => {
|
||||||
let getFrameCounter: number = 2;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
getFrameDetailsSpy.mockImplementation((_details: chrome.webNavigation.GetFrameDetails) => {
|
tabsSendMessageSpy.mockResolvedValue(
|
||||||
getFrameCounter--;
|
mock<SubFrameOffsetData>({
|
||||||
return mock<chrome.webNavigation.GetFrameResultDetails>({
|
left: getFrameCounter,
|
||||||
parentFrameId: getFrameCounter,
|
top: getFrameCounter,
|
||||||
});
|
url: "url",
|
||||||
});
|
}),
|
||||||
tabsSendMessageSpy.mockResolvedValue(mock<SubFrameOffsetData>());
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
it("builds the offset values for a sub frame within the tab", async () => {
|
||||||
getFrameCounter = 2;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("builds the offset values for a sub frame within the tab", () => {
|
|
||||||
sendMockExtensionMessage(
|
sendMockExtensionMessage(
|
||||||
{ command: "collectPageDetailsResponse", details: createAutofillPageDetailsMock() },
|
{ command: "collectPageDetailsResponse", details: createAutofillPageDetailsMock() },
|
||||||
mock<chrome.runtime.MessageSender>({
|
mock<chrome.runtime.MessageSender>({
|
||||||
@ -165,8 +169,11 @@ describe("OverlayBackground", () => {
|
|||||||
frameId: 1,
|
frameId: 1,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
expect(subFrameOffsetsSpy[tabId]).toBeDefined();
|
expect(subFrameOffsetsSpy[tabId]).toStrictEqual(
|
||||||
|
new Map([[1, { left: 4, top: 4, url: "url" }]]),
|
||||||
|
);
|
||||||
expect(pageDetailsForTabSpy[tabId].size).toBe(2);
|
expect(pageDetailsForTabSpy[tabId].size).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -202,10 +209,7 @@ describe("OverlayBackground", () => {
|
|||||||
tabsSendMessageSpy.mockResolvedValueOnce(null);
|
tabsSendMessageSpy.mockResolvedValueOnce(null);
|
||||||
sendMockExtensionMessage(
|
sendMockExtensionMessage(
|
||||||
{ command: "collectPageDetailsResponse", details: createAutofillPageDetailsMock() },
|
{ command: "collectPageDetailsResponse", details: createAutofillPageDetailsMock() },
|
||||||
mock<chrome.runtime.MessageSender>({
|
mock<chrome.runtime.MessageSender>({ tab, frameId }),
|
||||||
tab,
|
|
||||||
frameId,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
@ -219,6 +223,22 @@ describe("OverlayBackground", () => {
|
|||||||
);
|
);
|
||||||
expect(subFrameOffsetsSpy[tabId]).toStrictEqual(new Map([[frameId, null]]));
|
expect(subFrameOffsetsSpy[tabId]).toStrictEqual(new Map([[frameId, null]]));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("updates sub frame data that has been calculated using window messages", async () => {
|
||||||
|
const tab = createChromeTabMock({ id: tabId });
|
||||||
|
const frameId = 1;
|
||||||
|
const subFrameData = mock<SubFrameOffsetData>({ frameId, left: 10, top: 10, url: "url" });
|
||||||
|
tabsSendMessageSpy.mockResolvedValueOnce(null);
|
||||||
|
subFrameOffsetsSpy[tabId] = new Map([[frameId, null]]);
|
||||||
|
|
||||||
|
sendMockExtensionMessage(
|
||||||
|
{ command: "updateSubFrameData", subFrameData },
|
||||||
|
mock<chrome.runtime.MessageSender>({ tab, frameId }),
|
||||||
|
);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(subFrameOffsetsSpy[tabId]).toStrictEqual(new Map([[frameId, subFrameData]]));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -237,4 +257,81 @@ describe("OverlayBackground", () => {
|
|||||||
expect(portKeyForTabSpy[tabId]).toBeUndefined();
|
expect(portKeyForTabSpy[tabId]).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("re-positioning the inline menu within sub frames", () => {
|
||||||
|
describe("rebuildSubFrameOffsets", () => {
|
||||||
|
const tabId = 1;
|
||||||
|
const topFrameId = 0;
|
||||||
|
const middleFrameId = 10;
|
||||||
|
const bottomFrameId = 20;
|
||||||
|
let tab: chrome.tabs.Tab;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
tab = createChromeTabMock({ id: tabId });
|
||||||
|
overlayBackground["focusedFieldData"] = mock<FocusedFieldData>({
|
||||||
|
tabId,
|
||||||
|
frameId: bottomFrameId,
|
||||||
|
});
|
||||||
|
subFrameOffsetsSpy[tabId] = new Map([
|
||||||
|
[topFrameId, { left: 1, top: 1, url: "https://top-frame.com" }],
|
||||||
|
[middleFrameId, { left: 2, top: 2, url: "https://middle-frame.com" }],
|
||||||
|
[bottomFrameId, { left: 3, top: 3, url: "https://bottom-frame.com" }],
|
||||||
|
]);
|
||||||
|
tabsSendMessageSpy.mockResolvedValue(
|
||||||
|
mock<SubFrameOffsetData>({
|
||||||
|
left: getFrameCounter,
|
||||||
|
top: getFrameCounter,
|
||||||
|
url: "url",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("skips rebuilding sub frame offsets if the sender contains the currently focused field", () => {
|
||||||
|
const sender = mock<chrome.runtime.MessageSender>({ tab, frameId: bottomFrameId });
|
||||||
|
|
||||||
|
sendMockExtensionMessage({ command: "rebuildSubFrameOffsets" }, sender);
|
||||||
|
|
||||||
|
expect(getFrameDetailsSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("skips rebuilding sub frame offsets if the tab does not contain sub frames", () => {
|
||||||
|
const sender = mock<chrome.runtime.MessageSender>({
|
||||||
|
tab: createChromeTabMock({ id: 15 }),
|
||||||
|
frameId: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
sendMockExtensionMessage({ command: "rebuildSubFrameOffsets" }, sender);
|
||||||
|
|
||||||
|
expect(getFrameDetailsSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rebuilds the sub frame offsets for a given tab", async () => {
|
||||||
|
const sender = mock<chrome.runtime.MessageSender>({ tab, frameId: middleFrameId });
|
||||||
|
|
||||||
|
sendMockExtensionMessage({ command: "rebuildSubFrameOffsets" }, sender);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(getFrameDetailsSpy).toHaveBeenCalledWith({ tabId, frameId: topFrameId });
|
||||||
|
expect(getFrameDetailsSpy).toHaveBeenCalledWith({ tabId, frameId: bottomFrameId });
|
||||||
|
expect(getFrameDetailsSpy).not.toHaveBeenCalledWith({ tabId, frameId: middleFrameId });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("triggers an update of the inline menu position after rebuilding sub frames", async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
overlayBackground["updateInlineMenuPositionTimeout"] = 1;
|
||||||
|
const sender = mock<chrome.runtime.MessageSender>({ tab, frameId: middleFrameId });
|
||||||
|
jest.spyOn(overlayBackground as any, "updateInlineMenuPositionAfterSubFrameRebuild");
|
||||||
|
|
||||||
|
sendMockExtensionMessage({ command: "rebuildSubFrameOffsets" }, sender);
|
||||||
|
await flushPromises();
|
||||||
|
jest.advanceTimersByTime(650);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
overlayBackground["updateInlineMenuPositionAfterSubFrameRebuild"],
|
||||||
|
).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("updateInlineMenuPositionAfterSubFrameRebuild", () => {});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -276,6 +276,14 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the offset data for a sub frame of a tab. The offset data is used
|
||||||
|
* to calculate the position of the inline menu list and button.
|
||||||
|
*
|
||||||
|
* @param tab - The tab that the sub frame is associated with
|
||||||
|
* @param frameId - The frame ID of the sub frame
|
||||||
|
* @param url - The URL of the sub frame
|
||||||
|
*/
|
||||||
private async buildSubFrameOffsets(tab: chrome.tabs.Tab, frameId: number, url: string) {
|
private async buildSubFrameOffsets(tab: chrome.tabs.Tab, frameId: number, url: string) {
|
||||||
const tabId = tab.id;
|
const tabId = tab.id;
|
||||||
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
|
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
|
||||||
@ -291,7 +299,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
const subFrameData = { url, top: 0, left: 0 };
|
const subFrameData = { url, top: 0, left: 0 };
|
||||||
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
|
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
|
||||||
|
|
||||||
while (frameDetails && frameDetails.parentFrameId !== -1) {
|
while (frameDetails && frameDetails.parentFrameId > -1) {
|
||||||
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
||||||
tab,
|
tab,
|
||||||
{
|
{
|
||||||
@ -324,6 +332,15 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
subFrameOffsetsForTab.set(frameId, subFrameData);
|
subFrameOffsetsForTab.set(frameId, subFrameData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rebuilding the sub frame offsets when the tab is repositioned or scrolled.
|
||||||
|
* Will trigger a re-positioning of the inline menu list and button. Note that we
|
||||||
|
* do not trigger an update to sub frame data if the sender is the frame that has
|
||||||
|
* the field currently focused. We trigger a re-calculation of the field's position
|
||||||
|
* and as a result, the sub frame offsets of that frame will be updated.
|
||||||
|
*
|
||||||
|
* @param sender - The sender of the message
|
||||||
|
*/
|
||||||
private async rebuildSubFrameOffsets(sender: chrome.runtime.MessageSender) {
|
private async rebuildSubFrameOffsets(sender: chrome.runtime.MessageSender) {
|
||||||
if (sender.frameId === this.focusedFieldData?.frameId) {
|
if (sender.frameId === this.focusedFieldData?.frameId) {
|
||||||
return;
|
return;
|
||||||
@ -338,8 +355,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||||||
clearTimeout(this.updateInlineMenuPositionTimeout);
|
clearTimeout(this.updateInlineMenuPositionTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
const frameTabs = Array.from(subFrameOffsetsForTab.keys());
|
const tabFrameIds = Array.from(subFrameOffsetsForTab.keys());
|
||||||
for (const frameId of frameTabs) {
|
for (const frameId of tabFrameIds) {
|
||||||
if (frameId === sender.frameId) {
|
if (frameId === sender.frameId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user