diff options
Diffstat (limited to 'browser/base/content/test/sync/browser_contextmenu_sendpage.js')
-rw-r--r-- | browser/base/content/test/sync/browser_contextmenu_sendpage.js | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/browser/base/content/test/sync/browser_contextmenu_sendpage.js b/browser/base/content/test/sync/browser_contextmenu_sendpage.js new file mode 100644 index 0000000000..168fca2a2c --- /dev/null +++ b/browser/base/content/test/sync/browser_contextmenu_sendpage.js @@ -0,0 +1,465 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const fxaDevices = [ + { + id: 1, + name: "Foo", + availableCommands: { "https://identity.mozilla.com/cmd/open-uri": "baz" }, + lastAccessTime: Date.now(), + }, + { + id: 2, + name: "Bar", + availableCommands: { "https://identity.mozilla.com/cmd/open-uri": "boo" }, + lastAccessTime: Date.now() + 60000, // add 30min + }, + { + id: 3, + name: "Baz", + clientRecord: "bar", + lastAccessTime: Date.now() + 120000, // add 60min + }, // Legacy send tab target (no availableCommands). + { id: 4, name: "Homer" }, // Incompatible target. +]; + +add_setup(async function() { + await promiseSyncReady(); + await Services.search.init(); + // gSync.init() is called in a requestIdleCallback. Force its initialization. + gSync.init(); + sinon + .stub(Weave.Service.clientsEngine, "getClientByFxaDeviceId") + .callsFake(fxaDeviceId => { + let target = fxaDevices.find(c => c.id == fxaDeviceId); + return target ? target.clientRecord : null; + }); + sinon.stub(Weave.Service.clientsEngine, "getClientType").returns("desktop"); + await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:mozilla"); +}); + +add_task(async function test_page_contextmenu() { + const sandbox = setupSendTabMocks({ fxaDevices }); + + await openContentContextMenu("#moztext", "context-sendpagetodevice"); + is( + document.getElementById("context-sendpagetodevice").hidden, + false, + "Send page to device is shown" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send page to device is enabled" + ); + checkPopup([ + { label: "Bar" }, + { label: "Foo" }, + "----", + { label: "Send to All Devices" }, + { label: "Manage Devices..." }, + ]); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_link_contextmenu() { + const sandbox = setupSendTabMocks({ fxaDevices }); + let expectation = sandbox + .mock(gSync) + .expects("sendTabToDevice") + .once() + .withExactArgs( + "https://www.example.org/", + [fxaDevices[1]], + "Click on me!!" + ); + + // Add a link to the page + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => { + let a = content.document.createElement("a"); + a.href = "https://www.example.org"; + a.id = "testingLink"; + a.textContent = "Click on me!!"; + content.document.body.appendChild(a); + }); + + let contextMenu = await openContentContextMenu( + "#testingLink", + "context-sendlinktodevice", + "context-sendlinktodevice-popup" + ); + + let expectedArray = ["context-openlinkintab"]; + + if ( + Services.prefs.getBoolPref("privacy.userContext.enabled") && + ContextualIdentityService.getPublicIdentities().length + ) { + expectedArray.push("context-openlinkinusercontext-menu"); + } + + expectedArray.push( + "context-openlink", + "context-openlinkprivate", + "context-sep-open", + "context-bookmarklink", + "context-savelink", + "context-savelinktopocket", + "context-copylink", + "context-sendlinktodevice", + "context-sep-sendlinktodevice", + "context-searchselect", + "frame-sep" + ); + + if ( + Services.prefs.getBoolPref("devtools.accessibility.enabled", true) && + (Services.prefs.getBoolPref("devtools.everOpened", false) || + Services.prefs.getIntPref("devtools.selfxss.count", 0) > 0) + ) { + expectedArray.push("context-inspect-a11y"); + } + + expectedArray.push("context-inspect"); + + let menu = document.getElementById("contentAreaContextMenu"); + + for (let i = 0, j = 0; i < menu.children.length; i++) { + let item = menu.children[i]; + if (item.hidden) { + continue; + } + Assert.equal( + item.id, + expectedArray[j], + "Ids in context menu match expected values" + ); + j++; + } + + is( + document.getElementById("context-sendlinktodevice").hidden, + false, + "Send link to device is shown" + ); + is( + document.getElementById("context-sendlinktodevice").disabled, + false, + "Send link to device is enabled" + ); + contextMenu.activateItem( + document + .getElementById("context-sendlinktodevice-popup") + .querySelector("menuitem") + ); + await hideContentContextMenu(); + + expectation.verify(); + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_no_remote_clients() { + const sandbox = setupSendTabMocks({ fxaDevices: [] }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send tab to device is enabled" + ); + checkPopup(); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_one_remote_client() { + const sandbox = setupSendTabMocks({ + fxaDevices: [ + { + id: 1, + name: "Foo", + availableCommands: { + "https://identity.mozilla.com/cmd/open-uri": "baz", + }, + }, + ], + }); + + await openContentContextMenu("#moztext", "context-sendpagetodevice"); + is( + document.getElementById("context-sendpagetodevice").hidden, + false, + "Send page to device is shown" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send page to device is enabled" + ); + checkPopup([{ label: "Foo" }]); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_not_sendable() { + const sandbox = setupSendTabMocks({ fxaDevices, isSendableURI: false }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + true, + "Send page to device is disabled" + ); + checkPopup(); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_not_synced_yet() { + const sandbox = setupSendTabMocks({ fxaDevices: null }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + true, + "Send page to device is disabled" + ); + checkPopup(); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_sync_not_ready_configured() { + const sandbox = setupSendTabMocks({ syncReady: false }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + true, + "Send page to device is disabled" + ); + checkPopup(); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_sync_not_ready_other_state() { + const sandbox = setupSendTabMocks({ + syncReady: false, + state: UIState.STATUS_NOT_VERIFIED, + }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send page to device is enabled" + ); + checkPopup(); + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_unconfigured() { + const sandbox = setupSendTabMocks({ state: UIState.STATUS_NOT_CONFIGURED }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send page to device is enabled" + ); + checkPopup(); + + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_not_verified() { + const sandbox = setupSendTabMocks({ state: UIState.STATUS_NOT_VERIFIED }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send page to device is enabled" + ); + checkPopup(); + + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_login_failed() { + const sandbox = setupSendTabMocks({ state: UIState.STATUS_LOGIN_FAILED }); + + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + is( + document.getElementById("context-sendpagetodevice").disabled, + false, + "Send page to device is enabled" + ); + checkPopup(); + + await hideContentContextMenu(); + + sandbox.restore(); +}); + +add_task(async function test_page_contextmenu_fxa_disabled() { + const getter = sinon.stub(gSync, "FXA_ENABLED").get(() => false); + gSync.onFxaDisabled(); // Would have been called on gSync initialization if FXA_ENABLED had been set. + await openContentContextMenu("#moztext"); + is( + document.getElementById("context-sendpagetodevice").hidden, + true, + "Send page to device is hidden" + ); + await hideContentContextMenu(); + getter.restore(); + [...document.querySelectorAll(".sync-ui-item")].forEach( + e => (e.hidden = false) + ); +}); + +// We are not going to bother testing the visibility of context-sendlinktodevice +// since it uses the exact same code. +// However, browser_contextmenu.js contains tests that verify its presence. + +add_task(async function teardown() { + Weave.Service.clientsEngine.getClientByFxaDeviceId.restore(); + Weave.Service.clientsEngine.getClientType.restore(); + gBrowser.removeCurrentTab(); +}); + +function checkPopup(expectedItems = null) { + const popup = document.getElementById("context-sendpagetodevice-popup"); + if (!expectedItems) { + is(popup.state, "closed", "Popup should be hidden."); + return; + } + const menuItems = popup.children; + for (let i = 0; i < menuItems.length; i++) { + const menuItem = menuItems[i]; + const expectedItem = expectedItems[i]; + if (expectedItem === "----") { + is(menuItem.nodeName, "menuseparator", "Found a separator"); + continue; + } + is(menuItem.nodeName, "menuitem", "Found a menu item"); + // Bug workaround, menuItem.label "…" encoding is different than ours. + is( + menuItem.label.normalize("NFKC"), + expectedItem.label, + "Correct menu item label" + ); + is( + menuItem.disabled, + !!expectedItem.disabled, + "Correct menu item disabled state" + ); + } + // check the length last - the above loop might have given us other clues... + is( + menuItems.length, + expectedItems.length, + "Popup has the expected children count." + ); +} + +async function openContentContextMenu(selector, openSubmenuId = null) { + const contextMenu = document.getElementById("contentAreaContextMenu"); + is(contextMenu.state, "closed", "checking if popup is closed"); + + const awaitPopupShown = BrowserTestUtils.waitForEvent( + contextMenu, + "popupshown" + ); + await BrowserTestUtils.synthesizeMouse( + selector, + 0, + 0, + { + type: "contextmenu", + button: 2, + shiftkey: false, + centered: true, + }, + gBrowser.selectedBrowser + ); + await awaitPopupShown; + + if (openSubmenuId) { + const menu = document.getElementById(openSubmenuId); + const menuPopup = menu.menupopup; + const menuPopupPromise = BrowserTestUtils.waitForEvent( + menuPopup, + "popupshown" + ); + menu.openMenu(true); + await menuPopupPromise; + } + return contextMenu; +} + +async function hideContentContextMenu() { + const contextMenu = document.getElementById("contentAreaContextMenu"); + const awaitPopupHidden = BrowserTestUtils.waitForEvent( + contextMenu, + "popuphidden" + ); + contextMenu.hidePopup(); + await awaitPopupHidden; +} |