summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/test/unit/lib/BookmarkPanelHub.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/newtab/test/unit/lib/BookmarkPanelHub.test.js')
-rw-r--r--browser/components/newtab/test/unit/lib/BookmarkPanelHub.test.js514
1 files changed, 514 insertions, 0 deletions
diff --git a/browser/components/newtab/test/unit/lib/BookmarkPanelHub.test.js b/browser/components/newtab/test/unit/lib/BookmarkPanelHub.test.js
new file mode 100644
index 0000000000..dfcfecb2be
--- /dev/null
+++ b/browser/components/newtab/test/unit/lib/BookmarkPanelHub.test.js
@@ -0,0 +1,514 @@
+import { _BookmarkPanelHub } from "lib/BookmarkPanelHub.jsm";
+import { GlobalOverrider } from "test/unit/utils";
+import { PanelTestProvider } from "lib/PanelTestProvider.jsm";
+
+describe("BookmarkPanelHub", () => {
+ let globals;
+ let sandbox;
+ let instance;
+ let fakeAddImpression;
+ let fakeHandleMessageRequest;
+ let fakeL10n;
+ let fakeMessage;
+ let fakeMessageFluent;
+ let fakeTarget;
+ let fakeContainer;
+ let fakeSendTelemetry;
+ let fakeWindow;
+ let isBrowserPrivateStub;
+ beforeEach(async () => {
+ sandbox = sinon.createSandbox();
+ globals = new GlobalOverrider();
+
+ fakeL10n = {
+ setAttributes: sandbox.stub(),
+ translateElements: sandbox.stub().resolves(),
+ };
+ globals.set("DOMLocalization", function() {
+ return fakeL10n;
+ }); // eslint-disable-line prefer-arrow-callback
+ globals.set("FxAccounts", {
+ config: { promiseConnectAccountURI: sandbox.stub() },
+ });
+ isBrowserPrivateStub = sandbox.stub().returns(false);
+ globals.set("PrivateBrowsingUtils", {
+ isBrowserPrivate: isBrowserPrivateStub,
+ });
+
+ instance = new _BookmarkPanelHub();
+ fakeAddImpression = sandbox.stub();
+ fakeHandleMessageRequest = sandbox.stub();
+ [
+ { content: fakeMessageFluent },
+ { content: fakeMessage },
+ ] = await PanelTestProvider.getMessages();
+ fakeContainer = {
+ addEventListener: sandbox.stub(),
+ setAttribute: sandbox.stub(),
+ removeAttribute: sandbox.stub(),
+ classList: { add: sandbox.stub() },
+ appendChild: sandbox.stub(),
+ querySelector: sandbox.stub(),
+ children: [],
+ style: {},
+ getBoundingClientRect: sandbox.stub(),
+ };
+ const document = {
+ createElementNS: sandbox.stub().returns(fakeContainer),
+ getElementById: sandbox.stub().returns(fakeContainer),
+ l10n: fakeL10n,
+ };
+ fakeWindow = {
+ ownerGlobal: {
+ openLinkIn: sandbox.stub(),
+ gBrowser: { selectedBrowser: "browser" },
+ },
+ MozXULElement: { insertFTLIfNeeded: sandbox.stub() },
+ document,
+ requestAnimationFrame: x => x(),
+ };
+ fakeTarget = {
+ document,
+ container: {
+ querySelector: sandbox.stub(),
+ appendChild: sandbox.stub(),
+ setAttribute: sandbox.stub(),
+ removeAttribute: sandbox.stub(),
+ },
+ hidePopup: sandbox.stub(),
+ infoButton: {},
+ close: sandbox.stub(),
+ browser: {
+ ownerGlobal: {
+ gBrowser: { ownerDocument: document },
+ window: fakeWindow,
+ },
+ },
+ };
+ fakeSendTelemetry = sandbox.stub();
+ });
+ afterEach(() => {
+ instance.uninit();
+ sandbox.restore();
+ globals.restore();
+ });
+ it("should create an instance", () => {
+ assert.ok(instance);
+ });
+ it("should uninit", () => {
+ instance.uninit();
+
+ assert.isFalse(instance._initialized);
+ assert.isNull(instance._addImpression);
+ assert.isNull(instance._handleMessageRequest);
+ });
+ it("should instantiate handleMessageRequest and addImpression and l10n", () => {
+ instance.init(
+ fakeHandleMessageRequest,
+ fakeAddImpression,
+ fakeSendTelemetry
+ );
+
+ assert.equal(instance._addImpression, fakeAddImpression);
+ assert.equal(instance._handleMessageRequest, fakeHandleMessageRequest);
+ assert.equal(instance._sendTelemetry, fakeSendTelemetry);
+ assert.ok(instance._l10n);
+ assert.isTrue(instance._initialized);
+ });
+ it("should return early if not initialized", async () => {
+ assert.isFalse(await instance.messageRequest());
+ });
+ describe("#messageRequest", () => {
+ beforeEach(() => {
+ sandbox.stub(instance, "onResponse");
+ instance.init(
+ fakeHandleMessageRequest,
+ fakeAddImpression,
+ fakeSendTelemetry
+ );
+ });
+ afterEach(() => {
+ sandbox.restore();
+ });
+ it("should not re-request messages for the same URL", async () => {
+ instance._response = { url: "foo.com", content: true };
+ fakeTarget.url = "foo.com";
+ sandbox.stub(instance, "showMessage");
+
+ await instance.messageRequest(fakeTarget);
+
+ assert.notCalled(fakeHandleMessageRequest);
+ assert.calledOnce(instance.showMessage);
+ });
+ it("should call handleMessageRequest", async () => {
+ fakeHandleMessageRequest.resolves(fakeMessage);
+
+ await instance.messageRequest(fakeTarget, {});
+
+ assert.calledOnce(fakeHandleMessageRequest);
+ assert.calledWithExactly(fakeHandleMessageRequest, {
+ triggerId: instance._trigger.id,
+ });
+ });
+ it("should call onResponse", async () => {
+ fakeHandleMessageRequest.resolves(fakeMessage);
+
+ await instance.messageRequest(fakeTarget, {});
+
+ assert.calledOnce(instance.onResponse);
+ assert.calledWithExactly(
+ instance.onResponse,
+ fakeMessage,
+ fakeTarget,
+ {}
+ );
+ });
+ });
+ describe("#onResponse", () => {
+ beforeEach(() => {
+ instance.init(
+ fakeHandleMessageRequest,
+ fakeAddImpression,
+ fakeSendTelemetry
+ );
+ sandbox.stub(instance, "showMessage");
+ sandbox.stub(instance, "sendImpression");
+ sandbox.stub(instance, "hideMessage");
+ fakeTarget = { infoButton: { disabled: true } };
+ });
+ it("should show a message when called with a response", () => {
+ instance.onResponse({ content: "content" }, fakeTarget, fakeWindow);
+
+ assert.calledOnce(instance.showMessage);
+ assert.calledWithExactly(
+ instance.showMessage,
+ "content",
+ fakeTarget,
+ fakeWindow
+ );
+ assert.calledOnce(instance.sendImpression);
+ });
+ it("should insert the appropriate ftl files with translations", () => {
+ instance.onResponse({ content: "content" }, fakeTarget, fakeWindow);
+
+ assert.calledTwice(fakeWindow.MozXULElement.insertFTLIfNeeded);
+ assert.calledWith(
+ fakeWindow.MozXULElement.insertFTLIfNeeded,
+ "browser/newtab/asrouter.ftl"
+ );
+ assert.calledWith(
+ fakeWindow.MozXULElement.insertFTLIfNeeded,
+ "browser/branding/sync-brand.ftl"
+ );
+ });
+ it("should dispatch a user impression", () => {
+ sandbox.spy(instance, "sendUserEventTelemetry");
+
+ instance.onResponse({ content: "content" }, fakeTarget, fakeWindow);
+
+ assert.calledOnce(instance.sendUserEventTelemetry);
+ assert.calledWithExactly(
+ instance.sendUserEventTelemetry,
+ "IMPRESSION",
+ fakeWindow
+ );
+ assert.calledOnce(fakeSendTelemetry);
+
+ const [ping] = fakeSendTelemetry.firstCall.args;
+
+ assert.equal(ping.type, "DOORHANGER_TELEMETRY");
+ assert.equal(ping.data.event, "IMPRESSION");
+ });
+ it("should not dispatch a user impression if the window is private", () => {
+ isBrowserPrivateStub.returns(true);
+ sandbox.spy(instance, "sendUserEventTelemetry");
+
+ instance.onResponse({ content: "content" }, fakeTarget, fakeWindow);
+
+ assert.calledOnce(instance.sendUserEventTelemetry);
+ assert.calledWithExactly(
+ instance.sendUserEventTelemetry,
+ "IMPRESSION",
+ fakeWindow
+ );
+ assert.notCalled(fakeSendTelemetry);
+ });
+ it("should hide existing messages if no response is provided", () => {
+ instance.onResponse(null, fakeTarget);
+
+ assert.calledOnce(instance.hideMessage);
+ assert.calledWithExactly(instance.hideMessage, fakeTarget);
+ });
+ });
+ describe("#showMessage.collapsed=false", () => {
+ beforeEach(() => {
+ instance.init(
+ fakeHandleMessageRequest,
+ fakeAddImpression,
+ fakeSendTelemetry
+ );
+ sandbox.stub(instance, "toggleRecommendation");
+ sandbox.stub(instance, "_response").value({ collapsed: false });
+ });
+ it("should create a container", () => {
+ fakeTarget.container.querySelector.returns(false);
+
+ instance.showMessage(fakeMessage, fakeTarget);
+
+ assert.equal(fakeTarget.document.createElementNS.callCount, 6);
+ assert.calledOnce(fakeTarget.container.appendChild);
+ assert.notCalled(fakeL10n.setAttributes);
+ });
+ it("should create a container (fluent message)", () => {
+ fakeTarget.container.querySelector.returns(false);
+
+ instance.showMessage(fakeMessageFluent, fakeTarget);
+
+ assert.equal(fakeTarget.document.createElementNS.callCount, 6);
+ assert.calledOnce(fakeTarget.container.appendChild);
+ });
+ it("should set l10n attributes", () => {
+ fakeTarget.container.querySelector.returns(false);
+
+ instance.showMessage(fakeMessageFluent, fakeTarget);
+
+ assert.equal(fakeL10n.setAttributes.callCount, 4);
+ });
+ it("call adjust panel height when height is > 150px", async () => {
+ fakeTarget.container.querySelector.returns(false);
+ fakeContainer.getBoundingClientRect.returns({ height: 160 });
+
+ await instance._adjustPanelHeight(fakeWindow, fakeContainer);
+
+ assert.calledOnce(fakeWindow.document.l10n.translateElements);
+ assert.calledTwice(fakeContainer.getBoundingClientRect);
+ assert.calledWithExactly(
+ fakeContainer.classList.add,
+ "longMessagePadding"
+ );
+ });
+ it("should reuse the container", () => {
+ fakeTarget.container.querySelector.returns(true);
+
+ instance.showMessage(fakeMessage, fakeTarget);
+
+ assert.notCalled(fakeTarget.container.appendChild);
+ });
+ it("should open a tab with FxA signup", async () => {
+ fakeTarget.container.querySelector.returns(false);
+
+ instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
+ // Call the event listener cb
+ await fakeContainer.addEventListener.firstCall.args[1]();
+
+ assert.calledOnce(fakeWindow.ownerGlobal.openLinkIn);
+ });
+ it("should send a click event", async () => {
+ sandbox.stub(instance, "sendUserEventTelemetry");
+ fakeTarget.container.querySelector.returns(false);
+
+ instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
+ // Call the event listener cb
+ await fakeContainer.addEventListener.firstCall.args[1]();
+
+ assert.calledOnce(instance.sendUserEventTelemetry);
+ assert.calledWithExactly(
+ instance.sendUserEventTelemetry,
+ "CLICK",
+ fakeWindow
+ );
+ });
+ it("should send a click event", async () => {
+ sandbox.stub(instance, "sendUserEventTelemetry");
+ fakeTarget.container.querySelector.returns(false);
+
+ instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
+ // Call the event listener cb
+ await fakeContainer.addEventListener.firstCall.args[1]();
+
+ assert.calledOnce(instance.sendUserEventTelemetry);
+ assert.calledWithExactly(
+ instance.sendUserEventTelemetry,
+ "CLICK",
+ fakeWindow
+ );
+ });
+ it("should collapse the message", () => {
+ fakeTarget.container.querySelector.returns(false);
+ sandbox.spy(instance, "collapseMessage");
+ instance._response.collapsed = false;
+
+ instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
+ // Show message calls it once so we need to reset
+ instance.toggleRecommendation.reset();
+ // Call the event listener cb
+ fakeContainer.addEventListener.secondCall.args[1]();
+
+ assert.calledOnce(instance.collapseMessage);
+ assert.calledOnce(fakeTarget.close);
+ assert.isTrue(instance._response.collapsed);
+ assert.calledOnce(instance.toggleRecommendation);
+ });
+ it("should send a dismiss event", () => {
+ sandbox.stub(instance, "sendUserEventTelemetry");
+ sandbox.spy(instance, "collapseMessage");
+ instance._response.collapsed = false;
+
+ instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
+ // Call the event listener cb
+ fakeContainer.addEventListener.secondCall.args[1]();
+
+ assert.calledOnce(instance.sendUserEventTelemetry);
+ assert.calledWithExactly(
+ instance.sendUserEventTelemetry,
+ "DISMISS",
+ fakeWindow
+ );
+ });
+ it("should call toggleRecommendation `true`", () => {
+ instance.showMessage(fakeMessage, fakeTarget, fakeWindow);
+
+ assert.calledOnce(instance.toggleRecommendation);
+ assert.calledWithExactly(instance.toggleRecommendation, true);
+ });
+ });
+ describe("#showMessage.collapsed=true", () => {
+ beforeEach(() => {
+ sandbox
+ .stub(instance, "_response")
+ .value({ collapsed: true, target: fakeTarget });
+ sandbox.stub(instance, "toggleRecommendation");
+ });
+ it("should return early if the message is collapsed", () => {
+ instance.showMessage();
+
+ assert.calledOnce(instance.toggleRecommendation);
+ assert.calledWithExactly(instance.toggleRecommendation, false);
+ });
+ });
+ describe("#hideMessage", () => {
+ let removeStub;
+ beforeEach(() => {
+ sandbox.stub(instance, "toggleRecommendation");
+ removeStub = sandbox.stub();
+ fakeTarget = {
+ container: {
+ querySelector: sandbox.stub().returns({ remove: removeStub }),
+ },
+ };
+ instance._response = { win: fakeWindow };
+ });
+ it("should remove the message", () => {
+ instance.hideMessage(fakeTarget);
+
+ assert.calledOnce(removeStub);
+ });
+ it("should call toggleRecommendation `false`", () => {
+ instance.hideMessage(fakeTarget);
+
+ assert.calledOnce(instance.toggleRecommendation);
+ assert.calledWithExactly(instance.toggleRecommendation, false);
+ });
+ });
+ describe("#toggleRecommendation", () => {
+ let target;
+ beforeEach(() => {
+ target = {
+ infoButton: {},
+ container: {
+ setAttribute: sandbox.stub(),
+ removeAttribute: sandbox.stub(),
+ },
+ };
+ sandbox.stub(instance, "_response").value({ target });
+ });
+ it("should check infoButton", () => {
+ instance.toggleRecommendation(true);
+
+ assert.isTrue(target.infoButton.checked);
+ });
+ it("should uncheck infoButton", () => {
+ instance.toggleRecommendation(false);
+
+ assert.isFalse(target.infoButton.checked);
+ });
+ it("should uncheck infoButton", () => {
+ target.infoButton.checked = true;
+
+ instance.toggleRecommendation();
+
+ assert.isFalse(target.infoButton.checked);
+ });
+ it("should disable the container", () => {
+ target.infoButton.checked = true;
+
+ instance.toggleRecommendation();
+
+ assert.calledOnce(target.container.setAttribute);
+ });
+ it("should enable container", () => {
+ target.infoButton.checked = false;
+
+ instance.toggleRecommendation();
+
+ assert.calledOnce(target.container.removeAttribute);
+ });
+ });
+ describe("#forceShowMessage", () => {
+ it("should call showMessage with the correct args", () => {
+ sandbox.spy(instance, "showMessage");
+ sandbox.stub(instance, "hideMessage");
+
+ instance.forceShowMessage(fakeTarget.browser, { content: fakeMessage });
+
+ assert.calledOnce(instance.showMessage);
+ assert.calledOnce(instance.hideMessage);
+ assert.calledWithExactly(
+ instance.showMessage,
+ fakeMessage,
+ sinon.match.object,
+ fakeWindow
+ );
+ });
+ it("should insert required fluent files", () => {
+ sandbox.stub(instance, "showMessage");
+
+ instance.forceShowMessage(fakeTarget.browser, { content: fakeMessage });
+
+ assert.calledTwice(fakeWindow.MozXULElement.insertFTLIfNeeded);
+ });
+ it("should insert a message you can collapse", () => {
+ sandbox.spy(instance, "showMessage");
+ sandbox.stub(instance, "toggleRecommendation");
+ sandbox.stub(instance, "sendUserEventTelemetry");
+
+ instance.forceShowMessage(fakeTarget.browser, { content: fakeMessage });
+
+ const [
+ ,
+ eventListenerCb,
+ ] = fakeContainer.addEventListener.secondCall.args;
+ // Called with `true` to show the message
+ instance.toggleRecommendation.reset();
+ eventListenerCb({ stopPropagation: sandbox.stub() });
+
+ assert.calledWithExactly(instance.toggleRecommendation, false);
+ });
+ });
+ describe("#sendImpression", () => {
+ beforeEach(() => {
+ instance.init(
+ fakeHandleMessageRequest,
+ fakeAddImpression,
+ fakeSendTelemetry
+ );
+ instance._response = "foo";
+ });
+ it("should dispatch an impression", () => {
+ instance.sendImpression();
+
+ assert.calledOnce(fakeAddImpression);
+ assert.equal(fakeAddImpression.firstCall.args[0], "foo");
+ });
+ });
+});