gecko-dev/addon-sdk/source/test/test-ui-sidebar.js

1580 строки
46 KiB
JavaScript

/* 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';
module.metadata = {
'engines': {
'Firefox': '*'
}
};
const { Cu } = require('chrome');
const { Loader } = require('sdk/test/loader');
const { show, hide } = require('sdk/ui/sidebar/actions');
const { isShowing } = require('sdk/ui/sidebar/utils');
const { getMostRecentBrowserWindow, isFocused } = require('sdk/window/utils');
const { open, close, focus, promise: windowPromise } = require('sdk/window/helpers');
const { setTimeout, setImmediate } = require('sdk/timers');
const { isPrivate } = require('sdk/private-browsing');
const data = require('./fixtures');
const { URL } = require('sdk/url');
const { once, off, emit } = require('sdk/event/core');
const { defer, all } = require('sdk/core/promise');
const { modelFor } = require('sdk/model/core');
const { cleanUI } = require("sdk/test/utils");
const { before, after } = require('sdk/test/utils');
require('sdk/windows');
const { BUILTIN_SIDEBAR_MENUITEMS, isSidebarShowing,
getSidebarMenuitems, getExtraSidebarMenuitems, makeID, simulateCommand,
simulateClick, isChecked } = require('./sidebar/utils');
exports.testSidebarBasicLifeCycle = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testSidebarBasicLifeCycle';
let window = getMostRecentBrowserWindow();
assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
let sidebarXUL = window.document.getElementById('sidebar');
assert.ok(sidebarXUL, 'sidebar xul element does exist');
assert.ok(!getExtraSidebarMenuitems().length, 'there are no extra sidebar menuitems');
assert.equal(isSidebarShowing(window), false, 'sidebar is not showing 1');
let sidebarDetails = {
id: testName,
title: 'test',
url: 'data:text/html;charset=utf-8,'+testName
};
let sidebar = Sidebar(sidebarDetails);
// test the sidebar attributes
for (let key of Object.keys(sidebarDetails)) {
assert.equal(sidebarDetails[key], sidebar[key], 'the attributes match the input');
}
assert.pass('The Sidebar constructor worked');
let extraMenuitems = getExtraSidebarMenuitems();
assert.equal(extraMenuitems.length, 1, 'there is one extra sidebar menuitems');
let ele = window.document.getElementById(makeID(testName));
assert.equal(ele, extraMenuitems[0], 'the only extra menuitem is the one for our sidebar.')
assert.ok(ele, 'sidebar element was added');
assert.ok(!isChecked(ele), 'the sidebar is not displayed');
assert.equal(ele.getAttribute('label'), sidebar.title, 'the sidebar title is the menuitem label')
assert.equal(isSidebarShowing(window), false, 'sidebar is not showing 2');
// explicit test of the on hide event
yield new Promise(resolve => {
sidebar.on('show', resolve);
sidebar.show();
assert.pass('showing sidebar..');
});
assert.pass('the show event was fired');
assert.equal(isSidebarShowing(window), true, 'sidebar is not showing 3');
assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
assert.ok(isChecked(ele), 'the sidebar is displayed');
// explicit test of the on show event
yield new Promise(resolve => {
sidebar.on('hide', () => {
sidebar.once('detach', resolve);
assert.pass('the hide event was fired');
assert.ok(!isChecked(ele), 'the sidebar menuitem is not checked');
assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
assert.equal(isSidebarShowing(window), false, 'the sidebar elemnt is hidden');
});
sidebar.hide();
assert.pass('hiding sidebar..');
});
// calling destroy twice should not matter
sidebar.destroy();
sidebar.destroy();
for (let mi of getSidebarMenuitems()) {
let id = mi.getAttribute('id');
if (BUILTIN_SIDEBAR_MENUITEMS.indexOf(id) < 0) {
assert.fail('the menuitem "' + id + '" is not a built-in sidebar');
}
assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
}
assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
assert.pass('calling destroy worked without error');
}
exports.testSideBarIsInNewWindows = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testSideBarIsInNewWindows';
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
let startWindow = getMostRecentBrowserWindow();
let ele = startWindow.document.getElementById(makeID(testName));
assert.ok(ele, 'sidebar element was added');
let window = yield open();
ele = window.document.getElementById(makeID(testName));
assert.ok(ele, 'sidebar element was added');
// calling destroy twice should not matter
sidebar.destroy();
sidebar.destroy();
assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
}
exports.testSideBarIsShowingInNewWindows = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testSideBarIsShowingInNewWindows';
let sidebar = Sidebar({
id: testName,
title: testName,
url: URL('data:text/html;charset=utf-8,'+testName)
});
let startWindow = getMostRecentBrowserWindow();
let ele = startWindow.document.getElementById(makeID(testName));
assert.ok(ele, 'sidebar element was added');
let oldEle = ele;
yield new Promise(resolve => {
sidebar.once('attach', function() {
assert.pass('attach event fired');
sidebar.once('show', function() {
assert.pass('show event fired');
resolve();
})
});
sidebar.show();
});
yield new Promise(resolve => {
sidebar.once('show', resolve);
startWindow.OpenBrowserWindow();
});
let window = getMostRecentBrowserWindow();
assert.notEqual(startWindow, window, 'window is new');
let sb = window.document.getElementById('sidebar');
yield new Promise(resolve => {
if (sb && sb.docShell && sb.contentDocument && sb.contentDocument.getElementById('web-panels-browser')) {
end();
}
else {
sb.addEventListener('DOMWindowCreated', end, false);
}
function end () {
sb.removeEventListener('DOMWindowCreated', end, false);
resolve();
}
})
ele = window.document.getElementById(makeID(testName));
assert.ok(ele, 'sidebar element was added 2');
assert.ok(isChecked(ele), 'the sidebar is checked');
assert.notEqual(ele, oldEle, 'there are two different sidebars');
assert.equal(isShowing(sidebar), true, 'the sidebar is showing in new window');
sidebar.destroy();
assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
assert.ok(!isSidebarShowing(window), 'sidebar in most recent window is not showing');
assert.ok(!isSidebarShowing(startWindow), 'sidebar in most start window is not showing');
assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
}
// TODO: determine if this is acceptable..
/*
exports.testAddonGlobalSimple = function(assert, done) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testAddonGlobalSimple';
let sidebar = Sidebar({
id: testName,
title: testName,
url: data.url('test-sidebar-addon-global.html')
});
sidebar.on('show', function({worker}) {
assert.pass('sidebar was attached');
assert.ok(!!worker, 'attach event has worker');
worker.port.on('X', function(msg) {
assert.equal(msg, '23', 'the final message is correct');
sidebar.destroy();
done();
});
worker.port.emit('X', '2');
});
show(sidebar);
}
*/
exports.testAddonGlobalComplex = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testAddonGlobalComplex';
let sidebar = Sidebar({
id: testName,
title: testName,
url: data.url('test-sidebar-addon-global.html')
});
let worker = yield new Promise(resolve => {
sidebar.on('attach', resolve);
show(sidebar);
});
assert.pass('sidebar was attached');
assert.ok(!!worker, 'attach event has worker');
let msg = yield new Promise(resolve => {
worker.port.once('Y', resolve);
});
assert.equal(msg, '1', 'got event from worker');
msg = yield new Promise(resolve => {
worker.port.on('X', resolve);
worker.port.emit('X', msg + '2');
});
assert.equal(msg, '123', 'the final message is correct');
sidebar.destroy();
}
exports.testAddonReady = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testAddonReady';
let ready = defer();
let sidebar = Sidebar({
id: testName,
title: testName,
url: data.url('test-sidebar-addon-global.html'),
onReady: ready.resolve
});
show(sidebar);
let worker = yield ready.promise;
assert.pass('sidebar was attached');
assert.ok(!!worker, 'attach event has worker');
let msg = yield new Promise(resolve => {
worker.port.on('X', resolve);
worker.port.emit('X', '12');
});
assert.equal(msg, '123', 'the final message is correct');
sidebar.destroy();
}
exports.testShowingOneSidebarAfterAnother = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testShowingOneSidebarAfterAnother';
let sidebar1 = Sidebar({
id: testName + '1',
title: testName + '1',
url: 'data:text/html;charset=utf-8,'+ testName + 1
});
let sidebar2 = Sidebar({
id: testName + '2',
title: testName + '2',
url: 'data:text/html;charset=utf-8,'+ testName + 2
});
let window = getMostRecentBrowserWindow();
let IDs = [ sidebar1.id, sidebar2.id ];
let extraMenuitems = getExtraSidebarMenuitems(window);
assert.equal(extraMenuitems.length, 2, 'there are two extra sidebar menuitems');
function testShowing(sb1, sb2, sbEle) {
assert.equal(isShowing(sidebar1), sb1);
assert.equal(isShowing(sidebar2), sb2);
assert.equal(isSidebarShowing(window), sbEle);
}
testShowing(false, false, false);
yield show(sidebar1);
assert.pass('showed sidebar1');
testShowing(true, false, true);
for (let mi of getExtraSidebarMenuitems(window)) {
let menuitemID = mi.getAttribute('id').replace(/^jetpack-sidebar-/, '');
assert.ok(IDs.indexOf(menuitemID) >= 0, 'the extra menuitem is for one of our test sidebars');
assert.equal(isChecked(mi), menuitemID == sidebar1.id, 'the test sidebar menuitem has the correct checked value');
}
yield show(sidebar2);
assert.pass('showed sidebar2');
testShowing(false, true, true);
for (let mi of getExtraSidebarMenuitems(window)) {
let menuitemID = mi.getAttribute('id').replace(/^jetpack-sidebar-/, '');
assert.ok(IDs.indexOf(menuitemID) >= 0, 'the extra menuitem is for one of our test sidebars');
assert.equal(isChecked(mi), menuitemID == sidebar2.id, 'the test sidebar menuitem has the correct checked value');
}
sidebar1.destroy();
sidebar2.destroy();
testShowing(false, false, false);
}
exports.testSidebarUnload = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testSidebarUnload';
let loader = Loader(module);
let window = getMostRecentBrowserWindow();
assert.equal(isPrivate(window), false, 'the current window is not private');
let sidebar = loader.require('sdk/ui/sidebar').Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+ testName
});
yield sidebar.show();
assert.pass('showing the sidebar');
loader.unload();
for (let mi of getSidebarMenuitems()) {
assert.ok(BUILTIN_SIDEBAR_MENUITEMS.indexOf(mi.getAttribute('id')) >= 0, 'the menuitem is for a built-in sidebar')
assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
}
assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
}
exports.testRelativeURL = function*(assert) {
const { merge } = require('sdk/util/object');
const self = require('sdk/self');
let loader = Loader(module, null, null, {
modules: {
'sdk/self': merge({}, self, {
data: merge({}, self.data, require('./fixtures'))
})
}
});
const { Sidebar } = loader.require('sdk/ui/sidebar');
let testName = 'testRelativeURL';
let sidebar = Sidebar({
id: testName,
title: testName,
url: './test-sidebar-addon-global.html'
});
yield new Promise(resolve => {
sidebar.on('attach', function(worker) {
assert.pass('sidebar was attached');
assert.ok(!!worker, 'attach event has worker');
worker.port.once('Y', function(msg) {
assert.equal(msg, '1', 'got event from worker');
worker.port.on('X', function(msg) {
assert.equal(msg, '123', 'the final message is correct');
resolve();
});
worker.port.emit('X', msg + '2');
})
});
sidebar.show();
});
sidebar.destroy();
}
exports.testRemoteContent = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testRemoteContent';
try {
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'http://dne.xyz.mozilla.org'
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.ok(/The option "url" must be a valid local URI\./.test(e), 'remote content is not acceptable');
}
}
exports.testInvalidURL = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidURL';
try {
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'http:mozilla.org'
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.ok(/The option "url" must be a valid local URI\./.test(e), 'invalid URIs are not acceptable');
}
}
exports.testInvalidURLType = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidURLType';
try {
let sidebar = Sidebar({
id: testName,
title: testName
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.ok(/The option "url" must be a valid local URI\./.test(e), 'invalid URIs are not acceptable');
}
}
exports.testInvalidTitle = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidTitle';
try {
let sidebar = Sidebar({
id: testName,
title: '',
url: 'data:text/html;charset=utf-8,'+testName
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.equal('The option "title" must be one of the following types: string', e.message, 'invalid titles are not acceptable');
}
}
exports.testInvalidID = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidID';
try {
let sidebar = Sidebar({
id: '!',
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
}
}
exports.testInvalidBlankID = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidBlankID';
try {
let sidebar = Sidebar({
id: '',
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
}
}
exports.testInvalidNullID = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidNullID';
try {
let sidebar = Sidebar({
id: null,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
assert.fail('a bad sidebar was created..');
sidebar.destroy();
}
catch(e) {
assert.ok(/The option "id" must be a valid alphanumeric id/.test(e), 'invalid ids are not acceptable');
}
}
exports.testUndefinedID = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testInvalidUndefinedID';
try {
let sidebar = Sidebar({
title: testName,
url: 'data:text/html;charset=utf-8,' + testName
});
assert.ok(sidebar.id, 'an undefined id was accepted, id was creawted: ' + sidebar.id);
assert.ok(getMostRecentBrowserWindow().document.getElementById(makeID(sidebar.id)), 'the sidebar element was found');
sidebar.destroy();
}
catch(e) {
assert.fail('undefined ids are acceptable');
assert.fail(e.message);
}
}
// TEST: edge case where web panel is destroyed while loading
exports.testDestroyEdgeCaseBug = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testDestroyEdgeCaseBug';
let window = getMostRecentBrowserWindow();
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
// NOTE: purposely not listening to show event b/c the event happens
// between now and then.
sidebar.show();
assert.equal(isPrivate(window), false, 'the new window is not private');
assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
//assert.equal(isShowing(sidebar), true, 'the sidebar is showing');
let window2 = yield open().then(focus);
assert.equal(isPrivate(window2), false, 'the new window is not private');
assert.equal(isSidebarShowing(window2), false, 'the sidebar is not showing');
assert.equal(isShowing(sidebar), false, 'the sidebar is not showing');
sidebar.destroy();
assert.pass('destroying the sidebar');
yield close(window2);
let loader = Loader(module);
assert.equal(isPrivate(window), false, 'the current window is not private');
sidebar = loader.require('sdk/ui/sidebar').Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+ testName,
onShow: function() {
}
})
assert.pass('showing the sidebar');
yield sidebar.show();
loader.unload();
for (let mi of getSidebarMenuitems()) {
let id = mi.getAttribute('id');
if (BUILTIN_SIDEBAR_MENUITEMS.indexOf(id) < 0) {
assert.fail('the menuitem "' + id + '" is not a built-in sidebar');
}
assert.ok(!isChecked(mi), 'no sidebar menuitem is checked');
}
assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
}
exports.testClickingACheckedMenuitem = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
const testName = 'testClickingACheckedMenuitem';
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName,
});
assert.pass('sidebar was created');
let window = yield open().then(focus);
yield sidebar.show();
assert.pass('the show callback works');
let waitForHide = defer();
sidebar.once('hide', waitForHide.resolve);
let menuitem = window.document.getElementById(makeID(sidebar.id));
simulateCommand(menuitem);
yield waitForHide.promise;
assert.pass('clicking the menuitem after the sidebar has shown hides it.');
sidebar.destroy();
};
exports.testTitleSetter = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testTitleSetter';
let { document } = getMostRecentBrowserWindow();
let sidebar1 = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName,
});
assert.equal(sidebar1.title, testName, 'title getter works');
yield sidebar1.show();
assert.equal(document.getElementById(makeID(sidebar1.id)).getAttribute('label'),
testName,
'the menuitem label is correct');
assert.equal(document.getElementById('sidebar-title').value, testName, 'the menuitem label is correct');
sidebar1.title = 'foo';
assert.equal(sidebar1.title, 'foo', 'title getter works');
assert.equal(document.getElementById(makeID(sidebar1.id)).getAttribute('label'),
'foo',
'the menuitem label was updated');
assert.equal(document.getElementById('sidebar-title').value, 'foo', 'the sidebar title was updated');
sidebar1.destroy();
}
exports.testURLSetter = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testURLSetter';
let window = getMostRecentBrowserWindow();
let { document } = window;
let url = 'data:text/html;charset=utf-8,'+testName;
let sidebar1 = Sidebar({
id: testName,
title: testName,
url: url
});
assert.equal(sidebar1.url, url, 'url getter works');
assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
assert.ok(!isChecked(document.getElementById(makeID(sidebar1.id))),
'the menuitem is not checked');
assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
window = yield windowPromise(window.OpenBrowserWindow(), 'load');
document = window.document;
assert.pass('new window was opened');
yield sidebar1.show();
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
'the menuitem is checked');
assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
yield new Promise(resolve => {
sidebar1.once('show', resolve);
sidebar1.url = (url + '1');
assert.equal(sidebar1.url, (url + '1'), 'url getter works');
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
});
assert.pass('setting the sidebar.url causes a show event');
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
assert.equal(isSidebarShowing(window), true, 'the new window sidebar is still showing');
assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
'the menuitem is still checked');
sidebar1.destroy();
assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
}
exports.testDuplicateID = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testDuplicateID';
let window = getMostRecentBrowserWindow();
let { document } = window;
let url = 'data:text/html;charset=utf-8,'+testName;
let sidebar1 = Sidebar({
id: testName,
title: testName,
url: url
});
assert.throws(function() {
Sidebar({
id: testName,
title: testName + 1,
url: url + 2
}).destroy();
}, /The ID .+ seems already used\./i, 'duplicate IDs will throw errors');
sidebar1.destroy();
}
exports.testURLSetterToSameValueReloadsSidebar = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testURLSetterToSameValueReloadsSidebar';
let window = getMostRecentBrowserWindow();
let { document } = window;
let url = 'data:text/html;charset=utf-8,'+testName;
let sidebar1 = Sidebar({
id: testName,
title: testName,
url: url
});
assert.equal(sidebar1.url, url, 'url getter works');
assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
assert.ok(!isChecked(document.getElementById(makeID(sidebar1.id))),
'the menuitem is not checked');
assert.equal(isSidebarShowing(window), false, 'the new window sidebar is not showing');
window = yield windowPromise(window.OpenBrowserWindow(), 'load');
document = window.document;
assert.pass('new window was opened');
yield focus(window);
assert.pass('new window was focused');
yield sidebar1.show();
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
'the menuitem is checked');
assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
let shown = defer();
sidebar1.once('show', shown.resolve);
sidebar1.url = url;
assert.equal(sidebar1.url, url, 'url getter works');
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
assert.ok(isSidebarShowing(window), 'the new window sidebar is showing');
yield shown.promise;
assert.pass('setting the sidebar.url causes a show event');
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
assert.ok(isSidebarShowing(window), 'the new window sidebar is still showing');
assert.ok(isChecked(document.getElementById(makeID(sidebar1.id))),
'the menuitem is still checked');
sidebar1.destroy();
}
exports.testShowingInOneWindowDoesNotAffectOtherWindows = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testShowingInOneWindowDoesNotAffectOtherWindows';
let window1 = getMostRecentBrowserWindow();
let url = 'data:text/html;charset=utf-8,'+testName;
let sidebar1 = Sidebar({
id: testName,
title: testName,
url: url
});
assert.equal(sidebar1.url, url, 'url getter works');
assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
let checkCount = 1;
function checkSidebarShowing(window, expected) {
assert.pass('check count ' + checkCount++);
let mi = window.document.getElementById(makeID(sidebar1.id));
if (mi) {
assert.equal(isChecked(mi), expected,
'the menuitem is not checked');
}
assert.equal(isSidebarShowing(window), expected || false, 'the new window sidebar is not showing');
}
checkSidebarShowing(window1, false);
let window = yield windowPromise(window1.OpenBrowserWindow(), 'load');
let { document } = window;
assert.pass('new window was opened!');
// waiting for show
yield sidebar1.show();
// check state of the new window
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
checkSidebarShowing(window, true);
// check state of old window
checkSidebarShowing(window1, false);
yield sidebar1.show();
// check state of the new window
assert.equal(isShowing(sidebar1), true, 'the sidebar is showing');
checkSidebarShowing(window, true);
// check state of old window
checkSidebarShowing(window1, false);
// calling destroy() twice should not matter
sidebar1.destroy();
sidebar1.destroy();
// check state of the new window
assert.equal(isShowing(sidebar1), false, 'the sidebar is not showing');
checkSidebarShowing(window, undefined);
// check state of old window
checkSidebarShowing(window1, undefined);
}
exports.testHidingAHiddenSidebarRejects = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testHidingAHiddenSidebarRejects';
let url = 'data:text/html;charset=utf-8,'+testName;
let sidebar = Sidebar({
id: testName,
title: testName,
url: url
});
yield sidebar.hide().then(assert.fail, assert.pass);
sidebar.destroy();
}
exports.testGCdSidebarsOnUnload = function*(assert) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
const window = getMostRecentBrowserWindow();
let testName = 'testGCdSidebarsOnUnload';
let url = 'data:text/html;charset=utf-8,'+testName;
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
// IMPORTANT: make no reference to the sidebar instance, so it is GC'd
let sidebar = Sidebar({
id: testName,
title: testName,
url: url
});
yield sidebar.show();
sidebar = null;
assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
let menuitemID = makeID(testName);
assert.ok(window.document.getElementById(menuitemID), 'the menuitem was found');
yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
loader.unload();
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing after unload');
assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed');
}
exports.testGCdShowingSidebarsOnUnload = function*(assert) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
const window = getMostRecentBrowserWindow();
let testName = 'testGCdShowingSidebarsOnUnload';
let url = 'data:text/html;charset=utf-8,'+testName;
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
let sidebar = Sidebar({
id: testName,
title: testName,
url: url
});
yield sidebar.show();
sidebar = null;
assert.equal(isSidebarShowing(window), true, 'the sidebar is showing');
let menuitemID = makeID(testName);
assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found');
yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
assert.equal(isSidebarShowing(window), true, 'the sidebar is still showing after gc');
assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found after gc');
loader.unload();
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing after unload');
assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed');
}
exports.testDetachEventOnWindowClose = function*(assert) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
let window = getMostRecentBrowserWindow();
let testName = 'testDetachEventOnWindowClose';
let url = 'data:text/html;charset=utf-8,' + testName;
window = yield windowPromise(window.OpenBrowserWindow(), 'load').then(focus);
yield new Promise(resolve => {
let sidebar = Sidebar({
id: testName,
title: testName,
url: url,
onAttach: function() {
assert.pass('the attach event is fired');
window.close();
},
onDetach: resolve
});
sidebar.show();
});
assert.pass('the detach event is fired when the window showing it closes');
loader.unload();
}
exports.testHideEventOnWindowClose = function*(assert) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
let window = getMostRecentBrowserWindow();
let testName = 'testDetachEventOnWindowClose';
let url = 'data:text/html;charset=utf-8,' + testName;
window = yield windowPromise(window.OpenBrowserWindow(), 'load').then(focus);
yield new Promise(resolve => {
let sidebar = Sidebar({
id: testName,
title: testName,
url: url,
onAttach: function() {
assert.pass('the attach event is fired');
window.close();
},
onHide: resolve
});
sidebar.show();
});
assert.pass('the hide event is fired when the window showing it closes');
loader.unload();
}
exports.testGCdHiddenSidebarsOnUnload = function*(assert) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
const window = getMostRecentBrowserWindow();
let testName = 'testGCdHiddenSidebarsOnUnload';
let url = 'data:text/html;charset=utf-8,'+testName;
assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
// IMPORTANT: make no reference to the sidebar instance, so it is GC'd
Sidebar({
id: testName,
title: testName,
url: url
});
let menuitemID = makeID(testName);
assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found');
yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
assert.ok(!!window.document.getElementById(menuitemID), 'the menuitem was found after gc');
loader.unload();
assert.ok(!window.document.getElementById(menuitemID), 'the menuitem was removed');
}
exports.testSidebarGettersAndSettersAfterDestroy = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testSidebarGettersAndSettersAfterDestroy';
let url = 'data:text/html;charset=utf-8,'+testName;
let sidebar = Sidebar({
id: testName,
title: testName,
url: url
});
sidebar.destroy();
assert.equal(sidebar.id, undefined, 'sidebar after destroy has no id');
assert.throws(() => sidebar.id = 'foo-tang',
/^setting a property that has only a getter/,
'id cannot be set at runtime');
assert.equal(sidebar.id, undefined, 'sidebar after destroy has no id');
assert.equal(sidebar.title, undefined, 'sidebar after destroy has no title');
sidebar.title = 'boo-tang';
assert.equal(sidebar.title, undefined, 'sidebar after destroy has no title');
assert.equal(sidebar.url, undefined, 'sidebar after destroy has no url');
sidebar.url = url + 'barz';
assert.equal(sidebar.url, undefined, 'sidebar after destroy has no url');
}
exports.testSidebarLeakCheckDestroyAfterAttach = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testSidebarLeakCheckDestroyAfterAttach';
let window = getMostRecentBrowserWindow();
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
yield new Promise(resolve => {
sidebar.on('attach', resolve);
assert.pass('showing the sidebar');
sidebar.show();
})
assert.pass('the sidebar was shown');
sidebar.on('show', () => {
assert.fail('the sidebar show listener should have been removed');
});
assert.pass('added a sidebar show listener');
sidebar.on('hide', () => {
assert.fail('the sidebar hide listener should have been removed');
});
assert.pass('added a sidebar hide listener');
yield new Promise(resolve => {
let panelBrowser = window.document.getElementById('sidebar').contentDocument.getElementById('web-panels-browser');
panelBrowser.contentWindow.addEventListener('unload', function onUnload() {
panelBrowser.contentWindow.removeEventListener('unload', onUnload, false);
resolve();
}, false);
sidebar.destroy();
});
assert.pass('the sidebar web panel was unloaded properly');
}
exports.testSidebarLeakCheckUnloadAfterAttach = function*(assert) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
let testName = 'testSidebarLeakCheckUnloadAfterAttach';
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
let window = yield open().then(focus);
yield new Promise(resolve => {
sidebar.on('attach', resolve);
assert.pass('showing the sidebar');
sidebar.show();
});
assert.pass('the sidebar was shown');
sidebar.on('show', function() {
assert.fail('the sidebar show listener should have been removed');
});
assert.pass('added a sidebar show listener');
sidebar.on('hide', function() {
assert.fail('the sidebar hide listener should have been removed');
});
assert.pass('added a sidebar hide listener');
let panelBrowser = window.document.getElementById('sidebar').contentDocument.getElementById('web-panels-browser');
yield new Promise(resolve => {
panelBrowser.contentWindow.addEventListener('unload', function onUnload() {
panelBrowser.contentWindow.removeEventListener('unload', onUnload, false);
resolve();
}, false);
loader.unload();
});
assert.pass('the sidebar web panel was unloaded properly');
}
exports.testTwoSidebarsWithSameTitleAndURL = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testTwoSidebarsWithSameTitleAndURL';
let title = testName;
let url = 'data:text/html;charset=utf-8,' + testName;
let sidebar1 = Sidebar({
id: testName + 1,
title: title,
url: url
});
assert.throws(function() {
Sidebar({
id: testName + 2,
title: title,
url: url
}).destroy();
}, /title.+url.+invalid/i, 'Creating two sidebars with the same title + url is not allowed');
let sidebar2 = Sidebar({
id: testName + 2,
title: title,
url: 'data:text/html;charset=utf-8,X'
});
assert.throws(function() {
sidebar2.url = url;
}, /title.+url.+invalid/i, 'Creating two sidebars with the same title + url is not allowed');
sidebar2.title = 'foo';
sidebar2.url = url;
assert.throws(function() {
sidebar2.title = title;
}, /title.+url.+invalid/i, 'Creating two sidebars with the same title + url is not allowed');
sidebar1.destroy();
sidebar2.destroy();
}
exports.testChangingURLBackToOriginalValue = function(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testChangingURLBackToOriginalValue';
let title = testName;
let url = 'data:text/html;charset=utf-8,' + testName;
let count = 0;
let sidebar = Sidebar({
id: testName,
title: title,
url: url
});
sidebar.url = url + 2;
assert.equal(sidebar.url, url + 2, 'the sidebar.url is correct');
sidebar.url = url;
assert.equal(sidebar.url, url, 'the sidebar.url is correct');
sidebar.title = 'foo';
assert.equal(sidebar.title, 'foo', 'the sidebar.title is correct');
sidebar.title = title;
assert.equal(sidebar.title, title, 'the sidebar.title is correct');
sidebar.destroy();
assert.pass('Changing values back to originals works');
}
exports.testShowToOpenXToClose = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testShowToOpenXToClose';
let title = testName;
let url = 'data:text/html;charset=utf-8,' + testName;
let window = getMostRecentBrowserWindow();
let shown = defer();
let hidden = defer();
let sidebar = Sidebar({
id: testName,
title: testName,
url: url,
onShow: shown.resolve,
onHide: hidden.resolve
});
let menuitem = window.document.getElementById(makeID(sidebar.id));
assert.ok(!isChecked(menuitem), 'menuitem is not checked');
sidebar.show();
yield shown.promise;
assert.ok(isChecked(menuitem), 'menuitem is checked');
let closeButton = window.document.querySelector('#sidebar-header > toolbarbutton.close-icon');
simulateCommand(closeButton);
yield hidden.promise;
assert.ok(!isChecked(menuitem), 'menuitem is not checked');
sidebar.destroy();
}
exports.testShowToOpenMenuitemToClose = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testShowToOpenMenuitemToClose';
let title = testName;
let url = 'data:text/html;charset=utf-8,' + testName;
let window = getMostRecentBrowserWindow();
let hidden = defer();
let sidebar = Sidebar({
id: testName,
title: testName,
url: url,
onHide: hidden.resolve
});
let menuitem = window.document.getElementById(makeID(sidebar.id));
assert.ok(!isChecked(menuitem), 'menuitem is not checked');
yield sidebar.show();
assert.ok(isChecked(menuitem), 'menuitem is checked');
simulateCommand(menuitem);
yield hidden.promise;
assert.ok(!isChecked(menuitem), 'menuitem is not checked');
sidebar.destroy();
}
exports.testDestroyWhileNonBrowserWindowIsOpen = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testDestroyWhileNonBrowserWindowIsOpen';
let url = 'data:text/html;charset=utf-8,' + testName;
let sidebar = Sidebar({
id: testName,
title: testName,
url: url
});
let window = yield open('chrome://browser/content/aboutDialog.xul');
yield sidebar.show();
assert.equal(isSidebarShowing(getMostRecentBrowserWindow()), true, 'the sidebar is showing');
sidebar.destroy();
assert.pass('sidebar was destroyed while a non browser window was open');
yield cleanUI();
assert.equal(isSidebarShowing(getMostRecentBrowserWindow()), false, 'the sidebar is not showing');
}
exports.testEventListeners = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testWhatThisIsInSidebarEventListeners';
let eventListenerOrder = [];
let constructorOnShow = defer();
let constructorOnHide = defer();
let constructorOnAttach = defer();
let constructorOnReady = defer();
let onShow = defer();
let onHide = defer();
let onAttach = defer();
let onReady = defer();
let onceShow = defer();
let onceHide = defer();
let onceAttach = defer();
let onceReady = defer();
function testThis() {
assert(this, sidebar, '`this` is correct');
}
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,' + testName,
onShow: function() {
assert.equal(this, sidebar, '`this` is correct in onShow');
eventListenerOrder.push('onShow');
constructorOnShow.resolve();
},
onAttach: function() {
assert.equal(this, sidebar, '`this` is correct in onAttach');
eventListenerOrder.push('onAttach');
constructorOnAttach.resolve();
},
onReady: function() {
assert.equal(this, sidebar, '`this` is correct in onReady');
eventListenerOrder.push('onReady');
constructorOnReady.resolve();
},
onHide: function() {
assert.equal(this, sidebar, '`this` is correct in onHide');
eventListenerOrder.push('onHide');
constructorOnHide.resolve();
}
});
sidebar.once('show', function() {
assert.equal(this, sidebar, '`this` is correct in once show');
eventListenerOrder.push('once show');
onceShow.resolve();
});
sidebar.once('attach', function() {
assert.equal(this, sidebar, '`this` is correct in once attach');
eventListenerOrder.push('once attach');
onceAttach.resolve();
});
sidebar.once('ready', function() {
assert.equal(this, sidebar, '`this` is correct in once ready');
eventListenerOrder.push('once ready');
onceReady.resolve();
});
sidebar.once('hide', function() {
assert.equal(this, sidebar, '`this` is correct in once hide');
eventListenerOrder.push('once hide');
onceHide.resolve();
});
sidebar.on('show', function() {
assert.equal(this, sidebar, '`this` is correct in on show');
eventListenerOrder.push('on show');
onShow.resolve();
sidebar.hide();
});
sidebar.on('attach', function() {
assert.equal(this, sidebar, '`this` is correct in on attach');
eventListenerOrder.push('on attach');
onAttach.resolve();
});
sidebar.on('ready', function() {
assert.equal(this, sidebar, '`this` is correct in on ready');
eventListenerOrder.push('on ready');
onReady.resolve();
});
sidebar.on('hide', function() {
assert.equal(this, sidebar, '`this` is correct in on hide');
eventListenerOrder.push('on hide');
onHide.resolve();
});
sidebar.show();
yield all([constructorOnShow.promise,
constructorOnAttach.promise,
constructorOnReady.promise,
constructorOnHide.promise,
onceShow.promise,
onceAttach.promise,
onceReady.promise,
onceHide.promise,
onShow.promise,
onAttach.promise,
onReady.promise,
onHide.promise]);
assert.equal(eventListenerOrder.join(), [
'onAttach',
'once attach',
'on attach',
'onReady',
'once ready',
'on ready',
'onShow',
'once show',
'on show',
'onHide',
'once hide',
'on hide'
].join(), 'the event order was correct');
sidebar.destroy();
}
// For more information see Bug 920780
exports.testAttachDoesNotEmitWhenShown = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testAttachDoesNotEmitWhenShown';
let count = 0;
let attached = defer();
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName,
onAttach: function() {
if (count > 2) {
assert.fail('sidebar was attached again..');
}
else {
assert.pass('sidebar was attached ' + count + ' time(s)');
}
count++;
attached.resolve();
}
});
sidebar.show();
yield attached.promise;
let shownFired = 0;
let onShow = () => shownFired++;
sidebar.on('show', onShow);
yield sidebar.show();
assert.equal(shownFired, 0, 'shown should not be fired again when already showing from after attach');
yield sidebar.hide();
assert.pass("the sidebar was hidden");
yield sidebar.show();
assert.equal(shownFired, 1, 'shown was emitted when `show` called after being hidden');
yield sidebar.show();
assert.equal(shownFired, 1, 'shown was not emitted again if already being shown');
sidebar.off('show', onShow);
sidebar.destroy();
}
exports.testShowHideRawWindowArg = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testShowHideRawWindowArg';
assert.pass("Creating sidebar");
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,' + testName
});
assert.pass("Created sidebar");
let mainWindow = getMostRecentBrowserWindow();
let newWindow = yield windowPromise(mainWindow.OpenBrowserWindow(), 'load');
assert.pass("Created the new window");
yield focus(newWindow);
assert.pass("Focused the new window");
let newWindow2 = yield windowPromise(mainWindow.OpenBrowserWindow(), 'load');
assert.pass("Created the second new window");
yield focus(newWindow2);
assert.pass("Focused the second new window");
yield sidebar.show(newWindow);
assert.pass('the sidebar was shown');
assert.equal(isSidebarShowing(mainWindow), false, 'sidebar is not showing in main window');
assert.equal(isSidebarShowing(newWindow2), false, 'sidebar is not showing in second window');
assert.equal(isSidebarShowing(newWindow), true, 'sidebar is showing in new window');
assert.ok(isFocused(newWindow2), 'main window is still focused');
yield sidebar.hide(newWindow);
assert.equal(isFocused(newWindow2), true, 'second window is still focused');
assert.equal(isSidebarShowing(mainWindow), false, 'sidebar is not showing in main window');
assert.equal(isSidebarShowing(newWindow2), false, 'sidebar is not showing in second window');
assert.equal(isSidebarShowing(newWindow), false, 'sidebar is not showing in new window');
sidebar.destroy();
}
exports.testShowHideSDKWindowArg = function*(assert) {
const { Sidebar } = require('sdk/ui/sidebar');
let testName = 'testShowHideSDKWindowArg';
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,' + testName
});
let mainWindow = getMostRecentBrowserWindow();
let newWindow = yield open().then(focus);
let newSDKWindow = modelFor(newWindow);
yield focus(mainWindow);
yield sidebar.show(newSDKWindow);
assert.pass('the sidebar was shown');
assert.ok(!isSidebarShowing(mainWindow), 'sidebar is not showing in main window');
assert.ok(isSidebarShowing(newWindow), 'sidebar is showing in new window');
assert.ok(isFocused(mainWindow), 'main window is still focused');
yield sidebar.hide(newSDKWindow);
assert.ok(isFocused(mainWindow), 'main window is still focused');
assert.ok(!isSidebarShowing(mainWindow), 'sidebar is not showing in main window');
assert.ok(!isSidebarShowing(newWindow), 'sidebar is not showing in new window');
sidebar.destroy();
}
before(exports, (name, assert) => {
assert.equal(isSidebarShowing(), false, 'no sidebar is showing');
});
after(exports, function*(name, assert) {
assert.pass("Cleaning new windows and tabs");
yield cleanUI();
assert.equal(isSidebarShowing(), false, 'no sidebar is showing');
});
require('sdk/test').run(exports);