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 {
|
||||
FocusedFieldData,
|
||||
PageDetailsForTab,
|
||||
SubFrameOffsetData,
|
||||
SubFrameOffsetsForTab,
|
||||
@ -66,6 +67,7 @@ describe("OverlayBackground", () => {
|
||||
let subFrameOffsetsSpy: SubFrameOffsetsForTab;
|
||||
let getFrameDetailsSpy: jest.SpyInstance;
|
||||
let tabsSendMessageSpy: jest.SpyInstance;
|
||||
let getFrameCounter: number = 2;
|
||||
|
||||
beforeEach(() => {
|
||||
accountService = mockAccountServiceWith(mockUserId);
|
||||
@ -112,13 +114,21 @@ describe("OverlayBackground", () => {
|
||||
pageDetailsForTabSpy = overlayBackground["pageDetailsForTab"];
|
||||
subFrameOffsetsSpy = overlayBackground["subFrameOffsetsForTab"];
|
||||
getFrameDetailsSpy = jest.spyOn(BrowserApi, "getFrameDetails");
|
||||
getFrameDetailsSpy.mockImplementation((_details: chrome.webNavigation.GetFrameDetails) => {
|
||||
getFrameCounter--;
|
||||
return mock<chrome.webNavigation.GetFrameResultDetails>({
|
||||
parentFrameId: getFrameCounter,
|
||||
});
|
||||
});
|
||||
tabsSendMessageSpy = jest.spyOn(BrowserApi, "tabSendMessage");
|
||||
|
||||
void overlayBackground.init();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
getFrameCounter = 2;
|
||||
jest.clearAllMocks();
|
||||
jest.useRealTimers();
|
||||
mockReset(cipherService);
|
||||
});
|
||||
|
||||
@ -141,23 +151,17 @@ describe("OverlayBackground", () => {
|
||||
});
|
||||
|
||||
describe("building sub frame offsets", () => {
|
||||
let getFrameCounter: number = 2;
|
||||
|
||||
beforeEach(() => {
|
||||
getFrameDetailsSpy.mockImplementation((_details: chrome.webNavigation.GetFrameDetails) => {
|
||||
getFrameCounter--;
|
||||
return mock<chrome.webNavigation.GetFrameResultDetails>({
|
||||
parentFrameId: getFrameCounter,
|
||||
});
|
||||
});
|
||||
tabsSendMessageSpy.mockResolvedValue(mock<SubFrameOffsetData>());
|
||||
tabsSendMessageSpy.mockResolvedValue(
|
||||
mock<SubFrameOffsetData>({
|
||||
left: getFrameCounter,
|
||||
top: getFrameCounter,
|
||||
url: "url",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
getFrameCounter = 2;
|
||||
});
|
||||
|
||||
it("builds the offset values for a sub frame within the tab", () => {
|
||||
it("builds the offset values for a sub frame within the tab", async () => {
|
||||
sendMockExtensionMessage(
|
||||
{ command: "collectPageDetailsResponse", details: createAutofillPageDetailsMock() },
|
||||
mock<chrome.runtime.MessageSender>({
|
||||
@ -165,8 +169,11 @@ describe("OverlayBackground", () => {
|
||||
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);
|
||||
});
|
||||
|
||||
@ -202,10 +209,7 @@ describe("OverlayBackground", () => {
|
||||
tabsSendMessageSpy.mockResolvedValueOnce(null);
|
||||
sendMockExtensionMessage(
|
||||
{ command: "collectPageDetailsResponse", details: createAutofillPageDetailsMock() },
|
||||
mock<chrome.runtime.MessageSender>({
|
||||
tab,
|
||||
frameId,
|
||||
}),
|
||||
mock<chrome.runtime.MessageSender>({ tab, frameId }),
|
||||
);
|
||||
await flushPromises();
|
||||
|
||||
@ -219,6 +223,22 @@ describe("OverlayBackground", () => {
|
||||
);
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
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) {
|
||||
const tabId = tab.id;
|
||||
let subFrameOffsetsForTab = this.subFrameOffsetsForTab[tabId];
|
||||
@ -291,7 +299,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
const subFrameData = { url, top: 0, left: 0 };
|
||||
let frameDetails = await BrowserApi.getFrameDetails({ tabId, frameId });
|
||||
|
||||
while (frameDetails && frameDetails.parentFrameId !== -1) {
|
||||
while (frameDetails && frameDetails.parentFrameId > -1) {
|
||||
const subFrameOffset: SubFrameOffsetData = await BrowserApi.tabSendMessage(
|
||||
tab,
|
||||
{
|
||||
@ -324,6 +332,15 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
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) {
|
||||
if (sender.frameId === this.focusedFieldData?.frameId) {
|
||||
return;
|
||||
@ -338,8 +355,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
clearTimeout(this.updateInlineMenuPositionTimeout);
|
||||
}
|
||||
|
||||
const frameTabs = Array.from(subFrameOffsetsForTab.keys());
|
||||
for (const frameId of frameTabs) {
|
||||
const tabFrameIds = Array.from(subFrameOffsetsForTab.keys());
|
||||
for (const frameId of tabFrameIds) {
|
||||
if (frameId === sender.frameId) {
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user