/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // Tests clicks and enter key presses on UrlbarUtils.RESULT_TYPE.TIP results. "use strict"; const TIP_URL = "http://example.com/tip"; const HELP_URL = "http://example.com/help"; add_setup(async function () { window.windowUtils.disableNonTestMouseEvents(true); registerCleanupFunction(() => { window.windowUtils.disableNonTestMouseEvents(false); }); Services.telemetry.clearScalars(); Services.telemetry.clearEvents(); await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.eventTelemetry.enabled", true]], }); }); add_task(async function enter_mainButton_url() { await doTest({ click: false, buttonUrl: TIP_URL }); }); add_task(async function enter_mainButton_noURL() { await doTest({ click: false }); }); add_task(async function enter_help() { await doTest({ click: false, helpUrl: HELP_URL }); }); add_task(async function mouse_mainButton_url() { await doTest({ click: true, buttonUrl: TIP_URL }); }); add_task(async function mouse_mainButton_noURL() { await doTest({ click: true }); }); add_task(async function mouse_help() { await doTest({ click: true, helpUrl: HELP_URL }); }); // Clicks inside a tip but not on any button. add_task(async function mouse_insideTipButNotOnButtons() { let results = [makeTipResult({ buttonUrl: TIP_URL, helpUrl: HELP_URL })]; let provider = new UrlbarTestUtils.TestProvider({ results, priority: 1 }); UrlbarProvidersManager.registerProvider(provider); // Click inside the tip but outside the buttons. Nothing should happen. Make // the result the heuristic to check that the selection on the main button // isn't lost. results[0].heuristic = true; await UrlbarTestUtils.promiseAutocompleteResultPopup({ value: "test", window, fireInputEvent: true, }); let row = await UrlbarTestUtils.waitForAutocompleteResultAt(window, 0); Assert.equal( UrlbarTestUtils.getSelectedElementIndex(window), 0, "The main button's index should be selected initially" ); Assert.equal( UrlbarTestUtils.getSelectedElement(window), row._buttons.get("0"), "The main button element should be selected initially" ); EventUtils.synthesizeMouseAtCenter(row, {}); // eslint-disable-next-line mozilla/no-arbitrary-setTimeout await new Promise(r => setTimeout(r, 500)); Assert.ok(gURLBar.view.isOpen, "The view should remain open"); Assert.equal( UrlbarTestUtils.getSelectedElementIndex(window), 0, "The main button's index should remain selected" ); Assert.equal( UrlbarTestUtils.getSelectedElement(window), row._buttons.get("0"), "The main button element should remain selected" ); await UrlbarTestUtils.promisePopupClose(window); UrlbarProvidersManager.unregisterProvider(provider); }); /** * Runs this test's main checks. * * @param {object} options * Options for the test. * @param {boolean} options.click * Pass true to trigger a click, false to trigger an enter key. * @param {string} [options.buttonUrl] * Pass a URL if picking the main button should open a URL. Pass nothing if * a URL shouldn't be opened or if you want to pick the help button instead of * the main button. * @param {string} [options.helpUrl] * Pass a URL if you want to pick the help button. Pass nothing if you want * to pick the main button instead. */ async function doTest({ click, buttonUrl = undefined, helpUrl = undefined }) { // Open a new tab for the test if we expect to load a URL. let tab; if (buttonUrl || helpUrl) { tab = await BrowserTestUtils.openNewForegroundTab({ gBrowser, url: "about:blank", }); } // Add our test provider. let provider = new UrlbarTestUtils.TestProvider({ results: [makeTipResult({ buttonUrl, helpUrl })], priority: 1, }); UrlbarProvidersManager.registerProvider(provider); let onEngagementPromise = new Promise( resolve => (provider.onEngagement = resolve) ); // Do a search to show our tip result. await UrlbarTestUtils.promiseAutocompleteResultPopup({ value: "test", window, fireInputEvent: true, }); let row = await UrlbarTestUtils.waitForAutocompleteResultAt(window, 0); let mainButton = row._buttons.get("0"); let target = helpUrl ? row._buttons.get(UrlbarPrefs.get("resultMenu") ? "menu" : "help") : mainButton; // If we're picking the tip with the keyboard, TAB to select the proper // target. if (!click) { EventUtils.synthesizeKey("KEY_Tab", { repeat: helpUrl ? 2 : 1 }); Assert.equal( UrlbarTestUtils.getSelectedElement(window), target, `${target.className} should be selected.` ); } // Now pick the target and wait for provider.onEngagement to be called and // the URL to load if necessary. let loadPromise; if (buttonUrl || helpUrl) { loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); } await UrlbarTestUtils.promisePopupClose(window, () => { if (helpUrl && UrlbarPrefs.get("resultMenu")) { UrlbarTestUtils.openResultMenuAndPressAccesskey(window, "h", { openByMouse: click, resultIndex: 0, }); } else if (click) { EventUtils.synthesizeMouseAtCenter(target, {}); } else { EventUtils.synthesizeKey("KEY_Enter"); } }); await onEngagementPromise; await loadPromise; // Check telemetry. let scalars = TelemetryTestUtils.getProcessScalars("parent", true, true); TelemetryTestUtils.assertKeyedScalar( scalars, "urlbar.tips", helpUrl ? "test-help" : "test-picked", 1 ); TelemetryTestUtils.assertEvents( [ { category: "urlbar", method: "engagement", object: click && !(helpUrl && UrlbarPrefs.get("resultMenu")) ? "click" : "enter", value: "typed", }, ], { category: "urlbar" } ); // Done. UrlbarProvidersManager.unregisterProvider(provider); if (tab) { BrowserTestUtils.removeTab(tab); } } function makeTipResult({ buttonUrl, helpUrl }) { return new UrlbarResult( UrlbarUtils.RESULT_TYPE.TIP, UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, { type: "test", titleL10n: { id: "urlbar-search-tips-confirm" }, buttons: [ { url: buttonUrl, l10n: { id: "urlbar-search-tips-confirm" }, }, ], helpUrl, helpL10n: { id: UrlbarPrefs.get("resultMenu") ? "urlbar-result-menu-tip-get-help" : "urlbar-tip-help-icon", }, } ); }