diff options
Diffstat (limited to 'addon-sdk/source/test/addons/e10s-tabs/lib')
6 files changed, 552 insertions, 0 deletions
diff --git a/addon-sdk/source/test/addons/e10s-tabs/lib/main.js b/addon-sdk/source/test/addons/e10s-tabs/lib/main.js new file mode 100644 index 000000000..09ccf5008 --- /dev/null +++ b/addon-sdk/source/test/addons/e10s-tabs/lib/main.js @@ -0,0 +1,23 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { merge } = require('sdk/util/object'); +const { version } = require('sdk/system'); + +const SKIPPING_TESTS = { + "test skip": (assert) => assert.pass("nothing to test here") +}; + +merge(module.exports, require('./test-tab')); +merge(module.exports, require('./test-tab-events')); +merge(module.exports, require('./test-tab-observer')); +merge(module.exports, require('./test-tab-utils')); + +// run e10s tests only on builds from trunk, fx-team, Nightly.. +if (!version.endsWith('a1')) { + module.exports = SKIPPING_TESTS; +} + +require('sdk/test/runner').runTestsFromModule(module); diff --git a/addon-sdk/source/test/addons/e10s-tabs/lib/private-browsing/helper.js b/addon-sdk/source/test/addons/e10s-tabs/lib/private-browsing/helper.js new file mode 100644 index 000000000..f581c92c0 --- /dev/null +++ b/addon-sdk/source/test/addons/e10s-tabs/lib/private-browsing/helper.js @@ -0,0 +1,91 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { Loader } = require('sdk/test/loader'); + +const { loader } = LoaderWithHookedConsole(module); + +const pb = loader.require('sdk/private-browsing'); +const pbUtils = loader.require('sdk/private-browsing/utils'); +const xulApp = require("sdk/system/xul-app"); +const { open: openWindow, getMostRecentBrowserWindow } = require('sdk/window/utils'); +const { openTab, getTabContentWindow, getActiveTab, setTabURL, closeTab } = require('sdk/tabs/utils'); +const promise = require("sdk/core/promise"); +const windowHelpers = require('sdk/window/helpers'); +const events = require("sdk/system/events"); + +function LoaderWithHookedConsole(module) { + let globals = {}; + let errors = []; + + globals.console = Object.create(console, { + error: { + value: function(e) { + errors.push(e); + if (!/DEPRECATED:/.test(e)) { + console.error(e); + } + } + } + }); + + let loader = Loader(module, globals); + + return { + loader: loader, + errors: errors + } +} + +exports.pb = pb; +exports.pbUtils = pbUtils; +exports.LoaderWithHookedConsole = LoaderWithHookedConsole; + +exports.openWebpage = function openWebpage(url, enablePrivate) { + if (xulApp.is("Fennec")) { + let chromeWindow = getMostRecentBrowserWindow(); + let rawTab = openTab(chromeWindow, url, { + isPrivate: enablePrivate + }); + + return { + ready: promise.resolve(getTabContentWindow(rawTab)), + close: function () { + closeTab(rawTab); + // Returns a resolved promise as there is no need to wait + return promise.resolve(); + } + }; + } + else { + let win = openWindow(null, { + features: { + private: enablePrivate + } + }); + let deferred = promise.defer(); + + // Wait for delayed startup code to be executed, in order to ensure + // that the window is really ready + events.on("browser-delayed-startup-finished", function onReady({subject}) { + if (subject == win) { + events.off("browser-delayed-startup-finished", onReady); + deferred.resolve(win); + + let rawTab = getActiveTab(win); + setTabURL(rawTab, url); + deferred.resolve(getTabContentWindow(rawTab)); + } + }, true); + + return { + ready: deferred.promise, + close: function () { + return windowHelpers.close(win); + } + }; + } + return null; +} diff --git a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-events.js b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-events.js new file mode 100644 index 000000000..4d4eae347 --- /dev/null +++ b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-events.js @@ -0,0 +1,238 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { Loader } = require("sdk/test/loader"); +const utils = require("sdk/tabs/utils"); +const { open, close } = require("sdk/window/helpers"); +const { getMostRecentBrowserWindow } = require("sdk/window/utils"); +const { events } = require("sdk/tab/events"); +const { on, off } = require("sdk/event/core"); +const { resolve, defer } = require("sdk/core/promise"); + +var isFennec = require("sdk/system/xul-app").is("Fennec"); + +function test(options) { + return function(assert, done) { + let tabEvents = []; + let tabs = []; + let { promise, resolve: resolveP } = defer(); + let win = isFennec ? resolve(getMostRecentBrowserWindow()) : + open(null, { + features: { private: true, toolbar:true, chrome: true } + }); + let window = null; + + // Firefox events are fired sync; Fennec events async + // this normalizes the tests + function handler (event) { + tabEvents.push(event); + runIfReady(); + } + + function runIfReady () { + let releventEvents = getRelatedEvents(tabEvents, tabs); + if (options.readyWhen(releventEvents)) + options.end({ + tabs: tabs, + events: releventEvents, + assert: assert, + done: resolveP + }); + } + + win.then(function(w) { + window = w; + on(events, "data", handler); + options.start({ tabs: tabs, window: window }); + + // Execute here for synchronous FF events, as the handlers + // were called before tabs were pushed to `tabs` + runIfReady(); + return promise; + }).then(function() { + off(events, "data", handler); + return isFennec ? null : close(window); + }).then(done, assert.fail); + }; +} + +// Just making sure that tab events work for already opened tabs not only +// for new windows. +exports["test current window"] = test({ + readyWhen: events => events.length === 3, + start: ({ tabs, window }) => { + let tab = utils.openTab(window, 'data:text/plain,open'); + tabs.push(tab); + utils.closeTab(tab); + }, + end: ({ tabs, events, assert, done }) => { + let [open, select, close] = events; + let tab = tabs[0]; + + assert.equal(open.type, "TabOpen"); + assert.equal(open.target, tab); + + assert.equal(select.type, "TabSelect"); + assert.equal(select.target, tab); + + assert.equal(close.type, "TabClose"); + assert.equal(close.target, tab); + done(); + } +}); + +exports["test open"] = test({ + readyWhen: events => events.length === 2, + start: ({ tabs, window }) => { + tabs.push(utils.openTab(window, 'data:text/plain,open')); + }, + end: ({ tabs, events, assert, done }) => { + let [open, select] = events; + let tab = tabs[0]; + + assert.equal(open.type, "TabOpen"); + assert.equal(open.target, tab); + + assert.equal(select.type, "TabSelect"); + assert.equal(select.target, tab); + done(); + } +}); + +exports["test open -> close"] = test({ + readyWhen: events => events.length === 3, + start: ({ tabs, window }) => { + // First tab is useless we just open it so that closing second tab won't + // close window on some platforms. + utils.openTab(window, 'data:text/plain,ignore'); + let tab = utils.openTab(window, 'data:text/plain,open-close'); + tabs.push(tab); + utils.closeTab(tab); + }, + end: ({ tabs, events, assert, done }) => { + let [open, select, close] = events; + let tab = tabs[0]; + + assert.equal(open.type, "TabOpen"); + assert.equal(open.target, tab); + + assert.equal(select.type, "TabSelect"); + assert.equal(select.target, tab); + + assert.equal(close.type, "TabClose"); + assert.equal(close.target, tab); + done(); + } +}); + +exports["test open -> open -> select"] = test({ + readyWhen: events => events.length === 5, + start: ({tabs, window}) => { + tabs.push(utils.openTab(window, 'data:text/plain,Tab-1')); + tabs.push(utils.openTab(window, 'data:text/plain,Tab-2')); + utils.activateTab(tabs[0], window); + }, + end: ({ tabs, events, assert, done }) => { + let [ tab1, tab2 ] = tabs; + let tab1Events = 0; + getRelatedEvents(events, tab1).map(event => { + tab1Events++; + if (tab1Events === 1) + assert.equal(event.type, "TabOpen", "first tab opened"); + else + assert.equal(event.type, "TabSelect", "first tab selected"); + assert.equal(event.target, tab1); + }); + assert.equal(tab1Events, 3, "first tab has 3 events"); + + let tab2Opened; + getRelatedEvents(events, tab2).map(event => { + if (!tab2Opened) + assert.equal(event.type, "TabOpen", "second tab opened"); + else + assert.equal(event.type, "TabSelect", "second tab selected"); + tab2Opened = true; + assert.equal(event.target, tab2); + }); + done(); + } +}); + +exports["test open -> pin -> unpin"] = test({ + readyWhen: events => events.length === (isFennec ? 2 : 5), + start: ({ tabs, window }) => { + tabs.push(utils.openTab(window, 'data:text/plain,pin-unpin')); + utils.pin(tabs[0]); + utils.unpin(tabs[0]); + }, + end: ({ tabs, events, assert, done }) => { + let [open, select, move, pin, unpin] = events; + let tab = tabs[0]; + + assert.equal(open.type, "TabOpen"); + assert.equal(open.target, tab); + + assert.equal(select.type, "TabSelect"); + assert.equal(select.target, tab); + + if (isFennec) { + assert.pass("Tab pin / unpin is not supported by Fennec"); + } + else { + assert.equal(move.type, "TabMove"); + assert.equal(move.target, tab); + + assert.equal(pin.type, "TabPinned"); + assert.equal(pin.target, tab); + + assert.equal(unpin.type, "TabUnpinned"); + assert.equal(unpin.target, tab); + } + done(); + } +}); + +exports["test open -> open -> move "] = test({ + readyWhen: events => events.length === (isFennec ? 4 : 5), + start: ({tabs, window}) => { + tabs.push(utils.openTab(window, 'data:text/plain,Tab-1')); + tabs.push(utils.openTab(window, 'data:text/plain,Tab-2')); + utils.move(tabs[0], 2); + }, + end: ({ tabs, events, assert, done }) => { + let [ tab1, tab2 ] = tabs; + let tab1Events = 0; + getRelatedEvents(events, tab1).map(event => { + tab1Events++; + if (tab1Events === 1) + assert.equal(event.type, "TabOpen", "first tab opened"); + else if (tab1Events === 2) + assert.equal(event.type, "TabSelect", "first tab selected"); + else if (tab1Events === 3 && isFennec) + assert.equal(event.type, "TabMove", "first tab moved"); + assert.equal(event.target, tab1); + }); + assert.equal(tab1Events, isFennec ? 2 : 3, + "correct number of events for first tab"); + + let tab2Events = 0; + getRelatedEvents(events, tab2).map(event => { + tab2Events++; + if (tab2Events === 1) + assert.equal(event.type, "TabOpen", "second tab opened"); + else + assert.equal(event.type, "TabSelect", "second tab selected"); + assert.equal(event.target, tab2); + }); + done(); + } +}); + +function getRelatedEvents (events, tabs) { + return events.filter(({target}) => ~([].concat(tabs)).indexOf(target)); +} + +// require("sdk/test").run(exports); diff --git a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-observer.js b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-observer.js new file mode 100644 index 000000000..b0e1753a2 --- /dev/null +++ b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-observer.js @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// TODO Fennec support in Bug #894525 +module.metadata = { + "engines": { + "Firefox": "*" + } +} + +const { openTab, closeTab } = require("sdk/tabs/utils"); +const { Loader } = require("sdk/test/loader"); +const { setTimeout } = require("sdk/timers"); + +exports["test unload tab observer"] = function(assert, done) { + let loader = Loader(module); + + let window = loader.require("sdk/deprecated/window-utils").activeBrowserWindow; + let observer = loader.require("sdk/tabs/observer").observer; + let opened = 0; + let closed = 0; + + observer.on("open", function onOpen(window) { opened++; }); + observer.on("close", function onClose(window) { closed++; }); + + // Open and close tab to trigger observers. + closeTab(openTab(window, "data:text/html;charset=utf-8,tab-1")); + + // Unload the module so that all listeners set by observer are removed. + loader.unload(); + + // Open and close tab once again. + closeTab(openTab(window, "data:text/html;charset=utf-8,tab-2")); + + // Enqueuing asserts to make sure that assertion is not performed early. + setTimeout(function () { + assert.equal(1, opened, "observer open was called before unload only"); + assert.equal(1, closed, "observer close was called before unload only"); + done(); + }, 0); +}; + +// require("test").run(exports); diff --git a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-utils.js b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-utils.js new file mode 100644 index 000000000..97c388b3c --- /dev/null +++ b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab-utils.js @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +const { getTabs } = require('sdk/tabs/utils'); +const { isWindowPBSupported, isTabPBSupported } = require('sdk/private-browsing/utils'); +const { browserWindows } = require('sdk/windows'); +const tabs = require('sdk/tabs'); +const { isPrivate } = require('sdk/private-browsing'); +const { openTab, closeTab, getTabContentWindow, getOwnerWindow } = require('sdk/tabs/utils'); +const { open, close } = require('sdk/window/helpers'); +const { windows } = require('sdk/window/utils'); +const { getMostRecentBrowserWindow } = require('sdk/window/utils'); +const { fromIterator } = require('sdk/util/array'); + +if (isWindowPBSupported) { + exports.testGetTabsPWPB = function(assert, done) { + let tabCount = getTabs().length; + let windowCount = browserWindows.length; + + open(null, { + features: { + private: true, + toolbar: true, + chrome: true + } + }).then(function(window) { + assert.ok(isPrivate(window), 'new tab is private'); + + assert.equal(getTabs().length, tabCount, 'there are no new tabs found'); + getTabs().forEach(function(tab) { + assert.equal(isPrivate(tab), false, 'all found tabs are not private'); + assert.equal(isPrivate(getOwnerWindow(tab)), false, 'all found tabs are not private'); + assert.equal(isPrivate(getTabContentWindow(tab)), false, 'all found tabs are not private'); + }); + + assert.equal(browserWindows.length, windowCount, 'there are no new windows found'); + fromIterator(browserWindows).forEach(function(window) { + assert.equal(isPrivate(window), false, 'all found windows are not private'); + }); + + assert.equal(windows(null, {includePrivate: true}).length, 2, 'there are really two windows'); + + close(window).then(done); + }); + }; +} +else if (isTabPBSupported) { + exports.testGetTabsPTPB = function(assert, done) { + let startTabCount = getTabs().length; + let tab = openTab(getMostRecentBrowserWindow(), 'about:blank', { + isPrivate: true + }); + + assert.ok(isPrivate(getTabContentWindow(tab)), 'new tab is private'); + let utils_tabs = getTabs(); + assert.equal(utils_tabs.length, startTabCount + 1, + 'there are two tabs found'); + assert.equal(utils_tabs[utils_tabs.length-1], tab, + 'the last tab is the opened tab'); + assert.equal(browserWindows.length, 1, 'there is only one window'); + closeTab(tab); + + done(); + }; +} diff --git a/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab.js b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab.js new file mode 100644 index 000000000..0a94984a6 --- /dev/null +++ b/addon-sdk/source/test/addons/e10s-tabs/lib/test-tab.js @@ -0,0 +1,87 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const tabs = require("sdk/tabs"); // From addon-kit +const windowUtils = require("sdk/deprecated/window-utils"); +const app = require("sdk/system/xul-app"); +const { viewFor } = require("sdk/view/core"); +const { modelFor } = require("sdk/model/core"); +const { getTabId, isTab } = require("sdk/tabs/utils"); +const { defer } = require("sdk/lang/functional"); + +exports["test behavior on close"] = function(assert, done) { + tabs.open({ + url: "about:mozilla", + onReady: function(tab) { + assert.equal(tab.url, "about:mozilla", "Tab has the expected url"); + // if another test ends before closing a tab then index != 1 here + assert.ok(tab.index >= 1, "Tab has the expected index, a value greater than 0"); + tab.close(function () { + assert.equal(tab.url, undefined, + "After being closed, tab attributes are undefined (url)"); + assert.equal(tab.index, undefined, + "After being closed, tab attributes are undefined (index)"); + if (app.is("Firefox")) { + // Ensure that we can call destroy multiple times without throwing; + // Fennec doesn't use this internal utility + tab.destroy(); + tab.destroy(); + } + + done(); + }); + } + }); +}; + +exports["test viewFor(tab)"] = (assert, done) => { + // Note we defer handlers as length collection is updated after + // handler is invoked, so if test is finished before counnts are + // updated wrong length will show up in followup tests. + tabs.once("open", defer(tab => { + const view = viewFor(tab); + assert.ok(view, "view is returned"); + assert.equal(getTabId(view), tab.id, "tab has a same id"); + + tab.close(defer(done)); + })); + + tabs.open({ url: "about:mozilla" }); +}; + +exports["test modelFor(xulTab)"] = (assert, done) => { + tabs.open({ + url: "about:mozilla", + onReady: tab => { + const view = viewFor(tab); + assert.ok(view, "view is returned"); + assert.ok(isTab(view), "view is underlaying tab"); + assert.equal(getTabId(view), tab.id, "tab has a same id"); + assert.equal(modelFor(view), tab, "modelFor(view) is SDK tab"); + + tab.close(defer(done)); + } + }); +}; + +exports["test tab.readyState"] = (assert, done) => { + tabs.open({ + url: "data:text/html;charset=utf-8,test_readyState", + onOpen: (tab) => { + assert.notEqual(["uninitialized", "loading"].indexOf(tab.readyState), -1, + "tab is either uninitialized or loading when onOpen"); + }, + onReady: (tab) => { + assert.notEqual(["interactive", "complete"].indexOf(tab.readyState), -1, + "tab is either interactive or complete when onReady"); + }, + onLoad: (tab) => { + assert.equal(tab.readyState, "complete", "tab is complete onLoad"); + tab.close(defer(done)); + } + }); +} + +// require("sdk/test").run(exports); |