diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js')
-rw-r--r-- | browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js | 1596 |
1 files changed, 1596 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js new file mode 100644 index 0000000000..92c3c7c95d --- /dev/null +++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js @@ -0,0 +1,1596 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests the buttons in the onboarding dialog for quick suggest/Firefox Suggest. + */ + +ChromeUtils.defineESModuleGetters(this, { + TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs", +}); + +const OTHER_DIALOG_URI = getRootDirectory(gTestPath) + "subdialog.xhtml"; + +// Default-branch pref values in the offline scenario. +const OFFLINE_DEFAULT_PREFS = { + "suggest.quicksuggest.nonsponsored": true, + "suggest.quicksuggest.sponsored": true, + "quicksuggest.dataCollection.enabled": false, +}; + +let gDefaultBranch = Services.prefs.getDefaultBranch("browser.urlbar."); +let gUserBranch = Services.prefs.getBranch("browser.urlbar."); + +// Allow more time for Mac and Linux machines so they don't time out in verify mode. +if (AppConstants.platform === "macosx") { + requestLongerTimeout(4); +} else if (AppConstants.platform === "linux") { + requestLongerTimeout(2); +} + +// Whether the tab key can move the focus. On macOS with full keyboard access +// disabled (which is default), this will be false. See `canTabMoveFocus`. +let gCanTabMoveFocus; +add_setup(async function () { + gCanTabMoveFocus = await canTabMoveFocus(); +}); + +// When the user has already enabled the data-collection pref, the dialog should +// not appear. +add_task(async function dataCollectionAlreadyEnabled() { + setDialogPrereqPrefs(); + UrlbarPrefs.set("quicksuggest.dataCollection.enabled", true); + + info("Calling maybeShowOnboardingDialog"); + let showed = await QuickSuggest.maybeShowOnboardingDialog(); + Assert.ok(!showed, "The dialog was not shown"); + + UrlbarPrefs.clear("quicksuggest.dataCollection.enabled"); +}); + +// When the current tab is about:welcome, the dialog should not appear. +add_task(async function aboutWelcome() { + setDialogPrereqPrefs(); + await BrowserTestUtils.withNewTab("about:welcome", async () => { + info("Calling maybeShowOnboardingDialog"); + let showed = await QuickSuggest.maybeShowOnboardingDialog(); + Assert.ok(!showed, "The dialog was not shown"); + }); +}); + +// The Escape key should dismiss the dialog without opting in. This task tests +// when Escape is pressed while the focus is inside the dialog. +add_task(async function escKey_focusInsideDialog() { + await doDialogTest({ + callback: async () => { + const { maybeShowPromise } = await showOnboardingDialog({ + skipIntroduction: true, + }); + + const tabCount = gBrowser.tabs.length; + Assert.ok( + document.activeElement.classList.contains("dialogFrame"), + "dialogFrame is focused in the browser window" + ); + + info("Close the dialog"); + EventUtils.synthesizeKey("KEY_Escape"); + + await maybeShowPromise; + + Assert.equal( + gBrowser.currentURI.spec, + "about:blank", + "Nothing loaded in the current tab" + ); + Assert.equal(gBrowser.tabs.length, tabCount, "No news tabs were opened"); + }, + onboardingDialogVersion: JSON.stringify({ version: 1 }), + onboardingDialogChoice: "dismiss_2", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "dismiss_2", + }, + ], + }); +}); + +// The Escape key should dismiss the dialog without opting in. This task tests +// when Escape is pressed while the focus is outside the dialog. +add_task(async function escKey_focusOutsideDialog() { + await doDialogTest({ + callback: async () => { + const { maybeShowPromise } = await showOnboardingDialog({ + skipIntroduction: true, + }); + + document.documentElement.focus(); + Assert.ok( + !document.activeElement.classList.contains("dialogFrame"), + "dialogFrame is not focused in the browser window" + ); + + info("Close the dialog"); + EventUtils.synthesizeKey("KEY_Escape"); + + await maybeShowPromise; + }, + onboardingDialogVersion: JSON.stringify({ version: 1 }), + onboardingDialogChoice: "dismiss_2", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "dismiss_2", + }, + ], + }); +}); + +// The Escape key should dismiss the dialog without opting in when another +// dialog is queued and shown before the onboarding. This task dismisses the +// other dialog by pressing the Escape key. +add_task(async function escKey_queued_esc() { + await doQueuedEscKeyTest("KEY_Escape"); +}); + +// The Escape key should dismiss the dialog without opting in when another +// dialog is queued and shown before the onboarding. This task dismisses the +// other dialog by pressing the Enter key. +add_task(async function escKey_queued_enter() { + await doQueuedEscKeyTest("KEY_Enter"); +}); + +async function doQueuedEscKeyTest(otherDialogKey) { + await doDialogTest({ + callback: async () => { + // Create promises that will resolve when each dialog is opened. + let uris = [OTHER_DIALOG_URI, QuickSuggest.ONBOARDING_URI]; + let [otherOpenedPromise, onboardingOpenedPromise] = uris.map(uri => + TestUtils.topicObserved( + "subdialog-loaded", + contentWin => contentWin.document.documentURI == uri + ).then(async ([contentWin]) => { + if (contentWin.document.readyState != "complete") { + await BrowserTestUtils.waitForEvent(contentWin, "load"); + } + }) + ); + + info("Queuing dialogs for opening"); + let otherClosedPromise = gDialogBox.open(OTHER_DIALOG_URI); + let onboardingClosedPromise = QuickSuggest.maybeShowOnboardingDialog(); + + info("Waiting for the other dialog to open"); + await otherOpenedPromise; + + info(`Pressing ${otherDialogKey} and waiting for other dialog to close`); + EventUtils.synthesizeKey(otherDialogKey); + await otherClosedPromise; + + info("Waiting for the onboarding dialog to open"); + await onboardingOpenedPromise; + + info("Pressing Escape and waiting for onboarding dialog to close"); + EventUtils.synthesizeKey("KEY_Escape"); + await onboardingClosedPromise; + }, + onboardingDialogVersion: JSON.stringify({ version: 1 }), + onboardingDialogChoice: "dismiss_1", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "dismiss_1", + }, + ], + }); +} + +// Tests `dismissed_other` by closing the dialog programmatically. +add_task(async function dismissed_other_on_introduction() { + await doDialogTest({ + callback: async () => { + const { maybeShowPromise } = await showOnboardingDialog(); + gDialogBox._dialog.close(); + await maybeShowPromise; + }, + onboardingDialogVersion: JSON.stringify({ version: 1 }), + onboardingDialogChoice: "dismiss_1", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "dismiss_1", + }, + ], + }); +}); + +// The default is to wait for no browser restarts to show the onboarding dialog +// on the first restart. This tests that we can override it by configuring the +// `showOnboardingDialogOnNthRestart` +add_task(async function nimbus_override_wait_after_n_restarts() { + UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.seenRestarts", 0); + + await QuickSuggestTestUtils.withExperiment({ + valueOverrides: { + quickSuggestScenario: "online", + // Wait for 1 browser restart + quickSuggestShowOnboardingDialogAfterNRestarts: 1, + }, + callback: async () => { + let prefPromise = TestUtils.waitForPrefChange( + "browser.urlbar.quicksuggest.showedOnboardingDialog", + value => value === true + ).then(() => info("Saw pref change")); + + // Simulate 2 restarts. this function is only called by BrowserGlue + // on startup, the first restart would be where MR1 was shown then + // we will show onboarding the 2nd restart after that. + info("Simulating first restart"); + await QuickSuggest.maybeShowOnboardingDialog(); + + info("Simulating second restart"); + const dialogPromise = BrowserTestUtils.promiseAlertDialogOpen( + null, + QuickSuggest.ONBOARDING_URI, + { isSubDialog: true } + ); + const maybeShowPromise = QuickSuggest.maybeShowOnboardingDialog(); + const win = await dialogPromise; + if (win.document.readyState != "complete") { + await BrowserTestUtils.waitForEvent(win, "load"); + } + // Close dialog. + EventUtils.synthesizeKey("KEY_Escape"); + + info("Waiting for maybeShowPromise and pref change"); + await Promise.all([maybeShowPromise, prefPromise]); + }, + }); +}); + +add_task(async function nimbus_skip_onboarding_dialog() { + UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.seenRestarts", 0); + + await QuickSuggestTestUtils.withExperiment({ + valueOverrides: { + quickSuggestScenario: "online", + quickSuggestShouldShowOnboardingDialog: false, + }, + callback: async () => { + // Simulate 3 restarts. + for (let i = 0; i < 3; i++) { + info(`Simulating restart ${i + 1}`); + await QuickSuggest.maybeShowOnboardingDialog(); + } + Assert.ok( + !Services.prefs.getBoolPref( + "browser.urlbar.quicksuggest.showedOnboardingDialog", + false + ), + "The showed onboarding dialog pref should not be set" + ); + }, + }); +}); + +add_task(async function nimbus_exposure_event() { + const testData = [ + { + experimentType: "modal", + expectedRecorded: true, + }, + { + experimentType: "best-match", + expectedRecorded: false, + }, + { + expectedRecorded: false, + }, + ]; + + for (const { experimentType, expectedRecorded } of testData) { + info(`Nimbus exposure event test for type:[${experimentType}]`); + UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.seenRestarts", 0); + + await QuickSuggestTestUtils.clearExposureEvent(); + + await QuickSuggestTestUtils.withExperiment({ + valueOverrides: { + quickSuggestScenario: "online", + experimentType, + }, + callback: async () => { + info("Calling showOnboardingDialog"); + const { maybeShowPromise } = await showOnboardingDialog(); + EventUtils.synthesizeKey("KEY_Escape"); + await maybeShowPromise; + + info("Check the event"); + await QuickSuggestTestUtils.assertExposureEvent(expectedRecorded); + }, + }); + } +}); + +const LOGO_TYPE = { + FIREFOX: 1, + MAGGLASS: 2, + ANIMATION_MAGGLASS: 3, +}; + +const VARIATION_TEST_DATA = [ + { + name: "A", + introductionSection: { + logoType: LOGO_TYPE.ANIMATION_MAGGLASS, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-1", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + defaultFocusOrder: [ + "onboardingNext", + "onboardingClose", + "onboardingNext", + ], + actions: ["onboardingClose", "onboardingNext"], + }, + mainSection: { + logoType: LOGO_TYPE.MAGGLASS, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-1", + "main-description": "firefox-suggest-onboarding-main-description-1", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-1", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-1", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + defaultFocusOrder: [ + "onboardingNext", + "onboardingAccept", + "onboardingLearnMore", + "onboardingReject", + "onboardingSkipLink", + "onboardingAccept", + ], + acceptFocusOrder: [ + "onboardingAccept", + "onboardingLearnMore", + "onboardingSubmit", + "onboardingSkipLink", + "onboardingAccept", + ], + rejectFocusOrder: [ + "onboardingReject", + "onboardingSubmit", + "onboardingSkipLink", + "onboardingLearnMore", + "onboardingReject", + ], + actions: [ + "onboardingAccept", + "onboardingReject", + "onboardingSkipLink", + "onboardingLearnMore", + ], + }, + }, + { + // We don't need to test the focus order and actions because the layout of + // variation B-H is as same as A. + name: "B", + introductionSection: { + logoType: LOGO_TYPE.ANIMATION_MAGGLASS, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-2", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.MAGGLASS, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-2", + "main-description": "firefox-suggest-onboarding-main-description-2", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-1", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-1", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "C", + introductionSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-3", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-3", + "main-description": "firefox-suggest-onboarding-main-description-3", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-1", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-1", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "D", + introductionSection: { + logoType: LOGO_TYPE.ANIMATION_MAGGLASS, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-4", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.MAGGLASS, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-4", + "main-description": "firefox-suggest-onboarding-main-description-4", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-2", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-2", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "E", + introductionSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-5", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-5", + "main-description": "firefox-suggest-onboarding-main-description-5", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-2", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-2", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "F", + introductionSection: { + logoType: LOGO_TYPE.ANIMATION_MAGGLASS, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-2", + "introduction-title": "firefox-suggest-onboarding-introduction-title-6", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.MAGGLASS, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-6", + "main-description": "firefox-suggest-onboarding-main-description-6", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-2", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-2", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "G", + introductionSection: { + logoType: LOGO_TYPE.ANIMATION_MAGGLASS, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-7", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.MAGGLASS, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-7", + "main-description": "firefox-suggest-onboarding-main-description-7", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-2", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-2", + }, + visibility: { + "#main-privacy-first": true, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "H", + introductionSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1", + "introduction-title": "firefox-suggest-onboarding-introduction-title-2", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": false, + ".description-section": false, + ".pager": true, + }, + }, + mainSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-8", + "main-description": "firefox-suggest-onboarding-main-description-8", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-1", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-1", + }, + visibility: { + "#main-privacy-first": false, + ".description-section #onboardingLearnMore": false, + ".accept #onboardingLearnMore": true, + ".pager": true, + }, + }, + }, + { + name: "100-A", + introductionSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + onboardingNext: "firefox-suggest-onboarding-introduction-next-button-3", + "introduction-title": "firefox-suggest-onboarding-main-title-9", + }, + visibility: { + "#onboardingLearnMoreOnIntroduction": true, + ".description-section": true, + ".pager": true, + }, + defaultFocusOrder: [ + "onboardingNext", + "onboardingLearnMoreOnIntroduction", + "onboardingClose", + "onboardingNext", + ], + actions: [ + "onboardingClose", + "onboardingNext", + "onboardingLearnMoreOnIntroduction", + ], + }, + mainSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-9", + "main-description": "firefox-suggest-onboarding-main-description-9", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label-2", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-3", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label-2", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-3", + }, + visibility: { + "#main-privacy-first": true, + ".description-section #onboardingLearnMore": true, + ".accept #onboardingLearnMore": false, + ".pager": false, + }, + defaultFocusOrder: [ + "onboardingNext", + "onboardingLearnMore", + "onboardingAccept", + "onboardingReject", + "onboardingSkipLink", + "onboardingLearnMore", + ], + acceptFocusOrder: [ + "onboardingAccept", + "onboardingSubmit", + "onboardingSkipLink", + "onboardingLearnMore", + "onboardingAccept", + ], + rejectFocusOrder: [ + "onboardingReject", + "onboardingSubmit", + "onboardingSkipLink", + "onboardingLearnMore", + "onboardingReject", + ], + actions: [ + "onboardingAccept", + "onboardingReject", + "onboardingSkipLink", + "onboardingLearnMore", + ], + }, + }, + { + name: "100-B", + mainSection: { + logoType: LOGO_TYPE.FIREFOX, + l10n: { + "main-title": "firefox-suggest-onboarding-main-title-9", + "main-description": "firefox-suggest-onboarding-main-description-9", + "main-accept-option-label": + "firefox-suggest-onboarding-main-accept-option-label-2", + "main-accept-option-description": + "firefox-suggest-onboarding-main-accept-option-description-3", + "main-reject-option-label": + "firefox-suggest-onboarding-main-reject-option-label-2", + "main-reject-option-description": + "firefox-suggest-onboarding-main-reject-option-description-3", + }, + visibility: { + "#main-privacy-first": true, + ".description-section #onboardingLearnMore": true, + ".accept #onboardingLearnMore": false, + ".pager": false, + }, + // Layout of 100-B is same as 100-A, but since there is no the introduction + // pane, only the default focus order on the main pane is a bit diffrence. + defaultFocusOrder: [ + "onboardingLearnMore", + "onboardingAccept", + "onboardingReject", + "onboardingSkipLink", + "onboardingLearnMore", + ], + }, + }, +]; + +/** + * This test checks for differences due to variations in logo type, l10n text, + * element visibility, order of focus, actions, etc. The designation is on + * VARIATION_TEST_DATA. The items that can be specified are below. + * + * name: Specify the variation name. + * + * The following items are specified for each section. + * (introductionSection, mainSection). + * + * logoType: + * Specify the expected logo type. Please refer to LOGO_TYPE about the type. + * + * l10n: + * Specify the expected l10n id applied to elements. + * + * visibility: + * Specify the expected visibility of elements. The way to specify the element + * is using selector. + * + * defaultFocusOrder: + * Specify the expected focus order right after the section is appeared. The + * way to specify the element is using id. + * + * acceptFocusOrder: + * Specify the expected focus order after selecting accept option. + * + * rejectFocusOrder: + * Specify the expected focus order after selecting reject option. + * + * actions: + * Specify the action we want to verify such as clicking the close button. The + * available actions are below. + * - onboardingClose: + * Action of the close button “x” by mouse/keyboard. + * - onboardingNext: + * Action of the next button that transits from the introduction section to + * the main section by mouse/keyboard. + * - onboardingAccept: + * Action of the submit button by mouse/keyboard after selecting accept + * option by mouse/keyboard. + * - onboardingReject: + * Action of the submit button by mouse/keyboard after selecting reject + * option by mouse/keyboard. + * - onboardingSkipLink: + * Action of the skip link by mouse/keyboard. + * - onboardingLearnMore: + * Action of the learn more link by mouse/keyboard. + * - onboardingLearnMoreOnIntroduction: + * Action of the learn more link on the introduction section by + * mouse/keyboard. + */ +add_task(async function variation_test() { + for (const variation of VARIATION_TEST_DATA) { + info(`Test for variation [${variation.name}]`); + + info("Do layout test"); + await doLayoutTest(variation); + + for (const action of variation.introductionSection?.actions || []) { + info( + `${action} test on the introduction section for variation [${variation.name}]` + ); + await this[action](variation); + } + + for (const action of variation.mainSection?.actions || []) { + info( + `${action} test on the main section for variation [${variation.name}]` + ); + await this[action](variation, !!variation.introductionSection); + } + } +}); + +async function doLayoutTest(variation) { + UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.seenRestarts", 0); + + await QuickSuggestTestUtils.withExperiment({ + valueOverrides: { + quickSuggestScenario: "online", + quickSuggestOnboardingDialogVariation: variation.name, + }, + callback: async () => { + info("Calling showOnboardingDialog"); + const { win, maybeShowPromise } = await showOnboardingDialog(); + + const introductionSection = win.document.getElementById( + "introduction-section" + ); + const mainSection = win.document.getElementById("main-section"); + + if (variation.introductionSection) { + info("Check the section visibility"); + Assert.ok(BrowserTestUtils.is_visible(introductionSection)); + Assert.ok(BrowserTestUtils.is_hidden(mainSection)); + + info("Check the introduction section"); + await assertSection(introductionSection, variation.introductionSection); + + info("Transition to the main section"); + win.document.getElementById("onboardingNext").click(); + await BrowserTestUtils.waitForCondition( + () => + BrowserTestUtils.is_hidden(introductionSection) && + BrowserTestUtils.is_visible(mainSection) + ); + } else { + info("Check the section visibility"); + Assert.ok(BrowserTestUtils.is_hidden(introductionSection)); + Assert.ok(BrowserTestUtils.is_visible(mainSection)); + } + + info("Check the main section"); + await assertSection(mainSection, variation.mainSection); + + info("Close the dialog"); + EventUtils.synthesizeKey("KEY_Escape", {}, win); + await maybeShowPromise; + }, + }); +} + +async function assertSection(sectionElement, expectedSection) { + info("Check the logo"); + assertLogo(sectionElement, expectedSection.logoType); + + info("Check the l10n"); + assertL10N(sectionElement, expectedSection.l10n); + + info("Check the visibility"); + assertVisibility(sectionElement, expectedSection.visibility); + + if (!gCanTabMoveFocus) { + Assert.ok(true, "Tab key can't move focus, skipping test for focus order"); + return; + } + + if (expectedSection.defaultFocusOrder) { + info("Check the default focus order"); + assertFocusOrder(sectionElement, expectedSection.defaultFocusOrder); + } + + if (expectedSection.acceptFocusOrder) { + info("Check the focus order after selecting accept option"); + sectionElement.querySelector("#onboardingAccept").focus(); + EventUtils.synthesizeKey("VK_SPACE", {}, sectionElement.ownerGlobal); + assertFocusOrder(sectionElement, expectedSection.acceptFocusOrder); + } + + if (expectedSection.rejectFocusOrder) { + info("Check the focus order after selecting reject option"); + sectionElement.querySelector("#onboardingReject").focus(); + EventUtils.synthesizeKey("VK_SPACE", {}, sectionElement.ownerGlobal); + assertFocusOrder(sectionElement, expectedSection.rejectFocusOrder); + } +} + +function assertLogo(sectionElement, expectedLogoType) { + let expectedLogoImage; + switch (expectedLogoType) { + case LOGO_TYPE.FIREFOX: { + expectedLogoImage = 'url("chrome://branding/content/about-logo.svg")'; + break; + } + case LOGO_TYPE.MAGGLASS: { + expectedLogoImage = + 'url("chrome://browser/content/urlbar/quicksuggestOnboarding_magglass.svg")'; + break; + } + case LOGO_TYPE.ANIMATION_MAGGLASS: { + const mediaQuery = sectionElement.ownerGlobal.matchMedia( + "(prefers-reduced-motion: no-preference)" + ); + expectedLogoImage = mediaQuery.matches + ? 'url("chrome://browser/content/urlbar/quicksuggestOnboarding_magglass_animation.svg")' + : 'url("chrome://browser/content/urlbar/quicksuggestOnboarding_magglass.svg")'; + break; + } + default: { + Assert.ok(false, `Unexpected image type ${expectedLogoType}`); + break; + } + } + + const logo = sectionElement.querySelector(".logo"); + Assert.ok(BrowserTestUtils.is_visible(logo)); + const logoImage = + sectionElement.ownerGlobal.getComputedStyle(logo).backgroundImage; + Assert.equal(logoImage, expectedLogoImage); +} + +function assertL10N(sectionElement, expectedL10N) { + for (const [id, l10n] of Object.entries(expectedL10N)) { + const element = sectionElement.querySelector("#" + id); + Assert.equal(element.getAttribute("data-l10n-id"), l10n); + } +} + +function assertVisibility(sectionElement, expectedVisibility) { + for (const [selector, visibility] of Object.entries(expectedVisibility)) { + const element = sectionElement.querySelector(selector); + if (visibility) { + Assert.ok(BrowserTestUtils.is_visible(element)); + } else { + if (!element) { + Assert.ok(true); + return; + } + Assert.ok(BrowserTestUtils.is_hidden(element)); + } + } +} + +function assertFocusOrder(sectionElement, expectedFocusOrder) { + const win = sectionElement.ownerGlobal; + + // Check initial active element. + Assert.equal(win.document.activeElement.id, expectedFocusOrder[0]); + + for (const next of expectedFocusOrder.slice(1)) { + EventUtils.synthesizeKey("KEY_Tab", {}, win); + Assert.equal(win.document.activeElement.id, next); + } +} + +async function onboardingClose(variation) { + await doActionTest({ + callback: async (win, userAction, maybeShowPromise) => { + info("Check the status of the close button"); + const closeButton = win.document.getElementById("onboardingClose"); + Assert.ok(BrowserTestUtils.is_visible(closeButton)); + Assert.equal(closeButton.getAttribute("title"), "Close"); + + info("Commit the close button"); + userAction(closeButton); + + info("Waiting for maybeShowOnboardingDialog to finish"); + await maybeShowPromise; + }, + variation, + onboardingDialogVersion: JSON.stringify({ + version: 1, + variation: variation.name.toLowerCase(), + }), + onboardingDialogChoice: "close_1", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "close_1", + }, + ], + }); +} + +async function onboardingNext(variation) { + await doActionTest({ + callback: async (win, userAction, maybeShowPromise) => { + info("Check the status of the next button"); + const nextButton = win.document.getElementById("onboardingNext"); + Assert.ok(BrowserTestUtils.is_visible(nextButton)); + + info("Commit the next button"); + userAction(nextButton); + + const introductionSection = win.document.getElementById( + "introduction-section" + ); + const mainSection = win.document.getElementById("main-section"); + await BrowserTestUtils.waitForCondition( + () => + BrowserTestUtils.is_hidden(introductionSection) && + BrowserTestUtils.is_visible(mainSection), + "Wait for the transition" + ); + + info("Exit"); + EventUtils.synthesizeKey("KEY_Escape", {}, win); + + info("Waiting for maybeShowOnboardingDialog to finish"); + await maybeShowPromise; + }, + variation, + onboardingDialogVersion: JSON.stringify({ + version: 1, + variation: variation.name.toLowerCase(), + }), + onboardingDialogChoice: "dismiss_2", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "dismiss_2", + }, + ], + }); +} + +async function onboardingAccept(variation, skipIntroduction) { + await doActionTest({ + callback: async (win, userAction, maybeShowPromise) => { + info("Check the status of the accept option and submit button"); + const acceptOption = win.document.getElementById("onboardingAccept"); + const submitButton = win.document.getElementById("onboardingSubmit"); + Assert.ok(acceptOption); + Assert.ok(submitButton.disabled); + + info("Select the accept option"); + userAction(acceptOption); + + info("Commit the submit button"); + Assert.ok(!submitButton.disabled); + userAction(submitButton); + + info("Waiting for maybeShowOnboardingDialog to finish"); + await maybeShowPromise; + }, + variation, + skipIntroduction, + onboardingDialogVersion: JSON.stringify({ + version: 1, + variation: variation.name.toLowerCase(), + }), + onboardingDialogChoice: "accept_2", + expectedUserBranchPrefs: { + "quicksuggest.onboardingDialogVersion": JSON.stringify({ version: 1 }), + "quicksuggest.dataCollection.enabled": true, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "enabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "accept_2", + }, + ], + }); +} + +async function onboardingReject(variation, skipIntroduction) { + await doActionTest({ + callback: async (win, userAction, maybeShowPromise) => { + info("Check the status of the reject option and submit button"); + const rejectOption = win.document.getElementById("onboardingReject"); + const submitButton = win.document.getElementById("onboardingSubmit"); + Assert.ok(rejectOption); + Assert.ok(submitButton.disabled); + + info("Select the reject option"); + userAction(rejectOption); + + info("Commit the submit button"); + Assert.ok(!submitButton.disabled); + userAction(submitButton); + + info("Waiting for maybeShowOnboardingDialog to finish"); + await maybeShowPromise; + }, + variation, + skipIntroduction, + onboardingDialogVersion: JSON.stringify({ + version: 1, + variation: variation.name.toLowerCase(), + }), + onboardingDialogChoice: "reject_2", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "reject_2", + }, + ], + }); +} + +async function onboardingSkipLink(variation, skipIntroduction) { + await doActionTest({ + callback: async (win, userAction, maybeShowPromise) => { + info("Check the status of the skip link"); + const skipLink = win.document.getElementById("onboardingSkipLink"); + Assert.ok(BrowserTestUtils.is_visible(skipLink)); + + info("Commit the skip link"); + const tabCount = gBrowser.tabs.length; + userAction(skipLink); + + info("Waiting for maybeShowOnboardingDialog to finish"); + await maybeShowPromise; + + info("Check the current tab status"); + Assert.equal( + gBrowser.currentURI.spec, + "about:blank", + "Nothing loaded in the current tab" + ); + Assert.equal(gBrowser.tabs.length, tabCount, "No news tabs were opened"); + }, + variation, + skipIntroduction, + onboardingDialogVersion: JSON.stringify({ + version: 1, + variation: variation.name.toLowerCase(), + }), + onboardingDialogChoice: "not_now_2", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "not_now_2", + }, + ], + }); +} + +async function onboardingLearnMore(variation, skipIntroduction) { + await doLearnMoreTest( + variation, + skipIntroduction, + "onboardingLearnMore", + "learn_more_2" + ); +} + +async function onboardingLearnMoreOnIntroduction(variation, skipIntroduction) { + await doLearnMoreTest( + variation, + skipIntroduction, + "onboardingLearnMoreOnIntroduction", + "learn_more_1" + ); +} + +async function doLearnMoreTest(variation, skipIntroduction, target, telemetry) { + await doActionTest({ + callback: async (win, userAction, maybeShowPromise) => { + info("Check the status of the learn more link"); + const learnMoreLink = win.document.getElementById(target); + Assert.ok(BrowserTestUtils.is_visible(learnMoreLink)); + + info("Commit the learn more link"); + const loadPromise = BrowserTestUtils.waitForNewTab( + gBrowser, + QuickSuggest.HELP_URL + ).then(tab => { + info("Saw new tab"); + return tab; + }); + userAction(learnMoreLink); + + info("Waiting for maybeShowOnboardingDialog to finish"); + await maybeShowPromise; + + info("Waiting for new tab"); + let tab = await loadPromise; + + info("Check the current tab status"); + Assert.equal(gBrowser.selectedTab, tab, "Current tab is the new tab"); + Assert.equal( + gBrowser.currentURI.spec, + QuickSuggest.HELP_URL, + "Current tab is the support page" + ); + BrowserTestUtils.removeTab(tab); + }, + variation, + skipIntroduction, + onboardingDialogChoice: telemetry, + onboardingDialogVersion: JSON.stringify({ + version: 1, + variation: variation.name.toLowerCase(), + }), + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: telemetry, + }, + ], + }); +} + +async function doActionTest({ + variation, + skipIntroduction, + callback, + onboardingDialogVersion, + onboardingDialogChoice, + expectedUserBranchPrefs, + telemetryEvents, +}) { + const userClick = target => { + info("Click on the target"); + target.click(); + }; + const userEnter = target => { + target.focus(); + if (target.type === "radio") { + info("Space on the target"); + EventUtils.synthesizeKey("VK_SPACE", {}, target.ownerGlobal); + } else { + info("Enter on the target"); + EventUtils.synthesizeKey("KEY_Enter", {}, target.ownerGlobal); + } + }; + + for (const userAction of [userClick, userEnter]) { + UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog"); + UrlbarPrefs.clear("quicksuggest.seenRestarts", 0); + + await QuickSuggestTestUtils.withExperiment({ + valueOverrides: { + quickSuggestScenario: "online", + quickSuggestOnboardingDialogVariation: variation.name, + }, + callback: async () => { + await doDialogTest({ + callback: async () => { + info("Calling showOnboardingDialog"); + const { win, maybeShowPromise } = await showOnboardingDialog({ + skipIntroduction, + }); + + await callback(win, userAction, maybeShowPromise); + }, + onboardingDialogVersion, + onboardingDialogChoice, + expectedUserBranchPrefs, + telemetryEvents, + }); + }, + }); + } +} + +async function doDialogTest({ + callback, + onboardingDialogVersion, + onboardingDialogChoice, + telemetryEvents, + expectedUserBranchPrefs, +}) { + setDialogPrereqPrefs(); + + // Set initial prefs on the default branch. + let initialDefaultBranch = OFFLINE_DEFAULT_PREFS; + let originalDefaultBranch = {}; + for (let [name, value] of Object.entries(initialDefaultBranch)) { + originalDefaultBranch = gDefaultBranch.getBoolPref(name); + gDefaultBranch.setBoolPref(name, value); + gUserBranch.clearUserPref(name); + } + + // Setting the prefs just now triggered telemetry events, so clear them + // before calling the callback. + Services.telemetry.clearEvents(); + + // Call the callback, which should trigger the dialog and interact with it. + await BrowserTestUtils.withNewTab("about:blank", async () => { + await callback(); + }); + + // Now check all pref values on the default and user branches. + for (let [name, value] of Object.entries(initialDefaultBranch)) { + Assert.equal( + gDefaultBranch.getBoolPref(name), + value, + "Default-branch value for pref did not change after modal: " + name + ); + + let effectiveValue; + if (name in expectedUserBranchPrefs) { + effectiveValue = expectedUserBranchPrefs[name]; + Assert.equal( + gUserBranch.getBoolPref(name), + effectiveValue, + "User-branch value for pref has expected value: " + name + ); + } else { + effectiveValue = value; + Assert.ok( + !gUserBranch.prefHasUserValue(name), + "User-branch value for pref does not exist: " + name + ); + } + + // For good measure, check the value returned by UrlbarPrefs. + Assert.equal( + UrlbarPrefs.get(name), + effectiveValue, + "Effective value for pref is correct: " + name + ); + } + + Assert.equal( + UrlbarPrefs.get("quicksuggest.onboardingDialogVersion"), + onboardingDialogVersion, + "onboardingDialogVersion" + ); + Assert.equal( + UrlbarPrefs.get("quicksuggest.onboardingDialogChoice"), + onboardingDialogChoice, + "onboardingDialogChoice" + ); + Assert.equal( + TelemetryEnvironment.currentEnvironment.settings.userPrefs[ + "browser.urlbar.quicksuggest.onboardingDialogChoice" + ], + onboardingDialogChoice, + "onboardingDialogChoice is correct in TelemetryEnvironment" + ); + + QuickSuggestTestUtils.assertEvents(telemetryEvents); + + Assert.ok( + UrlbarPrefs.get("quicksuggest.showedOnboardingDialog"), + "quicksuggest.showedOnboardingDialog is true after showing dialog" + ); + + // Clean up. + for (let [name, value] of Object.entries(originalDefaultBranch)) { + gDefaultBranch.setBoolPref(name, value); + } + for (let name of Object.keys(expectedUserBranchPrefs)) { + gUserBranch.clearUserPref(name); + } +} + +/** + * Show onbaording dialog. + * + * @param {object} [options] + * The object options. + * @param {boolean} [options.skipIntroduction] + * If true, return dialog with skipping the introduction section. + * @returns {{ window, maybeShowPromise: Promise }} + * win: window object of the dialog. + * maybeShowPromise: Promise of QuickSuggest.maybeShowOnboardingDialog(). + */ +async function showOnboardingDialog({ skipIntroduction } = {}) { + const dialogPromise = BrowserTestUtils.promiseAlertDialogOpen( + null, + QuickSuggest.ONBOARDING_URI, + { isSubDialog: true } + ); + + const maybeShowPromise = QuickSuggest.maybeShowOnboardingDialog(); + + const win = await dialogPromise; + if (win.document.readyState != "complete") { + await BrowserTestUtils.waitForEvent(win, "load"); + } + + // Wait until all listers on onboarding dialog are ready. + await window._quicksuggestOnboardingReady; + + if (!skipIntroduction) { + return { win, maybeShowPromise }; + } + + // Trigger the transition by pressing Enter on the Next button. + EventUtils.synthesizeKey("KEY_Enter"); + + const introductionSection = win.document.getElementById( + "introduction-section" + ); + const mainSection = win.document.getElementById("main-section"); + + await BrowserTestUtils.waitForCondition( + () => + BrowserTestUtils.is_hidden(introductionSection) && + BrowserTestUtils.is_visible(mainSection) + ); + + return { win, maybeShowPromise }; +} + +/** + * Sets all the required prefs for showing the onboarding dialog except for the + * prefs that are set when the dialog is accepted. + */ +function setDialogPrereqPrefs() { + UrlbarPrefs.set("quicksuggest.shouldShowOnboardingDialog", true); + UrlbarPrefs.set("quicksuggest.showedOnboardingDialog", false); +} + +/** + * This is a real hacky way of determining whether the tab key can move focus. + * Windows and Linux both support it but macOS does not unless full keyboard + * access is enabled, so practically this is only useful on macOS. Gecko seems + * to know whether full keyboard access is enabled because it affects focus in + * Firefox and some code in nsXULElement.cpp and other places mention it, but + * there doesn't seem to be a way to access that information from JS. There is + * `Services.focus.elementIsFocusable`, but it returns true regardless of + * whether full access is enabled. + * + * So what we do here is open the dialog and synthesize a tab key. If the focus + * doesn't change, then we assume moving the focus via the tab key is not + * supported. + * + * Why not just always skip the focus tasks on Mac? Because individual + * developers (like the one writing this comment) may be running macOS with full + * keyboard access enabled and want to actually run the tasks on their machines. + * + * @returns {boolean} + */ +async function canTabMoveFocus() { + if (AppConstants.platform != "macosx") { + return true; + } + + let canMove = false; + await doDialogTest({ + callback: async () => { + const { win, maybeShowPromise } = await showOnboardingDialog({ + skipIntroduction: true, + }); + + let doc = win.document; + doc.getElementById("onboardingAccept").focus(); + EventUtils.synthesizeKey("KEY_Tab"); + + // Whether or not the focus can move to the link. + canMove = doc.activeElement.id === "onboardingLearnMore"; + + EventUtils.synthesizeKey("KEY_Escape"); + await maybeShowPromise; + }, + onboardingDialogVersion: JSON.stringify({ version: 1 }), + onboardingDialogChoice: "dismiss_2", + expectedUserBranchPrefs: { + "quicksuggest.dataCollection.enabled": false, + }, + telemetryEvents: [ + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "data_collect_toggled", + object: "disabled", + }, + { + category: QuickSuggest.TELEMETRY_EVENT_CATEGORY, + method: "opt_in_dialog", + object: "dismiss_2", + }, + ], + }); + + return canMove; +} |