diff options
Diffstat (limited to 'browser/components/preferences/tests/browser_applications_selection.js')
-rw-r--r-- | browser/components/preferences/tests/browser_applications_selection.js | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/browser/components/preferences/tests/browser_applications_selection.js b/browser/components/preferences/tests/browser_applications_selection.js new file mode 100644 index 0000000000..bb02e45f32 --- /dev/null +++ b/browser/components/preferences/tests/browser_applications_selection.js @@ -0,0 +1,406 @@ +SimpleTest.requestCompleteLog(); +const { HandlerServiceTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/HandlerServiceTestUtils.sys.mjs" +); + +let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService( + Ci.nsIHandlerService +); + +let gOldMailHandlers = []; +let gDummyHandlers = []; +let gOriginalPreferredMailHandler; +let gOriginalPreferredPDFHandler; + +registerCleanupFunction(function() { + function removeDummyHandlers(handlers) { + // Remove any of the dummy handlers we created. + for (let i = handlers.Count() - 1; i >= 0; i--) { + try { + if ( + gDummyHandlers.some( + h => + h.uriTemplate == + handlers.queryElementAt(i, Ci.nsIWebHandlerApp).uriTemplate + ) + ) { + handlers.removeElementAt(i); + } + } catch (ex) { + /* ignore non-web-app handlers */ + } + } + } + // Re-add the original protocol handlers: + let mailHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto"); + let mailHandlers = mailHandlerInfo.possibleApplicationHandlers; + for (let h of gOldMailHandlers) { + mailHandlers.appendElement(h); + } + removeDummyHandlers(mailHandlers); + mailHandlerInfo.preferredApplicationHandler = gOriginalPreferredMailHandler; + gHandlerService.store(mailHandlerInfo); + + let pdfHandlerInfo = HandlerServiceTestUtils.getHandlerInfo( + "application/pdf" + ); + removeDummyHandlers(pdfHandlerInfo.possibleApplicationHandlers); + pdfHandlerInfo.preferredApplicationHandler = gOriginalPreferredPDFHandler; + gHandlerService.store(pdfHandlerInfo); + + gBrowser.removeCurrentTab(); +}); + +function scrubMailtoHandlers(handlerInfo) { + // Remove extant web handlers because they have icons that + // we fetch from the web, which isn't allowed in tests. + let handlers = handlerInfo.possibleApplicationHandlers; + for (let i = handlers.Count() - 1; i >= 0; i--) { + try { + let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp); + gOldMailHandlers.push(handler); + // If we get here, this is a web handler app. Remove it: + handlers.removeElementAt(i); + } catch (ex) {} + } +} + +add_setup(async function() { + // Create our dummy handlers + let handler1 = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance( + Ci.nsIWebHandlerApp + ); + handler1.name = "Handler 1"; + handler1.uriTemplate = "https://example.com/first/%s"; + + let handler2 = Cc["@mozilla.org/uriloader/web-handler-app;1"].createInstance( + Ci.nsIWebHandlerApp + ); + handler2.name = "Handler 2"; + handler2.uriTemplate = "http://example.org/second/%s"; + gDummyHandlers.push(handler1, handler2); + + function substituteWebHandlers(handlerInfo) { + // Append the dummy handlers to replace them: + let handlers = handlerInfo.possibleApplicationHandlers; + handlers.appendElement(handler1); + handlers.appendElement(handler2); + gHandlerService.store(handlerInfo); + } + // Set up our mailto handler test infrastructure. + let mailtoHandlerInfo = HandlerServiceTestUtils.getHandlerInfo("mailto"); + scrubMailtoHandlers(mailtoHandlerInfo); + gOriginalPreferredMailHandler = mailtoHandlerInfo.preferredApplicationHandler; + substituteWebHandlers(mailtoHandlerInfo); + + // Now do the same for pdf handler: + let pdfHandlerInfo = HandlerServiceTestUtils.getHandlerInfo( + "application/pdf" + ); + // PDF doesn't have built-in web handlers, so no need to scrub. + gOriginalPreferredPDFHandler = pdfHandlerInfo.preferredApplicationHandler; + substituteWebHandlers(pdfHandlerInfo); + + await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); + info("Preferences page opened on the general pane."); + + await gBrowser.selectedBrowser.contentWindow.promiseLoadHandlersList; + info("Apps list loaded."); +}); + +async function selectStandardOptions(itemToUse) { + async function selectItemInPopup(item) { + let popupShown = BrowserTestUtils.waitForEvent(popup, "popupshown"); + // Synthesizing the mouse on the .actionsMenu menulist somehow just selects + // the top row. Probably something to do with the multiple layers of anon + // content - workaround by using the `.open` setter instead. + list.open = true; + await popupShown; + let popupHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden"); + if (typeof item == "function") { + item = item(); + } + popup.activateItem(item); + await popupHidden; + return item; + } + + let itemType = itemToUse.getAttribute("type"); + // Center the item. Center rather than top so it doesn't get blocked by + // the search header. + itemToUse.scrollIntoView({ block: "center" }); + itemToUse.closest("richlistbox").selectItem(itemToUse); + Assert.ok(itemToUse.selected, "Should be able to select our item."); + // Force reflow to make sure it's visible and the container dropdown isn't + // hidden. + itemToUse.getBoundingClientRect().top; + let list = itemToUse.querySelector(".actionsMenu"); + let popup = list.menupopup; + + // select one of our test cases: + let handlerItem = list.querySelector("menuitem[data-l10n-args*='Handler 1']"); + await selectItemInPopup(handlerItem); + let { + preferredAction, + alwaysAskBeforeHandling, + } = HandlerServiceTestUtils.getHandlerInfo(itemType); + Assert.notEqual( + preferredAction, + Ci.nsIHandlerInfo.alwaysAsk, + "Should have selected something other than 'always ask' (" + itemType + ")" + ); + Assert.ok( + !alwaysAskBeforeHandling, + "Should have turned off asking before handling (" + itemType + ")" + ); + + // Test the alwaysAsk option + let alwaysAskItem = list.getElementsByAttribute( + "action", + Ci.nsIHandlerInfo.alwaysAsk + )[0]; + await selectItemInPopup(alwaysAskItem); + Assert.equal( + list.selectedItem, + alwaysAskItem, + "Should have selected always ask item (" + itemType + ")" + ); + alwaysAskBeforeHandling = HandlerServiceTestUtils.getHandlerInfo(itemType) + .alwaysAskBeforeHandling; + Assert.ok( + alwaysAskBeforeHandling, + "Should have turned on asking before handling (" + itemType + ")" + ); + + let useDefaultItem = list.getElementsByAttribute( + "action", + Ci.nsIHandlerInfo.useSystemDefault + ); + useDefaultItem = useDefaultItem && useDefaultItem[0]; + if (useDefaultItem) { + await selectItemInPopup(useDefaultItem); + Assert.equal( + list.selectedItem, + useDefaultItem, + "Should have selected 'use default' item (" + itemType + ")" + ); + preferredAction = HandlerServiceTestUtils.getHandlerInfo(itemType) + .preferredAction; + Assert.equal( + preferredAction, + Ci.nsIHandlerInfo.useSystemDefault, + "Should have selected 'use default' (" + itemType + ")" + ); + } else { + // Whether there's a "use default" item depends on the OS, so it's not + // possible to rely on it being the case or not. + info("No 'Use default' item, so not testing (" + itemType + ")"); + } + + // Select a web app item. + let webAppItems = Array.from( + popup.getElementsByAttribute("action", Ci.nsIHandlerInfo.useHelperApp) + ); + webAppItems = webAppItems.filter( + item => item.handlerApp instanceof Ci.nsIWebHandlerApp + ); + Assert.equal( + webAppItems.length, + 2, + "Should have 2 web application handler. (" + itemType + ")" + ); + Assert.notEqual( + webAppItems[0].label, + webAppItems[1].label, + "Should have 2 different web app handlers" + ); + let selectedItem = await selectItemInPopup(webAppItems[0]); + + // Test that the selected item label is the same as the label + // of the menu item. + let win = gBrowser.selectedBrowser.contentWindow; + await win.document.l10n.translateFragment(selectedItem); + await win.document.l10n.translateFragment(itemToUse); + Assert.equal( + selectedItem.label, + itemToUse.querySelector(".actionContainer label").value, + "Should have selected correct item (" + itemType + ")" + ); + let { preferredApplicationHandler } = HandlerServiceTestUtils.getHandlerInfo( + itemType + ); + preferredApplicationHandler.QueryInterface(Ci.nsIWebHandlerApp); + Assert.equal( + selectedItem.handlerApp.uriTemplate, + preferredApplicationHandler.uriTemplate, + "App should actually be selected in the backend. (" + itemType + ")" + ); + + // select the other web app item + selectedItem = await selectItemInPopup(webAppItems[1]); + + // Test that the selected item label is the same as the label + // of the menu item + await win.document.l10n.translateFragment(selectedItem); + await win.document.l10n.translateFragment(itemToUse); + Assert.equal( + selectedItem.label, + itemToUse.querySelector(".actionContainer label").value, + "Should have selected correct item (" + itemType + ")" + ); + preferredApplicationHandler = HandlerServiceTestUtils.getHandlerInfo(itemType) + .preferredApplicationHandler; + preferredApplicationHandler.QueryInterface(Ci.nsIWebHandlerApp); + Assert.equal( + selectedItem.handlerApp.uriTemplate, + preferredApplicationHandler.uriTemplate, + "App should actually be selected in the backend. (" + itemType + ")" + ); +} + +add_task(async function checkDropdownBehavior() { + let win = gBrowser.selectedBrowser.contentWindow; + + let container = win.document.getElementById("handlersView"); + + // First check a protocol handler item. + let mailItem = container.querySelector("richlistitem[type='mailto']"); + Assert.ok(mailItem, "mailItem is present in handlersView."); + await selectStandardOptions(mailItem); + + // Then check a content menu item. + let pdfItem = container.querySelector("richlistitem[type='application/pdf']"); + Assert.ok(pdfItem, "pdfItem is present in handlersView."); + await selectStandardOptions(pdfItem); +}); + +add_task(async function sortingCheck() { + let win = gBrowser.selectedBrowser.contentWindow; + const handlerView = win.document.getElementById("handlersView"); + const typeColumn = win.document.getElementById("typeColumn"); + Assert.ok(typeColumn, "typeColumn is present in handlersView."); + + let expectedNumberOfItems = handlerView.querySelectorAll("richlistitem") + .length; + + // Test default sorting + assertSortByType("ascending"); + + const oldDir = typeColumn.getAttribute("sortDirection"); + + // click on an item and sort again: + let itemToUse = handlerView.querySelector("richlistitem[type=mailto]"); + itemToUse.scrollIntoView({ block: "center" }); + itemToUse.closest("richlistbox").selectItem(itemToUse); + + // Test sorting on the type column + typeColumn.click(); + assertSortByType("descending"); + Assert.notEqual( + oldDir, + typeColumn.getAttribute("sortDirection"), + "Sort direction should change" + ); + + typeColumn.click(); + assertSortByType("ascending"); + + const actionColumn = win.document.getElementById("actionColumn"); + Assert.ok(actionColumn, "actionColumn is present in handlersView."); + + // Test sorting on the action column + const oldActionDir = actionColumn.getAttribute("sortDirection"); + actionColumn.click(); + assertSortByAction("ascending"); + Assert.notEqual( + oldActionDir, + actionColumn.getAttribute("sortDirection"), + "Sort direction should change" + ); + + actionColumn.click(); + assertSortByAction("descending"); + + // Restore the default sort order + typeColumn.click(); + assertSortByType("ascending"); + + function assertSortByAction(order) { + Assert.equal( + actionColumn.getAttribute("sortDirection"), + order, + `Sort direction should be ${order}` + ); + let siteItems = handlerView.getElementsByTagName("richlistitem"); + Assert.equal( + siteItems.length, + expectedNumberOfItems, + "Number of items should not change." + ); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aType = siteItems[i].getAttribute("actionDescription").toLowerCase(); + let bType = siteItems[i + 1] + .getAttribute("actionDescription") + .toLowerCase(); + let result = 0; + if (aType > bType) { + result = 1; + } else if (bType > aType) { + result = -1; + } + if (order == "ascending") { + Assert.lessOrEqual( + result, + 0, + "Should sort applications in the ascending order by action" + ); + } else { + Assert.greaterOrEqual( + result, + 0, + "Should sort applications in the descending order by action" + ); + } + } + } + + function assertSortByType(order) { + Assert.equal( + typeColumn.getAttribute("sortDirection"), + order, + `Sort direction should be ${order}` + ); + + let siteItems = handlerView.getElementsByTagName("richlistitem"); + Assert.equal( + siteItems.length, + expectedNumberOfItems, + "Number of items should not change." + ); + for (let i = 0; i < siteItems.length - 1; ++i) { + let aType = siteItems[i].getAttribute("typeDescription").toLowerCase(); + let bType = siteItems[i + 1] + .getAttribute("typeDescription") + .toLowerCase(); + let result = 0; + if (aType > bType) { + result = 1; + } else if (bType > aType) { + result = -1; + } + if (order == "ascending") { + Assert.lessOrEqual( + result, + 0, + "Should sort applications in the ascending order by type" + ); + } else { + Assert.greaterOrEqual( + result, + 0, + "Should sort applications in the descending order by type" + ); + } + } + } +}); |