summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/browser-tips/browser_picks.js
blob: 60a7676668e60fc59f365163dd427a167623c955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/* 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",
      },
    }
  );
}