зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1290280 - Add tests for window state restoration remoteness flips. r=mikedeboer
MozReview-Commit-ID: ARtmju65xR9 --HG-- extra : rebase_source : 8a1466e01be4f1af69f2efe5611c59c4f4649501
This commit is contained in:
Родитель
f5ae3a058b
Коммит
c40ae43473
|
@ -229,3 +229,5 @@ run-if = e10s
|
|||
[browser_sessionStoreContainer.js]
|
||||
[browser_windowStateContainer.js]
|
||||
[browser_1234021.js]
|
||||
[browser_remoteness_flip_on_restore.js]
|
||||
run-if = e10s
|
||||
|
|
|
@ -0,0 +1,324 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* This set of tests checks that the remoteness is properly
|
||||
* set for each browser in a window when that window has
|
||||
* session state loaded into it.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Takes a SessionStore window state object for a single
|
||||
* window, sets the selected tab for it, and then returns
|
||||
* the object to be passed to SessionStore.setWindowState.
|
||||
*
|
||||
* @param state (object)
|
||||
* The state to prepare to be sent to a window. This is
|
||||
* state should just be for a single window.
|
||||
* @param selected (int)
|
||||
* The 1-based index of the selected tab. Note that
|
||||
* If this is 0, then the selected tab will not change
|
||||
* from what's already selected in the window that we're
|
||||
* sending state to.
|
||||
* @returns (object)
|
||||
* The JSON encoded string to call
|
||||
* SessionStore.setWindowState with.
|
||||
*/
|
||||
function prepareState(state, selected) {
|
||||
// We'll create a copy so that we don't accidentally
|
||||
// modify the caller's selected property.
|
||||
let copy = {};
|
||||
Object.assign(copy, state);
|
||||
copy.selected = selected;
|
||||
|
||||
return {
|
||||
windows: [ copy ],
|
||||
};
|
||||
}
|
||||
|
||||
const SIMPLE_STATE = {
|
||||
tabs: [
|
||||
{ entries: [{ url: "http://example.com/", title: "title" }] },
|
||||
{ entries: [{ url: "http://example.com/", title: "title" }] },
|
||||
{ entries: [{ url: "http://example.com/", title: "title" }] },
|
||||
],
|
||||
title: "",
|
||||
_closedTabs: [],
|
||||
};
|
||||
|
||||
const PINNED_STATE = {
|
||||
tabs: [
|
||||
{ entries: [{ url: "http://example.com/", title: "title" }], pinned: true },
|
||||
{ entries: [{ url: "http://example.com/", title: "title" }], pinned: true },
|
||||
{ entries: [{ url: "http://example.com/", title: "title" }] },
|
||||
],
|
||||
title: "",
|
||||
_closedTabs: [],
|
||||
};
|
||||
|
||||
/**
|
||||
* This is where most of the action is happening. This function takes
|
||||
* an Array of "test scenario" Objects and runs them. For each scenario, a
|
||||
* window is opened, put into some state, and then a new state is
|
||||
* loaded into that window. We then check to make sure that the
|
||||
* right things have happened in that window wrt remoteness flips.
|
||||
*
|
||||
* The schema for a testing scenario Object is as follows:
|
||||
*
|
||||
* initialRemoteness:
|
||||
* an Array that represents the starting window. Each bool
|
||||
* in the Array represents the window tabs in order. A "true"
|
||||
* indicates that that tab should be remote. "false" if the tab
|
||||
* should be non-remote.
|
||||
*
|
||||
* initialSelectedTab:
|
||||
* The 1-based index of the tab that we want to select for the
|
||||
* restored window. This is 1-based to avoid confusion with the
|
||||
* selectedTab property described down below, though you probably
|
||||
* want to set this to be greater than 0, since the initial window
|
||||
* needs to have a defined initial selected tab. Because of this,
|
||||
* the test will throw if initialSelectedTab is 0.
|
||||
*
|
||||
* stateToRestore:
|
||||
* A JS Object for the state to send down to the window.
|
||||
*
|
||||
* selectedTab:
|
||||
* The 1-based index of the tab that we want to select for the
|
||||
* restored window. Leave this at 0 if you don't want to change
|
||||
* the selection from the initial window state.
|
||||
*
|
||||
* expectedFlips:
|
||||
* an Array that represents the window that we end up with after
|
||||
* restoring state. Each bool in the Array represents the window tabs,
|
||||
* in order. A "true" indicates that the tab should have flipped
|
||||
* its remoteness once. "false" indicates that the tab should never
|
||||
* have flipped remoteness. Note that any tab that flips its remoteness
|
||||
* more than once will cause a test failure.
|
||||
*
|
||||
* expectedRemoteness:
|
||||
* an Array that represents the window that we end up with after
|
||||
* restoring state. Each bool in the Array represents the window
|
||||
* tabs in order. A "true" indicates that the tab be remote, and
|
||||
* a "false" indicates that the tab should be "non-remote". We
|
||||
* need this Array in order to test pinned tabs which will also
|
||||
* be loaded by default, and therefore should end up remote.
|
||||
*
|
||||
*/
|
||||
function* runScenarios(scenarios) {
|
||||
for (let scenario of scenarios) {
|
||||
// Let's make sure our scenario is sane first.
|
||||
Assert.equal(scenario.expectedFlips.length,
|
||||
scenario.expectedRemoteness.length,
|
||||
"All expected flips and remoteness needs to be supplied");
|
||||
Assert.ok(scenario.initialSelectedTab > 0,
|
||||
"You must define an initially selected tab");
|
||||
|
||||
// First, we need to create the initial conditions, so we
|
||||
// open a new window to put into our starting state...
|
||||
let win = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
let tabbrowser = win.gBrowser;
|
||||
Assert.ok(tabbrowser.selectedBrowser.isRemoteBrowser,
|
||||
"The initial browser should be remote.");
|
||||
// Now put the window into the expected initial state.
|
||||
for (let i = 0; i < scenario.initialRemoteness.length; ++i) {
|
||||
let tab;
|
||||
if (i > 0) {
|
||||
// The window starts with one tab, so we need to create
|
||||
// any of the additional ones required by this test.
|
||||
info("Opening a new tab");
|
||||
tab = yield BrowserTestUtils.openNewForegroundTab(tabbrowser)
|
||||
} else {
|
||||
info("Using the selected tab");
|
||||
tab = tabbrowser.selectedTab;
|
||||
}
|
||||
let browser = tab.linkedBrowser;
|
||||
let remotenessState = scenario.initialRemoteness[i];
|
||||
tabbrowser.updateBrowserRemoteness(browser, remotenessState);
|
||||
}
|
||||
|
||||
// And select the requested tab.
|
||||
let tabToSelect = tabbrowser.tabs[scenario.initialSelectedTab - 1];
|
||||
if (tabbrowser.selectedTab != tabToSelect) {
|
||||
yield BrowserTestUtils.switchTab(tabbrowser, tabToSelect);
|
||||
}
|
||||
|
||||
// Hook up an event listener to make sure that the right
|
||||
// tabs flip remoteness, and only once.
|
||||
let flipListener = {
|
||||
seenTabs: new Set(),
|
||||
handleEvent(e) {
|
||||
let index = Array.from(tabbrowser.tabs).indexOf(e.target);
|
||||
info(`Saw a tab at index ${index} flip remoteness`);
|
||||
if (this.seenTabs.has(e.target)) {
|
||||
Assert.ok(false, "Saw a tab flip remoteness more than once");
|
||||
}
|
||||
this.seenTabs.add(e.target);
|
||||
},
|
||||
};
|
||||
|
||||
win.addEventListener("TabRemotenessChange", flipListener);
|
||||
|
||||
// Okay, time to test!
|
||||
let state = prepareState(scenario.stateToRestore,
|
||||
scenario.selectedTab);
|
||||
|
||||
SessionStore.setWindowState(win, state, true);
|
||||
|
||||
win.removeEventListener("TabRemotenessChange", flipListener);
|
||||
|
||||
// Because we know that scenario.expectedFlips and
|
||||
// scenario.expectedRemoteness have the same length, we
|
||||
// can check that we satisfied both with the same loop.
|
||||
for (let i = 0; i < scenario.expectedFlips.length; ++i) {
|
||||
let expectedToFlip = scenario.expectedFlips[i];
|
||||
let expectedRemoteness = scenario.expectedRemoteness[i];
|
||||
let tab = tabbrowser.tabs[i];
|
||||
if (expectedToFlip) {
|
||||
Assert.ok(flipListener.seenTabs.has(tab),
|
||||
`We should have seen tab at index ${i} flip remoteness`);
|
||||
} else {
|
||||
Assert.ok(!flipListener.seenTabs.has(tab),
|
||||
`We should not have seen tab at index ${i} flip remoteness`);
|
||||
}
|
||||
|
||||
Assert.equal(tab.linkedBrowser.isRemoteBrowser, expectedRemoteness,
|
||||
"Should have gotten the expected remoteness " +
|
||||
`for the tab at index ${i}`);
|
||||
}
|
||||
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that if we restore state to browser windows with
|
||||
* a variety of initial remoteness states, that we only flip
|
||||
* the remoteness on the necessary tabs. For this particular
|
||||
* set of tests, we assume that tabs are restoring on demand.
|
||||
*/
|
||||
add_task(function*() {
|
||||
// This test opens and closes windows, which might bog down
|
||||
// a debug build long enough to time out the test, so we
|
||||
// extend the tolerance on timeouts.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
"set": [["browser.sessionstore.restore_on_demand", true]],
|
||||
});
|
||||
|
||||
const TEST_SCENARIOS = [
|
||||
// Only one tab in the new window, and it's remote. This
|
||||
// is the common case, since this is how restoration occurs
|
||||
// when the restored window is being opened.
|
||||
{
|
||||
initialRemoteness: [true],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: SIMPLE_STATE,
|
||||
selectedTab: 3,
|
||||
// The initial tab is remote and should go into
|
||||
// the background state. The second and third tabs
|
||||
// are new and should be initialized non-remote.
|
||||
expectedFlips: [true, false, true],
|
||||
// Only the selected tab should be remote.
|
||||
expectedRemoteness: [false, false, true],
|
||||
},
|
||||
|
||||
// A single remote tab, and this is the one that's going
|
||||
// to be selected once state is restored.
|
||||
{
|
||||
initialRemoteness: [true],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: SIMPLE_STATE,
|
||||
selectedTab: 1,
|
||||
// The initial tab is remote and selected, so it should
|
||||
// not flip remoteness. The other two new tabs should
|
||||
// be non-remote by default.
|
||||
expectedFlips: [false, false, false],
|
||||
// Only the selected tab should be remote.
|
||||
expectedRemoteness: [true, false, false],
|
||||
},
|
||||
|
||||
// A single remote tab which starts selected. We set the
|
||||
// selectedTab to 0 which is equivalent to "don't change
|
||||
// the tab selection in the window".
|
||||
{
|
||||
initialRemoteness: [true],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: SIMPLE_STATE,
|
||||
selectedTab: 0,
|
||||
// The initial tab is remote and selected, so it should
|
||||
// not flip remoteness. The other two new tabs should
|
||||
// be non-remote by default.
|
||||
expectedFlips: [false, false, false],
|
||||
// Only the selected tab should be remote.
|
||||
expectedRemoteness: [true, false, false],
|
||||
},
|
||||
|
||||
// An initially remote tab, but we're going to load
|
||||
// some pinned tabs now, and the pinned tabs should load
|
||||
// right away.
|
||||
{
|
||||
initialRemoteness: [true],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: PINNED_STATE,
|
||||
selectedTab: 3,
|
||||
// The initial tab is pinned and will load right away,
|
||||
// so it should stay remote. The second tab is new
|
||||
// and pinned, so it should start remote and not flip.
|
||||
// The third tab is not pinned, but it is selected,
|
||||
// so it will start non-remote, and then flip remoteness.
|
||||
expectedFlips: [false, false, true],
|
||||
// Both pinned tabs and the selected tabs should all
|
||||
// end up being remote.
|
||||
expectedRemoteness: [true, true, true],
|
||||
},
|
||||
|
||||
// A single non-remote tab.
|
||||
{
|
||||
initialRemoteness: [false],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: SIMPLE_STATE,
|
||||
selectedTab: 2,
|
||||
// The initial tab is non-remote and should stay
|
||||
// that way. The second and third tabs are new and
|
||||
// should be initialized non-remote.
|
||||
expectedFlips: [false, true, false],
|
||||
// Only the selected tab should be remote.
|
||||
expectedRemoteness: [false, true, false],
|
||||
},
|
||||
|
||||
// A mixture of remote and non-remote tabs.
|
||||
{
|
||||
initialRemoteness: [true, false, true],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: SIMPLE_STATE,
|
||||
selectedTab: 3,
|
||||
// The initial tab is remote and should flip to non-remote
|
||||
// as it is put into the background. The second tab should
|
||||
// stay non-remote, and the third one should stay remote.
|
||||
expectedFlips: [true, false, false],
|
||||
// Only the selected tab should be remote.
|
||||
expectedRemoteness: [false, false, true],
|
||||
},
|
||||
|
||||
// An initially non-remote tab, but we're going to load
|
||||
// some pinned tabs now, and the pinned tabs should load
|
||||
// right away.
|
||||
{
|
||||
initialRemoteness: [false],
|
||||
initialSelectedTab: 1,
|
||||
stateToRestore: PINNED_STATE,
|
||||
selectedTab: 3,
|
||||
// The initial tab is pinned and will load right away,
|
||||
// so it should flip remoteness. The second tab is new
|
||||
// and pinned, so it should start remote and not flip.
|
||||
// The third tab is not pinned, but it is selected,
|
||||
// so it will start non-remote, and then flip remoteness.
|
||||
expectedFlips: [true, false, true],
|
||||
// Both pinned tabs and the selected tabs should all
|
||||
// end up being remote.
|
||||
expectedRemoteness: [true, true, true],
|
||||
},
|
||||
];
|
||||
|
||||
yield* runScenarios(TEST_SCENARIOS);
|
||||
});
|
Загрузка…
Ссылка в новой задаче