123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- 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 fakeDispatch;
- let fakeWindow;
- let isBrowserPrivateStub;
- beforeEach(() => {
- sandbox = sinon.createSandbox();
- globals = new GlobalOverrider();
- fakeL10n = {setAttributes: sandbox.stub()};
- globals.set("DOMLocalization", function() { return fakeL10n; }); // eslint-disable-line prefer-arrow-callback
- globals.set("FxAccounts", {config: {promiseEmailFirstURI: 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}] = PanelTestProvider.getMessages();
- fakeContainer = {
- addEventListener: sandbox.stub(),
- setAttribute: sandbox.stub(),
- removeAttribute: sandbox.stub(),
- classList: {add: sandbox.stub()},
- appendChild: sandbox.stub(),
- querySelector: sandbox.stub(),
- children: [],
- style: {},
- };
- fakeWindow = {
- ownerGlobal: {openLinkIn: sandbox.stub(), gBrowser: {selectedBrowser: "browser"}},
- MozXULElement: {insertFTLIfNeeded: sandbox.stub()},
- };
- const document = {
- createElementNS: sandbox.stub().returns(fakeContainer),
- getElementById: sandbox.stub().returns(fakeContainer),
- };
- 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}},
- };
- fakeDispatch = 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, fakeDispatch);
- assert.equal(instance._addImpression, fakeAddImpression);
- assert.equal(instance._handleMessageRequest, fakeHandleMessageRequest);
- assert.equal(instance._dispatch, fakeDispatch);
- 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, fakeDispatch);
- });
- 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, instance._trigger);
- });
- 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, fakeDispatch);
- 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(fakeDispatch);
- const [ping] = fakeDispatch.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(fakeDispatch);
- });
- 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, fakeDispatch);
- 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, 5);
- 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, 5);
- 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("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})}};
- });
- 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, {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, {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, {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, fakeDispatch);
- instance._response = "foo";
- });
- it("should dispatch an impression", () => {
- instance.sendImpression();
- assert.calledOnce(fakeAddImpression);
- assert.equal(fakeAddImpression.firstCall.args[0], "foo");
- });
- });
- });
|