diff options
Diffstat (limited to '')
8 files changed, 623 insertions, 0 deletions
diff --git a/browser/components/pocket/test/unit/browser.ini b/browser/components/pocket/test/unit/browser.ini new file mode 100644 index 0000000000..5d616810e5 --- /dev/null +++ b/browser/components/pocket/test/unit/browser.ini @@ -0,0 +1,7 @@ +[DEFAULT] +support-files = + head.js + +[browser_pocket_AboutPocketParent.js] +[browser_pocket_pktTelemetry.js] +[browser_pocket_pktUI.js] diff --git a/browser/components/pocket/test/unit/browser_pocket_AboutPocketParent.js b/browser/components/pocket/test/unit/browser_pocket_AboutPocketParent.js new file mode 100644 index 0000000000..5abe3b3db1 --- /dev/null +++ b/browser/components/pocket/test/unit/browser_pocket_AboutPocketParent.js @@ -0,0 +1,372 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const { AboutPocketParent } = ChromeUtils.importESModule( + "resource:///actors/AboutPocketParent.sys.mjs" +); +const { pktApi } = ChromeUtils.importESModule( + "chrome://pocket/content/pktApi.sys.mjs" +); +let aboutPocketParent; + +function test_runner(test) { + let testTask = async () => { + // Before each + const sandbox = sinon.createSandbox(); + aboutPocketParent = new AboutPocketParent(); + + const manager = { + isClosed: false, + }; + const browsingContext = { + topChromeWindow: { + pktUI: { + onShowSignup: sandbox.spy(), + onShowSaved: sandbox.spy(), + closePanel: sandbox.spy(), + onOpenTabWithUrl: sandbox.spy(), + onOpenTabWithPocketUrl: sandbox.spy(), + resizePanel: sandbox.spy(), + getPanelFrame: () => ({ setAttribute: () => {} }), + }, + }, + embedderElement: { + csp: "csp", + contentPrincipal: "contentPrincipal", + }, + }; + + sandbox.stub(aboutPocketParent, "manager").get(() => manager); + sandbox + .stub(aboutPocketParent, "browsingContext") + .get(() => browsingContext); + + try { + await test({ sandbox }); + } finally { + // After each + sandbox.restore(); + } + }; + + // Copy the name of the test function to identify the test + Object.defineProperty(testTask, "name", { value: test.name }); + add_task(testTask); +} + +test_runner(async function test_AboutPocketParent_sendResponseMessageToPanel({ + sandbox, +}) { + const sendAsyncMessage = sandbox.stub(aboutPocketParent, "sendAsyncMessage"); + + aboutPocketParent.sendResponseMessageToPanel("PKT_testMessage", { + foo: 1, + }); + + const { args } = sendAsyncMessage.firstCall; + + Assert.ok( + sendAsyncMessage.calledOnce, + "Should fire sendAsyncMessage once with sendResponseMessageToPanel" + ); + Assert.deepEqual( + args, + ["PKT_testMessage_response", { foo: 1 }], + "Should fire sendAsyncMessage with proper args from sendResponseMessageToPanel" + ); +}); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_show_signup({ + sandbox, + }) { + await aboutPocketParent.receiveMessage({ + name: "PKT_show_signup", + }); + + const { onShowSignup } = + aboutPocketParent.browsingContext.topChromeWindow.pktUI; + + Assert.ok( + onShowSignup.calledOnce, + "Should fire onShowSignup once with PKT_show_signup" + ); + } +); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_show_saved({ + sandbox, + }) { + await aboutPocketParent.receiveMessage({ + name: "PKT_show_saved", + }); + + const { onShowSaved } = + aboutPocketParent.browsingContext.topChromeWindow.pktUI; + + Assert.ok( + onShowSaved.calledOnce, + "Should fire onShowSaved once with PKT_show_saved" + ); + } +); + +test_runner(async function test_AboutPocketParent_receiveMessage_PKT_close({ + sandbox, +}) { + await aboutPocketParent.receiveMessage({ + name: "PKT_close", + }); + + const { closePanel } = + aboutPocketParent.browsingContext.topChromeWindow.pktUI; + + Assert.ok( + closePanel.calledOnce, + "Should fire closePanel once with PKT_close" + ); +}); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_openTabWithUrl({ + sandbox, + }) { + await aboutPocketParent.receiveMessage({ + name: "PKT_openTabWithUrl", + data: { foo: 1 }, + }); + + const { onOpenTabWithUrl } = + aboutPocketParent.browsingContext.topChromeWindow.pktUI; + const { args } = onOpenTabWithUrl.firstCall; + + Assert.ok( + onOpenTabWithUrl.calledOnce, + "Should fire onOpenTabWithUrl once with PKT_openTabWithUrl" + ); + Assert.deepEqual( + args, + [{ foo: 1 }, "contentPrincipal", "csp"], + "Should fire onOpenTabWithUrl with proper args from PKT_openTabWithUrl" + ); + } +); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_openTabWithPocketUrl({ + sandbox, + }) { + await aboutPocketParent.receiveMessage({ + name: "PKT_openTabWithPocketUrl", + data: { foo: 1 }, + }); + + const { onOpenTabWithPocketUrl } = + aboutPocketParent.browsingContext.topChromeWindow.pktUI; + const { args } = onOpenTabWithPocketUrl.firstCall; + + Assert.ok( + onOpenTabWithPocketUrl.calledOnce, + "Should fire onOpenTabWithPocketUrl once with PKT_openTabWithPocketUrl" + ); + Assert.deepEqual( + args, + [{ foo: 1 }, "contentPrincipal", "csp"], + "Should fire onOpenTabWithPocketUrl with proper args from PKT_openTabWithPocketUrl" + ); + } +); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_resizePanel({ + sandbox, + }) { + const sendResponseMessageToPanel = sandbox.stub( + aboutPocketParent, + "sendResponseMessageToPanel" + ); + await aboutPocketParent.receiveMessage({ + name: "PKT_resizePanel", + data: { foo: 1 }, + }); + + const { resizePanel } = + aboutPocketParent.browsingContext.topChromeWindow.pktUI; + const { args } = resizePanel.firstCall; + + Assert.ok( + resizePanel.calledOnce, + "Should fire resizePanel once with PKT_resizePanel" + ); + Assert.deepEqual( + args, + [{ foo: 1 }], + "Should fire resizePanel with proper args from PKT_resizePanel" + ); + Assert.ok( + sendResponseMessageToPanel.calledOnce, + "Should fire sendResponseMessageToPanel once with PKT_resizePanel" + ); + Assert.deepEqual( + sendResponseMessageToPanel.firstCall.args, + ["PKT_resizePanel"], + "Should fire sendResponseMessageToPanel with proper args from PKT_resizePanel" + ); + } +); + +test_runner(async function test_AboutPocketParent_receiveMessage_PKT_getTags({ + sandbox, +}) { + const sendResponseMessageToPanel = sandbox.stub( + aboutPocketParent, + "sendResponseMessageToPanel" + ); + await aboutPocketParent.receiveMessage({ + name: "PKT_getTags", + }); + Assert.ok( + sendResponseMessageToPanel.calledOnce, + "Should fire sendResponseMessageToPanel once with PKT_getTags" + ); + Assert.deepEqual( + sendResponseMessageToPanel.firstCall.args, + ["PKT_getTags", { tags: [] }], + "Should fire sendResponseMessageToPanel with proper args from PKT_getTags" + ); +}); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_getSuggestedTags({ + sandbox, + }) { + const sendResponseMessageToPanel = sandbox.stub( + aboutPocketParent, + "sendResponseMessageToPanel" + ); + sandbox.stub(pktApi, "getSuggestedTagsForURL").callsFake((url, options) => { + options.success({ suggested_tags: "foo" }); + }); + + await aboutPocketParent.receiveMessage({ + name: "PKT_getSuggestedTags", + data: { url: "https://foo.com" }, + }); + + Assert.ok( + pktApi.getSuggestedTagsForURL.calledOnce, + "Should fire getSuggestedTagsForURL once with PKT_getSuggestedTags" + ); + Assert.equal( + pktApi.getSuggestedTagsForURL.firstCall.args[0], + "https://foo.com", + "Should fire getSuggestedTagsForURL with proper url from PKT_getSuggestedTags" + ); + Assert.ok( + sendResponseMessageToPanel.calledOnce, + "Should fire sendResponseMessageToPanel once with PKT_getSuggestedTags" + ); + Assert.deepEqual( + sendResponseMessageToPanel.firstCall.args, + [ + "PKT_getSuggestedTags", + { + status: "success", + value: { suggestedTags: "foo" }, + }, + ], + "Should fire sendResponseMessageToPanel with proper args from PKT_getSuggestedTags" + ); + } +); + +test_runner(async function test_AboutPocketParent_receiveMessage_PKT_addTags({ + sandbox, +}) { + const sendResponseMessageToPanel = sandbox.stub( + aboutPocketParent, + "sendResponseMessageToPanel" + ); + sandbox.stub(pktApi, "addTagsToURL").callsFake((url, tags, options) => { + options.success(); + }); + + await aboutPocketParent.receiveMessage({ + name: "PKT_addTags", + data: { url: "https://foo.com", tags: "tags" }, + }); + + Assert.ok( + pktApi.addTagsToURL.calledOnce, + "Should fire addTagsToURL once with PKT_addTags" + ); + Assert.equal( + pktApi.addTagsToURL.firstCall.args[0], + "https://foo.com", + "Should fire addTagsToURL with proper url from PKT_addTags" + ); + Assert.equal( + pktApi.addTagsToURL.firstCall.args[1], + "tags", + "Should fire addTagsToURL with proper tags from PKT_addTags" + ); + Assert.ok( + sendResponseMessageToPanel.calledOnce, + "Should fire sendResponseMessageToPanel once with PKT_addTags" + ); + Assert.deepEqual( + sendResponseMessageToPanel.firstCall.args, + [ + "PKT_addTags", + { + status: "success", + }, + ], + "Should fire sendResponseMessageToPanel with proper args from PKT_addTags" + ); +}); + +test_runner( + async function test_AboutPocketParent_receiveMessage_PKT_deleteItem({ + sandbox, + }) { + const sendResponseMessageToPanel = sandbox.stub( + aboutPocketParent, + "sendResponseMessageToPanel" + ); + sandbox.stub(pktApi, "deleteItem").callsFake((itemId, options) => { + options.success(); + }); + + await aboutPocketParent.receiveMessage({ + name: "PKT_deleteItem", + data: { itemId: "itemId" }, + }); + + Assert.ok( + pktApi.deleteItem.calledOnce, + "Should fire deleteItem once with PKT_deleteItem" + ); + Assert.equal( + pktApi.deleteItem.firstCall.args[0], + "itemId", + "Should fire deleteItem with proper itemId from PKT_deleteItem" + ); + Assert.ok( + sendResponseMessageToPanel.calledOnce, + "Should fire sendResponseMessageToPanel once with PKT_deleteItem" + ); + Assert.deepEqual( + sendResponseMessageToPanel.firstCall.args, + [ + "PKT_deleteItem", + { + status: "success", + }, + ], + "Should fire sendResponseMessageToPanel with proper args from PKT_deleteItem" + ); + } +); diff --git a/browser/components/pocket/test/unit/browser_pocket_pktTelemetry.js b/browser/components/pocket/test/unit/browser_pocket_pktTelemetry.js new file mode 100644 index 0000000000..197a152ee5 --- /dev/null +++ b/browser/components/pocket/test/unit/browser_pocket_pktTelemetry.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +ChromeUtils.defineESModuleGetters(this, { + pktTelemetry: "chrome://pocket/content/pktTelemetry.sys.mjs", +}); + +function test_runner(test) { + let testTask = async () => { + // Before each + const sandbox = sinon.createSandbox(); + try { + await test({ sandbox }); + } finally { + // After each + sandbox.restore(); + } + }; + + // Copy the name of the test function to identify the test + Object.defineProperty(testTask, "name", { value: test.name }); + add_task(testTask); +} + +test_runner(async function test_createPingPayload({ sandbox }) { + const impressionId = "{7fd5a1ac-6089-4212-91a7-fcdec1d2f533}"; + const creationDate = "18578"; + await SpecialPowers.pushPrefEnv({ + set: [["browser.newtabpage.activity-stream.impressionId", impressionId]], + }); + sandbox.stub(pktTelemetry, "_profileCreationDate").returns(creationDate); + const result = pktTelemetry.createPingPayload({ test: "test" }); + + Assert.deepEqual(result, { + test: "test", + pocket_logged_in_status: false, + profile_creation_date: creationDate, + impression_id: impressionId, + }); +}); + +test_runner(async function test_generateStructuredIngestionEndpoint({ + sandbox, +}) { + sandbox + .stub(pktTelemetry, "_generateUUID") + .returns("{7fd5a1ac-6089-4212-91a7-fcdec1d2f533}"); + const endpoint = pktTelemetry._generateStructuredIngestionEndpoint(); + Assert.equal( + endpoint, + "https://incoming.telemetry.mozilla.org/submit/activity-stream/pocket-button/1/7fd5a1ac-6089-4212-91a7-fcdec1d2f533" + ); +}); diff --git a/browser/components/pocket/test/unit/browser_pocket_pktUI.js b/browser/components/pocket/test/unit/browser_pocket_pktUI.js new file mode 100644 index 0000000000..92cb78eea6 --- /dev/null +++ b/browser/components/pocket/test/unit/browser_pocket_pktUI.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +function test_runner(test) { + let testTask = async () => { + // Before each + pktUI.initPrefs(); + const sandbox = sinon.createSandbox(); + try { + await test({ sandbox }); + } finally { + // After each + sandbox.restore(); + } + }; + + // Copy the name of the test function to identify the test + Object.defineProperty(testTask, "name", { value: test.name }); + add_task(testTask); +} + +test_runner(async function test_pktUI_getAndShowRecsForItem_on({ sandbox }) { + await SpecialPowers.pushPrefEnv({ + set: [["extensions.pocket.onSaveRecs", true]], + }); + pktUI.initPrefs(); + const getRecsForItemStub = sandbox.stub(pktApi, "getRecsForItem"); + + pktUI.getAndShowRecsForItem( + { + resolved_id: "1234", + }, + { + success() {}, + } + ); + + Assert.ok(getRecsForItemStub.calledOnce); + Assert.equal(getRecsForItemStub.getCall(0).args[0], "1234"); +}); + +test_runner(async function test_pktUI_getAndShowRecsForItem_off({ sandbox }) { + await SpecialPowers.pushPrefEnv({ + set: [["extensions.pocket.onSaveRecs", false]], + }); + pktUI.initPrefs(); + const getRecsForItemStub = sandbox.stub(pktApi, "getRecsForItem"); + + pktUI.getAndShowRecsForItem( + { + resolved_id: "1234", + }, + { + success() {}, + } + ); + + Assert.ok(getRecsForItemStub.notCalled); +}); + +test_runner(async function test_pktUI_getAndShowRecsForItem_locale({ + sandbox, +}) { + await SpecialPowers.pushPrefEnv({ + set: [ + ["extensions.pocket.onSaveRecs", true], + ["extensions.pocket.onSaveRecs.locales", "de"], + ], + }); + pktUI.initPrefs(); + const getRecsForItemStub = sandbox.stub(pktApi, "getRecsForItem"); + + pktUI.getAndShowRecsForItem( + { + resolved_id: "1234", + }, + { + success() {}, + } + ); + + Assert.ok(getRecsForItemStub.notCalled); +}); + +test_runner(async function test_pktUI_showPanel({ sandbox }) { + const testFrame = { + setAttribute: sandbox.stub(), + style: { width: 0, height: 0 }, + }; + pktUI.setToolbarPanelFrame(testFrame); + + pktUI.showPanel("about:pocket-saved", `saved`); + + Assert.deepEqual(testFrame.setAttribute.args[0], [ + "src", + `about:pocket-saved?utmSource=firefox_pocket_save_button&locale=${SpecialPowers.Services.locale.appLocaleAsBCP47}`, + ]); + Assert.deepEqual(testFrame.style, { width: "350px", height: "110px" }); +}); diff --git a/browser/components/pocket/test/unit/head.js b/browser/components/pocket/test/unit/head.js new file mode 100644 index 0000000000..6699eb7a1c --- /dev/null +++ b/browser/components/pocket/test/unit/head.js @@ -0,0 +1,12 @@ +ChromeUtils.defineESModuleGetters(this, { + pktApi: "chrome://pocket/content/pktApi.sys.mjs", +}); +XPCOMUtils.defineLazyScriptGetter( + this, + "pktUI", + "chrome://pocket/content/pktUI.js" +); + +const { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); diff --git a/browser/components/pocket/test/unit/panels/browser.ini b/browser/components/pocket/test/unit/panels/browser.ini new file mode 100644 index 0000000000..66642d3745 --- /dev/null +++ b/browser/components/pocket/test/unit/panels/browser.ini @@ -0,0 +1,5 @@ +[DEFAULT] +support-files = + head.js + +[browser_pocket_main.js] diff --git a/browser/components/pocket/test/unit/panels/browser_pocket_main.js b/browser/components/pocket/test/unit/panels/browser_pocket_main.js new file mode 100644 index 0000000000..c40ad4d5d4 --- /dev/null +++ b/browser/components/pocket/test/unit/panels/browser_pocket_main.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +function test_runner(test) { + let testTask = async () => { + // Before each + const sandbox = sinon.createSandbox(); + try { + await test({ + sandbox, + pktPanelMessaging: testGlobal.window.pktPanelMessaging, + }); + } finally { + // After each + sandbox.restore(); + } + }; + + // Copy the name of the test function to identify the test + Object.defineProperty(testTask, "name", { value: test.name }); + add_task(testTask); +} + +test_runner(async function test_clickHelper({ sandbox, pktPanelMessaging }) { + // Create a button to test the click helper with. + const button = document.createElement("button"); + button.setAttribute("href", "http://example.com"); + + // Setup a stub for the click itself. + sandbox.stub(pktPanelMessaging, "sendMessage"); + + // Create the click helper and trigger the click. + pktPanelMessaging.clickHelper(button, { source: "test-click", position: 2 }); + button.click(); + + Assert.ok( + pktPanelMessaging.sendMessage.calledOnce, + "Should fire sendMessage once with clickHelper click" + ); + Assert.ok( + pktPanelMessaging.sendMessage.calledWith("PKT_openTabWithUrl", { + url: "http://example.com", + source: "test-click", + position: 2, + }), + "Should send expected values to sendMessage with clickHelper click" + ); +}); diff --git a/browser/components/pocket/test/unit/panels/head.js b/browser/components/pocket/test/unit/panels/head.js new file mode 100644 index 0000000000..cc6ba440f1 --- /dev/null +++ b/browser/components/pocket/test/unit/panels/head.js @@ -0,0 +1,24 @@ +const { sinon } = ChromeUtils.importESModule( + "resource://testing-common/Sinon.sys.mjs" +); + +const testGlobal = { + PKT_PANEL_OVERLAY: class { + create() {} + }, + RPMRemoveMessageListener: () => {}, + RPMAddMessageListener: () => {}, + RPMSendAsyncMessage: () => {}, + window: {}, + self: {}, +}; + +Services.scriptloader.loadSubScript( + "chrome://pocket/content/panels/js/vendor.bundle.js", + testGlobal +); + +Services.scriptloader.loadSubScript( + "chrome://pocket/content/panels/js/main.bundle.js", + testGlobal +); |