Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
const { sinon } = ChromeUtils.importESModule(
);
const BASE = getRootDirectory(gTestPath).replace(
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
);
const TEST_URL_1 = BASE + "browser_contextmenu_shareurl.html";
const TEST_URL_2 = "https://example.org/";
let mockShareData = [
{
name: "Test",
menuItemTitle: "Sharing Service Test",
image:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKE" +
"lEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==",
},
];
// Setup spies for observing function calls from MacSharingService
let shareUrlSpy = sinon.spy();
let openSharingPreferencesSpy = sinon.spy();
let getSharingProvidersSpy = sinon.spy();
let { MockRegistrar } = ChromeUtils.importESModule(
);
let mockMacSharingService = MockRegistrar.register(
"@mozilla.org/widget/macsharingservice;1",
{
getSharingProviders(url) {
getSharingProvidersSpy(url);
return mockShareData;
},
shareUrl(name, url, title) {
shareUrlSpy(name, url, title);
},
openSharingPreferences() {
openSharingPreferencesSpy();
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIMacSharingService]),
}
);
registerCleanupFunction(function () {
MockRegistrar.unregister(mockMacSharingService);
});
const qrCodeEnabled = Services.prefs.getBoolPref(
"browser.shareqrcode.enabled",
false
);
// copy link + service + More, plus QR code if enabled.
const expectedItemCount = qrCodeEnabled ? 4 : 3;
/**
* Test the "Share" item menus in the tab contextmenu on MacOSX.
*/
add_task(async function test_contextmenu_share_macosx() {
await BrowserTestUtils.withNewTab(TEST_URL_1, async () => {
let contextMenu = await openTabContextMenu(gBrowser.selectedTab);
await BrowserTestUtils.waitForMutationCondition(
contextMenu,
{ childList: true },
() => contextMenu.querySelector(".share-tab-url-item")
);
ok(true, "Got Share item");
await openMenuPopup(contextMenu);
ok(getSharingProvidersSpy.calledOnce, "getSharingProviders called");
info(
"Check we have copy link, a service and one extra menu item for the More... button"
);
let popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
let items = Array.from(popup.querySelectorAll("menuitem"));
is(
items.length,
expectedItemCount,
`There should be ${expectedItemCount} menu items.`
);
info("Click on the sharing service");
let menuPopupClosedPromised = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"hidden"
);
let shareButton = items.find(
t => t.label == mockShareData[0].menuItemTitle
);
ok(
shareButton,
"Share button's label should match the service's menu item title. "
);
is(
shareButton?.getAttribute("data-share-name"),
mockShareData[0].name,
"Share button's share-name value should match the service's name. "
);
popup.activateItem(shareButton);
await menuPopupClosedPromised;
ok(shareUrlSpy.calledOnce, "shareUrl called");
info("Check the correct data was shared.");
let [name, url, title] = shareUrlSpy.getCall(0).args;
is(name, mockShareData[0].name, "Shared correct service name");
is(url, TEST_URL_1, "Shared correct URL");
is(title, "Sharing URL", "Shared the correct title.");
info("Test the copy link button");
contextMenu = await openTabContextMenu(gBrowser.selectedTab);
await openMenuPopup(contextMenu);
// Since the tab context menu was collapsed previously, the popup needs to get the
// providers again.
ok(getSharingProvidersSpy.calledTwice, "getSharingProviders called again");
popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
items = Array.from(popup.querySelectorAll("menuitem"));
is(
items.length,
expectedItemCount,
`There should be ${expectedItemCount} menu items.`
);
info("Click on the Copy Link item");
let copyLinkItem = items.find(item =>
item.classList.contains("share-copy-link")
);
menuPopupClosedPromised = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"hidden"
);
await SimpleTest.promiseClipboardChange(TEST_URL_1, () =>
popup.activateItem(copyLinkItem)
);
await menuPopupClosedPromised;
info("Test the More... item");
contextMenu = await openTabContextMenu(gBrowser.selectedTab);
await openMenuPopup(contextMenu);
// Since the tab context menu was collapsed previously, the popup needs to get the
// providers again.
is(getSharingProvidersSpy.callCount, 3, "getSharingProviders called again");
popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
items = popup.querySelectorAll("menuitem");
is(
items.length,
expectedItemCount,
`There should be ${expectedItemCount} menu items.`
);
info("Click on the More item");
let moreMenuitem = popup.querySelector(".share-more-button");
menuPopupClosedPromised = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"hidden"
);
popup.activateItem(moreMenuitem);
await menuPopupClosedPromised;
ok(openSharingPreferencesSpy.calledOnce, "openSharingPreferences called");
shareUrlSpy.resetHistory();
});
});
/**
* Test that for multiple selected tabs on macOS:
* - Native sharing services are enabled and share the context tab's URL
* - "Copy links" copies all shareable URLs to the clipboard
*/
add_task(async function test_contextmenu_share_multiselect_macosx() {
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL_1);
let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL_2);
await triggerClickOn(tab1, { ctrlKey: true });
ok(tab1.multiselected, "tab1 is multiselected");
ok(tab2.multiselected, "tab2 is multiselected");
let contextMenu = await openTabContextMenu(tab2);
await BrowserTestUtils.waitForMutationCondition(
contextMenu,
{ childList: true },
() => contextMenu.querySelector(".share-tab-url-item")
);
await openMenuPopup(contextMenu);
let popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
let items = Array.from(popup.querySelectorAll("menuitem"));
info("Native sharing service should be enabled for multi-tab");
let nativeServiceItem = items.find(
item => item.label == mockShareData[0].menuItemTitle
);
ok(nativeServiceItem, "native service item exists");
ok(
!nativeServiceItem.hasAttribute("disabled"),
"native service is enabled for multi-tab (shares context tab URL)"
);
info("Clicking native service shares the context tab's URL");
let menuPopupClosed = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"hidden"
);
popup.activateItem(nativeServiceItem);
await menuPopupClosed;
ok(shareUrlSpy.calledOnce, "shareUrl was called once");
is(
shareUrlSpy.firstCall.args[1],
TEST_URL_2,
"shareUrl was called with the context tab's URL"
);
info("Verify that tab multiselect is enabled");
contextMenu = await openTabContextMenu(tab2);
await openMenuPopup(contextMenu);
popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
items = Array.from(popup.querySelectorAll("menuitem"));
let copyLinkItem = items.find(item =>
item.classList.contains("share-copy-link")
);
ok(copyLinkItem, "copy link item exists");
ok(
!copyLinkItem.hasAttribute("disabled"),
"copy link is enabled for multi-tab"
);
menuPopupClosed = BrowserTestUtils.waitForPopupEvent(contextMenu, "hidden");
await SimpleTest.promiseClipboardChange(TEST_URL_1 + "\n" + TEST_URL_2, () =>
popup.activateItem(copyLinkItem)
);
await menuPopupClosed;
info("Verify HTML clipboard contains linked anchors for both tabs");
let htmlContent = getHTMLClipboard();
let htmlDoc = new DOMParser().parseFromString(htmlContent, "text/html");
let anchors = Array.from(htmlDoc.querySelectorAll("a"));
is(anchors.length, 2, "HTML clipboard has 2 anchor elements");
is(
anchors[0].getAttribute("href"),
TEST_URL_1,
"First anchor href matches URL 1"
);
ok(anchors[0].textContent, "First anchor has non-empty title");
is(
anchors[1].getAttribute("href"),
TEST_URL_2,
"Second anchor href matches URL 2"
);
ok(anchors[1].textContent, "Second anchor has non-empty title");
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
shareUrlSpy.resetHistory();
});
/**
* Test that Copy Links is enabled when the first selected tab is about:blank
* but another selected tab has a real URL.
*/
add_task(
async function test_contextmenu_share_multiselect_blank_first_macosx() {
let tab1 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:blank"
);
let tab2 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_URL_1
);
await triggerClickOn(tab1, { ctrlKey: true });
ok(tab1.multiselected, "tab1 (blank) is multiselected");
ok(tab2.multiselected, "tab2 (real URL) is multiselected");
let contextMenu = await openTabContextMenu(tab1);
await BrowserTestUtils.waitForMutationCondition(
contextMenu,
{ childList: true },
() => contextMenu.querySelector(".share-tab-url-item")
);
await openMenuPopup(contextMenu);
let popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
let copyLinkItem = Array.from(popup.querySelectorAll("menuitem")).find(
item => item.classList.contains("share-copy-link")
);
ok(copyLinkItem, "copy links item exists");
ok(
!copyLinkItem.hasAttribute("disabled"),
"copy links is enabled when at least one tab has a shareable URL"
);
let menuPopupClosed = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"hidden"
);
contextMenu.hidePopup();
await menuPopupClosed;
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
}
);
/**
* Test that Copy Links is disabled when all selected tabs have non-shareable URLs.
*/
add_task(async function test_contextmenu_share_multiselect_all_blank_macosx() {
let tab1 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:blank"
);
let tab2 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:blank"
);
await triggerClickOn(tab1, { ctrlKey: true });
ok(tab1.multiselected, "tab1 is multiselected");
ok(tab2.multiselected, "tab2 is multiselected");
let contextMenu = await openTabContextMenu(tab2);
await BrowserTestUtils.waitForMutationCondition(
contextMenu,
{ childList: true },
() => contextMenu.querySelector(".share-tab-url-item")
);
await openMenuPopup(contextMenu);
let popup = contextMenu.querySelector(".share-tab-url-item").menupopup;
let copyLinkItem = Array.from(popup.querySelectorAll("menuitem")).find(item =>
item.classList.contains("share-copy-link")
);
ok(copyLinkItem, "copy links item exists");
is(
copyLinkItem.getAttribute("disabled"),
"true",
"copy links is disabled when all selected tabs have non-shareable URLs"
);
let menuPopupClosed = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"hidden"
);
contextMenu.hidePopup();
await menuPopupClosed;
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
});
/**
* Helper for opening the toolbar context menu.
*/
async function openTabContextMenu(tab) {
info("Opening tab context menu");
let contextMenu = document.getElementById("tabContextMenu");
let openTabContextMenuPromise = BrowserTestUtils.waitForPopupEvent(
contextMenu,
"shown"
);
EventUtils.synthesizeMouseAtCenter(tab, { type: "contextmenu" });
await openTabContextMenuPromise;
return contextMenu;
}
async function openMenuPopup(contextMenu) {
info("Opening Share menu popup.");
let shareItem = contextMenu.querySelector(".share-tab-url-item");
shareItem.openMenu(true);
await BrowserTestUtils.waitForPopupEvent(shareItem.menupopup, "shown");
}