summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/browser/browser_searchMode_sessionStore.js
blob: ef3fabe6364fba852e2f05c3086f135d33c23a91 (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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

/**
 * Tests search mode and session store.  Also tests that search mode is
 * duplicated when duplicating tabs, since tab duplication is handled by session
 * store.
 */

"use strict";

ChromeUtils.defineESModuleGetters(this, {
  SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
  TabStateFlusher: "resource:///modules/sessionstore/TabStateFlusher.sys.mjs",
});

// This test takes a long time on the OS X 10.14 machines, so request a longer
// timeout.  See bug 1671045.  This may also fix a different failure on Linux in
// bug 1671087, but it's not clear.  Regardless, a longer timeout won't hurt.
requestLongerTimeout(5);

const SEARCH_STRING = "test browser_sessionStore.js";
const URL = "http://example.com/";

// A URL in gInitialPages.  We test this separately since SessionStore sometimes
// takes different paths for these URLs.
const INITIAL_URL = "about:newtab";

// The following tasks make sure non-null search mode is restored.

add_task(async function initialPageOnRestore() {
  await doTest({
    urls: [INITIAL_URL],
    searchModeTabIndex: 0,
    exitSearchMode: false,
    switchTabsAfterEnteringSearchMode: false,
  });
});

add_task(async function switchToInitialPage() {
  await doTest({
    urls: [URL, INITIAL_URL],
    searchModeTabIndex: 1,
    exitSearchMode: false,
    switchTabsAfterEnteringSearchMode: true,
  });
});

add_task(async function nonInitialPageOnRestore() {
  await doTest({
    urls: [URL],
    searchModeTabIndex: 0,
    exitSearchMode: false,
    switchTabsAfterEnteringSearchMode: false,
  });
});

add_task(async function switchToNonInitialPage() {
  await doTest({
    urls: [INITIAL_URL, URL],
    searchModeTabIndex: 1,
    exitSearchMode: false,
    switchTabsAfterEnteringSearchMode: true,
  });
});

// The following tasks enter and then exit search mode to make sure that no
// search mode is restored.

add_task(async function initialPageOnRestore_exit() {
  await doTest({
    urls: [INITIAL_URL],
    searchModeTabIndex: 0,
    exitSearchMode: true,
    switchTabsAfterEnteringSearchMode: false,
  });
});

add_task(async function switchToInitialPage_exit() {
  await doTest({
    urls: [URL, INITIAL_URL],
    searchModeTabIndex: 1,
    exitSearchMode: true,
    switchTabsAfterEnteringSearchMode: true,
  });
});

add_task(async function nonInitialPageOnRestore_exit() {
  await doTest({
    urls: [URL],
    searchModeTabIndex: 0,
    exitSearchMode: true,
    switchTabsAfterEnteringSearchMode: false,
  });
});

add_task(async function switchToNonInitialPage_exit() {
  await doTest({
    urls: [INITIAL_URL, URL],
    searchModeTabIndex: 1,
    exitSearchMode: true,
    switchTabsAfterEnteringSearchMode: true,
  });
});

/**
 * The main test function.  Opens some URLs in a new window, enters search mode
 * in one of the tabs, closes the window, restores it, and makes sure that
 * search mode is restored properly.
 *
 * @param {object} options
 *   Options object
 * @param {Array} options.urls
 *   Array of string URLs to open.
 * @param {number} options.searchModeTabIndex
 *   The index of the tab in which to enter search mode.
 * @param {boolean} options.exitSearchMode
 *   If true, search mode will be immediately exited after entering it.  Use
 *   this to make sure search mode is *not* restored after it's exited.
 * @param {boolean} options.switchTabsAfterEnteringSearchMode
 *   If true, we'll switch to a tab other than the one that search mode was
 *   entered in before closing the window.  `urls` should contain more than one
 *   URL in this case.
 */
async function doTest({
  urls,
  searchModeTabIndex,
  exitSearchMode,
  switchTabsAfterEnteringSearchMode,
}) {
  let searchModeURL = urls[searchModeTabIndex];
  let otherTabIndex = (searchModeTabIndex + 1) % urls.length;
  let otherURL = urls[otherTabIndex];

  await withNewWindow(urls, async win => {
    if (win.gBrowser.selectedTab != win.gBrowser.tabs[searchModeTabIndex]) {
      await BrowserTestUtils.switchTab(
        win.gBrowser,
        win.gBrowser.tabs[searchModeTabIndex]
      );
    }

    Assert.equal(
      win.gBrowser.currentURI.spec,
      searchModeURL,
      `Sanity check: Tab at index ${searchModeTabIndex} is correct`
    );
    Assert.equal(
      searchModeURL == INITIAL_URL,
      win.gInitialPages.includes(win.gBrowser.currentURI.spec),
      `Sanity check: ${searchModeURL} is or is not in gInitialPages as expected`
    );

    await UrlbarTestUtils.promiseAutocompleteResultPopup({
      window: win,
      value: SEARCH_STRING,
      fireInputEvent: true,
    });
    await UrlbarTestUtils.enterSearchMode(win, {
      source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
    });

    if (exitSearchMode) {
      await UrlbarTestUtils.exitSearchMode(win);
    }

    // Make sure session store is updated.
    await TabStateFlusher.flush(win.gBrowser.selectedBrowser);

    if (switchTabsAfterEnteringSearchMode) {
      await BrowserTestUtils.switchTab(
        win.gBrowser,
        win.gBrowser.tabs[otherTabIndex]
      );
    }
  });

  let restoredURL = switchTabsAfterEnteringSearchMode
    ? otherURL
    : searchModeURL;

  let win = await restoreWindow(restoredURL);

  Assert.equal(
    win.gBrowser.currentURI.spec,
    restoredURL,
    "Sanity check: Initially selected tab in restored window is correct"
  );

  if (switchTabsAfterEnteringSearchMode) {
    // Switch back to the tab with search mode.
    await BrowserTestUtils.switchTab(
      win.gBrowser,
      win.gBrowser.tabs[searchModeTabIndex]
    );
  }

  if (exitSearchMode) {
    // If we exited search mode, it should be null.
    await new Promise(r => win.setTimeout(r, 500));
    await UrlbarTestUtils.assertSearchMode(win, null);
  } else {
    // If we didn't exit search mode, it should be restored.
    await TestUtils.waitForCondition(
      () => win.gURLBar.searchMode,
      "Waiting for search mode to be restored"
    );
    await UrlbarTestUtils.assertSearchMode(win, {
      source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
      entry: "oneoff",
    });
    Assert.equal(
      win.gURLBar.value,
      SEARCH_STRING,
      "Search string should be restored"
    );
  }

  await BrowserTestUtils.closeWindow(win);
}

async function openTabMenuFor(tab) {
  let tabMenu = tab.ownerDocument.getElementById("tabContextMenu");

  let tabMenuShown = BrowserTestUtils.waitForEvent(tabMenu, "popupshown");
  EventUtils.synthesizeMouseAtCenter(
    tab,
    { type: "contextmenu" },
    tab.ownerGlobal
  );
  await tabMenuShown;

  return tabMenu;
}

// Tests that search mode is duplicated when duplicating tabs.  Note that tab
// duplication is handled by session store.
add_task(async function duplicateTabs() {
  let tab = await BrowserTestUtils.openNewForegroundTab(
    gBrowser,
    "http://example.net/"
  );
  gBrowser.selectedTab = tab;
  // Enter search mode with a search string in the current tab.
  await UrlbarTestUtils.promiseAutocompleteResultPopup({
    window,
    value: SEARCH_STRING,
    fireInputEvent: true,
  });
  await UrlbarTestUtils.enterSearchMode(window, {
    source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
  });

  // Now duplicate the current tab using the context menu item.
  const menu = await openTabMenuFor(gBrowser.selectedTab);
  let tabPromise = BrowserTestUtils.waitForNewTab(
    gBrowser,
    gBrowser.currentURI.spec
  );
  menu.activateItem(document.getElementById("context_duplicateTab"));
  let newTab = await tabPromise;
  Assert.equal(
    gBrowser.selectedTab,
    newTab,
    "Sanity check: The duplicated tab is now the selected tab"
  );

  // Wait for search mode, then check it and the input value.
  await TestUtils.waitForCondition(
    () => gURLBar.searchMode,
    "Waiting for search mode to be duplicated/restored"
  );
  await UrlbarTestUtils.assertSearchMode(window, {
    source: UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
    entry: "oneoff",
  });
  Assert.equal(
    gURLBar.value,
    SEARCH_STRING,
    "Search string should be duplicated/restored"
  );

  BrowserTestUtils.removeTab(tab);
  BrowserTestUtils.removeTab(newTab);
  gURLBar.handleRevert();
});

/**
 * Opens a new browser window with the given URLs, calls a callback, and then
 * closes the window.
 *
 * @param {Array} urls
 *   Array of string URLs to open.
 * @param {Function} callback
 *   The callback.
 */
async function withNewWindow(urls, callback) {
  let win = await BrowserTestUtils.openNewBrowserWindow();
  for (let url of urls) {
    await BrowserTestUtils.openNewForegroundTab({
      url,
      gBrowser: win.gBrowser,
      waitForLoad: url != "about:newtab",
    });
    if (url == "about:newtab") {
      await TestUtils.waitForCondition(
        () => win.gBrowser.currentURI.spec == "about:newtab",
        "Waiting for about:newtab"
      );
    }
  }
  BrowserTestUtils.removeTab(win.gBrowser.tabs[0]);
  await callback(win);
  await BrowserTestUtils.closeWindow(win);
}

/**
 * Uses SessionStore to reopen the last closed window.
 *
 * @param {string} expectedRestoredURL
 *   The URL you expect will be restored in the selected browser.
 */
async function restoreWindow(expectedRestoredURL) {
  let winPromise = BrowserTestUtils.waitForNewWindow();
  let win = SessionStore.undoCloseWindow(0);
  await winPromise;
  await TestUtils.waitForCondition(
    () => win.gBrowser.currentURI.spec == expectedRestoredURL,
    "Waiting for restored selected browser to have expected URI"
  );
  return win;
}