mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1833193 - Allow CFRs to use alt_anchor_id in more situations where anchor_id is not available. r=omc-reviewers,hanna_a
Differential Revision: https://phabricator.services.mozilla.com/D178099
This commit is contained in:
parent
7c063cf058
commit
9cfcbebf18
@ -803,29 +803,48 @@ class PageAction {
|
||||
}
|
||||
}
|
||||
|
||||
_getVisibleElement(id) {
|
||||
const element = id && this.window.document.getElementById(id);
|
||||
if (!element) {
|
||||
return null; // element doesn't exist at all
|
||||
}
|
||||
const { visibility, display } = this.window.getComputedStyle(element);
|
||||
if (
|
||||
!this.window.isElementVisible(element) ||
|
||||
visibility !== "visible" ||
|
||||
display === "none"
|
||||
) {
|
||||
// CSS rules like visibility: hidden or display: none. these result in
|
||||
// element being invisible and unclickable.
|
||||
return null;
|
||||
}
|
||||
let widget = lazy.CustomizableUI.getWidget(id);
|
||||
if (widget && (!widget.areaType || widget.areaType.includes("panel"))) {
|
||||
// the element is a customizable widget (a toolbar item, e.g. the reload
|
||||
// button or the downloads button). widgets can be in various areas, like
|
||||
// the overflow panel (the chevron button that appears when your window is
|
||||
// so small the toolbar overflows. they can also be in the customization
|
||||
// palette, which is an element in the browser chrome, but it looks like a
|
||||
// tab/page. it appears when you right click the toolbar and click Customize
|
||||
// Toolbar. widgets in the palette are always present in the chrome's DOM.
|
||||
// but they're totally invisible except in customize mode. so if a widget is
|
||||
// in the palette, its areaType will be undefined.
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
async showPopup() {
|
||||
const browser = this.window.gBrowser.selectedBrowser;
|
||||
const message = RecommendationMap.get(browser);
|
||||
const { content } = message;
|
||||
let anchor;
|
||||
|
||||
// A hacky way of setting the popup anchor outside the usual url bar icon box
|
||||
// See https://searchfox.org/mozilla-central/rev/847b64cc28b74b44c379f9bff4f415b97da1c6d7/toolkit/modules/PopupNotifications.jsm#42
|
||||
//If the anchor has been moved to the overflow menu ('menu-panel') and an alt_anchor_id has been provided, we want to use the alt_anchor_id
|
||||
|
||||
if (
|
||||
content.alt_anchor_id &&
|
||||
lazy.CustomizableUI.getWidget(content.anchor_id).areaType.includes(
|
||||
"panel"
|
||||
)
|
||||
) {
|
||||
anchor = this.window.document.getElementById(content.alt_anchor_id);
|
||||
} else {
|
||||
anchor =
|
||||
this.window.document.getElementById(content.anchor_id) ||
|
||||
this.container;
|
||||
}
|
||||
browser.cfrpopupnotificationanchor = anchor;
|
||||
// See https://searchfox.org/mozilla-central/rev/eb07633057d66ab25f9db4c5900eeb6913da7579/toolkit/modules/PopupNotifications.sys.mjs#44
|
||||
browser.cfrpopupnotificationanchor =
|
||||
this._getVisibleElement(content.anchor_id) ||
|
||||
this._getVisibleElement(content.alt_anchor_id) ||
|
||||
this.container;
|
||||
|
||||
await this._renderPopup(message, browser);
|
||||
}
|
||||
@ -836,7 +855,7 @@ class PageAction {
|
||||
const { content } = message;
|
||||
|
||||
// A hacky way of setting the popup anchor outside the usual url bar icon box
|
||||
// See https://searchfox.org/mozilla-central/rev/c5c002f81f08a73e04868e0c2bf0eb113f200b03/toolkit/modules/PopupNotifications.sys.mjs#40
|
||||
// See https://searchfox.org/mozilla-central/rev/eb07633057d66ab25f9db4c5900eeb6913da7579/toolkit/modules/PopupNotifications.sys.mjs#44
|
||||
browser.cfrpopupnotificationanchor =
|
||||
this.window.document.getElementById(content.anchor_id) || this.container;
|
||||
|
||||
|
@ -934,54 +934,125 @@ describe("CFRPageActions", () => {
|
||||
let savedRec;
|
||||
let pageAction;
|
||||
let fakeAnchorId = "fake_anchor_id";
|
||||
let sandboxShowPopup = sinon.createSandbox();
|
||||
let fakePopUp = {
|
||||
id: "fake_id",
|
||||
template: "cfr_doorhanger",
|
||||
content: {
|
||||
skip_address_bar_notifier: true,
|
||||
heading_text: "Fake Heading Text",
|
||||
anchor_id: "fake_anchor_id",
|
||||
},
|
||||
};
|
||||
let fakeAltAnchorId = "fake_alt_anchor_id";
|
||||
let TEST_MESSAGE;
|
||||
let getElmStub;
|
||||
let getStyleStub;
|
||||
let isElmVisibleStub;
|
||||
let getWidgetStub;
|
||||
beforeEach(() => {
|
||||
const { id, content } = fakePopUp;
|
||||
TEST_MESSAGE = {
|
||||
id: "fake_id",
|
||||
template: "cfr_doorhanger",
|
||||
content: {
|
||||
skip_address_bar_notifier: true,
|
||||
heading_text: "Fake Heading Text",
|
||||
anchor_id: fakeAnchorId,
|
||||
},
|
||||
};
|
||||
getElmStub = sandbox
|
||||
.stub(window.document, "getElementById")
|
||||
.callsFake(id => ({ id }));
|
||||
getStyleStub = sandbox
|
||||
.stub(window, "getComputedStyle")
|
||||
.returns({ display: "block", visibility: "visible" });
|
||||
isElmVisibleStub = sandbox.stub().returns(true);
|
||||
getWidgetStub = sandbox.stub();
|
||||
globals.set({
|
||||
CustomizableUI: { getWidget: getWidgetStub },
|
||||
isElementVisible: isElmVisibleStub,
|
||||
});
|
||||
|
||||
savedRec = {
|
||||
id,
|
||||
id: TEST_MESSAGE.id,
|
||||
host: fakeHost,
|
||||
content,
|
||||
content: TEST_MESSAGE.content,
|
||||
};
|
||||
CFRPageActions.RecommendationMap.set(fakeBrowser, savedRec);
|
||||
pageAction = new PageAction(window, dispatchStub);
|
||||
|
||||
sandboxShowPopup.stub(window.document, "getElementById");
|
||||
sandboxShowPopup.stub(pageAction, "_renderPopup");
|
||||
globals.set({
|
||||
CustomizableUI: {
|
||||
getWidget: sandboxShowPopup
|
||||
.stub()
|
||||
.withArgs(fakeAnchorId)
|
||||
.returns({ areaType: "menu-panel" }),
|
||||
},
|
||||
});
|
||||
sandbox.stub(pageAction, "_renderPopup");
|
||||
});
|
||||
afterEach(() => {
|
||||
sandboxShowPopup.restore();
|
||||
sandbox.restore();
|
||||
globals.restore();
|
||||
});
|
||||
|
||||
it("Should use default anchor_id if an alternate hasn't been provided", async () => {
|
||||
it("should use anchor_id if element exists and is not a customizable widget", async () => {
|
||||
await pageAction.showPopup();
|
||||
|
||||
assert.calledWith(window.document.getElementById, fakeAnchorId);
|
||||
assert.equal(fakeBrowser.cfrpopupnotificationanchor.id, fakeAnchorId);
|
||||
});
|
||||
|
||||
it("Should use alt_anchor_if if one has been provided AND the anchor_id has been removed", async () => {
|
||||
let fakeAltAnchorId = "fake_alt_anchor_id";
|
||||
|
||||
fakePopUp.content.alt_anchor_id = fakeAltAnchorId;
|
||||
it("should use anchor_id if element exists and is in the toolbar", async () => {
|
||||
getWidgetStub.withArgs(fakeAnchorId).returns({ areaType: "toolbar" });
|
||||
await pageAction.showPopup();
|
||||
assert.calledWith(window.document.getElementById, fakeAltAnchorId);
|
||||
assert.equal(fakeBrowser.cfrpopupnotificationanchor.id, fakeAnchorId);
|
||||
});
|
||||
|
||||
it("should use default container if element exists but is in the widget overflow panel", async () => {
|
||||
getWidgetStub
|
||||
.withArgs(fakeAnchorId)
|
||||
.returns({ areaType: "menu-panel" });
|
||||
await pageAction.showPopup();
|
||||
assert.equal(
|
||||
fakeBrowser.cfrpopupnotificationanchor.id,
|
||||
pageAction.container.id
|
||||
);
|
||||
});
|
||||
|
||||
it("should use default container if element exists but is in the customization palette", async () => {
|
||||
getWidgetStub.withArgs(fakeAnchorId).returns({ areaType: null });
|
||||
await pageAction.showPopup();
|
||||
assert.equal(
|
||||
fakeBrowser.cfrpopupnotificationanchor.id,
|
||||
pageAction.container.id
|
||||
);
|
||||
});
|
||||
|
||||
it("should use alt_anchor_id if one has been provided and the anchor_id element cannot be found", async () => {
|
||||
TEST_MESSAGE.content.alt_anchor_id = fakeAltAnchorId;
|
||||
getElmStub.withArgs(fakeAnchorId).returns(null);
|
||||
await pageAction.showPopup();
|
||||
assert.equal(
|
||||
fakeBrowser.cfrpopupnotificationanchor.id,
|
||||
fakeAltAnchorId
|
||||
);
|
||||
});
|
||||
|
||||
it("should use alt_anchor_id if one has been provided and the anchor_id element is hidden by CSS", async () => {
|
||||
TEST_MESSAGE.content.alt_anchor_id = fakeAltAnchorId;
|
||||
getStyleStub
|
||||
.withArgs(sandbox.match({ id: fakeAnchorId }))
|
||||
.returns({ display: "none", visibility: "visible" });
|
||||
await pageAction.showPopup();
|
||||
assert.equal(
|
||||
fakeBrowser.cfrpopupnotificationanchor.id,
|
||||
fakeAltAnchorId
|
||||
);
|
||||
});
|
||||
|
||||
it("should use alt_anchor_id if one has been provided and the anchor_id element has no height/width", async () => {
|
||||
TEST_MESSAGE.content.alt_anchor_id = fakeAltAnchorId;
|
||||
isElmVisibleStub
|
||||
.withArgs(sandbox.match({ id: fakeAnchorId }))
|
||||
.returns(false);
|
||||
await pageAction.showPopup();
|
||||
assert.equal(
|
||||
fakeBrowser.cfrpopupnotificationanchor.id,
|
||||
fakeAltAnchorId
|
||||
);
|
||||
});
|
||||
|
||||
it("should use default container if the anchor_id and alt_anchor_id are both not visible", async () => {
|
||||
TEST_MESSAGE.content.alt_anchor_id = fakeAltAnchorId;
|
||||
getStyleStub
|
||||
.withArgs(sandbox.match({ id: fakeAnchorId }))
|
||||
.returns({ display: "none", visibility: "visible" });
|
||||
getWidgetStub.withArgs(fakeAltAnchorId).returns({ areaType: null });
|
||||
await pageAction.showPopup();
|
||||
assert.equal(
|
||||
fakeBrowser.cfrpopupnotificationanchor.id,
|
||||
pageAction.container.id
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user