Bug 1179013: Uplift Add-on SDK. a=me

d8ba32821e...96ae8d914f
This commit is contained in:
Dave Townsend 2015-06-30 15:10:35 -07:00
parent 930c87a273
commit fe566acbe3
77 changed files with 1592 additions and 1751 deletions

View File

@ -29,7 +29,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk":
EXTRA_JS_MODULES.commonjs.sdk.deprecated += [
'source/lib/sdk/deprecated/api-utils.js',
'source/lib/sdk/deprecated/memory.js',
'source/lib/sdk/deprecated/sync-worker.js',
'source/lib/sdk/deprecated/unit-test-finder.js',
'source/lib/sdk/deprecated/unit-test.js',
@ -258,6 +257,10 @@ EXTRA_JS_MODULES.commonjs.sdk.content += [
'source/lib/sdk/content/worker.js',
]
EXTRA_JS_MODULES.commonjs.sdk.content.sandbox += [
'source/lib/sdk/content/sandbox/events.js',
]
EXTRA_JS_MODULES.commonjs.sdk['context-menu'] += [
'source/lib/sdk/context-menu/context.js',
'source/lib/sdk/context-menu/core.js',
@ -307,7 +310,6 @@ EXTRA_JS_MODULES.commonjs.sdk.input += [
EXTRA_JS_MODULES.commonjs.sdk.io += [
'source/lib/sdk/io/buffer.js',
'source/lib/sdk/io/byte-streams.js',
'source/lib/sdk/io/data.js',
'source/lib/sdk/io/file.js',
'source/lib/sdk/io/fs.js',
'source/lib/sdk/io/stream.js',
@ -453,7 +455,6 @@ EXTRA_JS_MODULES.commonjs.sdk.url += [
EXTRA_JS_MODULES.commonjs.sdk.util += [
'source/lib/sdk/util/array.js',
'source/lib/sdk/util/bond.js',
'source/lib/sdk/util/collection.js',
'source/lib/sdk/util/contract.js',
'source/lib/sdk/util/deprecate.js',

View File

@ -1,7 +1,7 @@
sudo: false
language: node_js
node_js:
- "0.10"
- "0.12"
env:
- JPM_FX_DEBUG=0

View File

@ -17,12 +17,13 @@ exports.run = function(type) {
return new Promise(function(resolve) {
type = type || "";
[
(!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
(!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
(/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"),
(!isDebug && /^(firefox-bin)?$/.test(type)) && require.resolve("../bin/node-scripts/test.firefox-bin"),
(!isDebug && /^(docs)?$/.test(type)) && require.resolve("../bin/node-scripts/test.docs"),
(!isDebug && /^(ini)?$/.test(type)) && require.resolve("../bin/node-scripts/test.ini"),
].sort().forEach(function(filepath) {
(/^(examples)?$/.test(type)) && require.resolve("../bin/node-scripts/test.examples"),
(!isDebug && /^(addons)?$/.test(type)) && require.resolve("../bin/node-scripts/test.addons"),
(!isDebug && /^(modules)?$/.test(type)) && require.resolve("../bin/node-scripts/test.modules"),
].forEach(function(filepath) {
filepath && mocha.addFile(filepath);
})

View File

@ -0,0 +1,37 @@
/* 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";
var fs = require("fs");
var Promise = require("promise");
var chai = require("chai");
var expect = chai.expect;
var normalizeBinary = require("fx-runner/lib/utils").normalizeBinary;
//var firefox_binary = process.env["JPM_FIREFOX_BINARY"] || normalizeBinary("nightly");
describe("Checking Firefox binary", function () {
it("using matching fx-runner version with jpm", function () {
var sdkPackageJSON = require("../../package.json");
var jpmPackageINI = require("jpm/package.json");
expect(sdkPackageJSON.devDependencies["fx-runner"]).to.be.equal(jpmPackageINI.dependencies["fx-runner"]);
});
it("exists", function (done) {
var useEnvVar = new Promise(function(resolve) {
resolve(process.env["JPM_FIREFOX_BINARY"]);
});
var firefox_binary = process.env["JPM_FIREFOX_BINARY"] ? useEnvVar : normalizeBinary("nightly");
firefox_binary.then(function(path) {
expect(path).to.be.ok;
fs.exists(path, function (exists) {
expect(exists).to.be.ok;
done();
});
})
});
});

View File

@ -11,6 +11,7 @@ var expect = chai.expect;
var ini = require("./update-ini");
var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
var packageINI = path.resolve("./test/jetpack-package.ini");
describe("Checking ini files", function () {
@ -20,7 +21,10 @@ describe("Checking ini files", function () {
if (err) {
throw err;
}
var text = data.toString();
// filter comments
var text = data.toString().split("\n").filter(function(line) {
return !/^\s*#/.test(line);
}).join("\n");
var expected = "";
ini.makeAddonIniContent()
@ -28,7 +32,32 @@ describe("Checking ini files", function () {
expected = contents;
setTimeout(function end() {
expect(expected.trim()).to.be.equal(text.trim());
expect(text.trim()).to.be.equal(expected.trim());
done();
});
});
});
});
it("Check test/jetpack-package.ini", function (done) {
fs.readFile(packageINI, function (err, data) {
if (err) {
throw err;
}
// filter comments
var text = data.toString().split("\n").filter(function(line) {
return !/^\s*#/.test(line);
}).join("\n");
var expected = "";
ini.makePackageIniContent()
.then(function(contents) {
expected = contents;
setTimeout(function end() {
expect(text.trim()).to.be.equal(expected.trim());
done();
});
});

View File

@ -11,6 +11,14 @@ var parser = require("ini-parser");
var addonINI = path.resolve("./test/addons/jetpack-addon.ini");
var addonsDir = path.resolve("./test/addons/");
var packageINI = path.resolve("./test/jetpack-package.ini");
var packageDir = path.resolve("./test/");
var packageIgnorables = [ "addons", "preferences" ];
var packageSupportFiles = [
"fixtures.js",
"test-context-menu.html",
"util.js"
]
function updateAddonINI() {
return new Promise(function(resolve) {
@ -32,16 +40,18 @@ function makeAddonIniContent() {
var result = {};
fs.readdir(addonsDir, function(err, files) {
// get a list of folders
var folders = files.filter(function(file) {
return fs.statSync(path.resolve(addonsDir, file)).isDirectory();
}).sort();
// copy any related data from the existing ini
folders.forEach(function(folder) {
var oldData = data[folder + ".xpi"];
result[folder] = oldData ? oldData : {};
});
// build ini file
// build a new ini file
var contents = [];
Object.keys(result).sort().forEach(function(key) {
contents.push("[" + key + ".xpi]");
@ -56,3 +66,76 @@ function makeAddonIniContent() {
});
}
exports.makeAddonIniContent = makeAddonIniContent;
function makePackageIniContent() {
return new Promise(function(resolve) {
var data = parser.parse(fs.readFileSync(packageINI, { encoding: "utf8" }).toString());
var result = {};
fs.readdir(packageDir, function(err, files) {
// get a list of folders
var folders = files.filter(function(file) {
var ignore = (packageIgnorables.indexOf(file) >= 0);
var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory();
return (isDir && !ignore);
}).sort();
// get a list of "test-"" files
var files = files.filter(function(file) {
var ignore = !/^test\-.*\.js$/i.test(file);
var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory();
return (!isDir && !ignore);
}).sort();
// get a list of the support files
var support_files = packageSupportFiles.map(function(file) {
return " " + file;
});
folders.forEach(function(folder) {
support_files.push(" " + folder + "/**");
});
support_files = support_files.sort();
// copy any related data from the existing ini
files.forEach(function(file) {
var oldData = data[file];
result[file] = oldData ? oldData : {};
});
// build a new ini file
var contents = [
"[DEFAULT]",
"support-files ="
];
support_files.forEach(function(support_file) {
contents.push(support_file);
});
contents.push("");
Object.keys(result).sort().forEach(function(key) {
contents.push("[" + key + "]");
Object.keys(result[key]).forEach(function(dataKey) {
contents.push(dataKey + " = " + result[key][dataKey]);
});
});
contents = contents.join("\n") + "\n";
return resolve(contents);
});
});
}
exports.makePackageIniContent = makePackageIniContent;
function updatePackageINI() {
return new Promise(function(resolve) {
console.log("Start updating " + packageINI);
makeAddonIniContent().
then(function(contents) {
fs.writeFileSync(packageINI, contents, { encoding: "utf8" });
console.log("Done updating " + packageINI);
resolve();
});
})
}
exports.updatePackageINI = updatePackageINI;

View File

@ -65,6 +65,9 @@ function run (cmd, options, p) {
if (p) {
proc.stdout.pipe(p.stdout);
}
else if (!isDebug) {
proc.stdout.pipe(DEFAULT_PROCESS.stdout);
}
else {
proc.stdout.on("data", function (data) {
data = (data || "") + "";

View File

@ -28,7 +28,11 @@ gulp.task('test:modules', function(done) {
});
gulp.task('test:ini', function(done) {
test("ini").catch(console.error).then(done);
require("./bin/jpm-test").run("ini").catch(console.error).then(done);
});
gulp.task('test:firefox-bin', function(done) {
require("./bin/jpm-test").run("firefox-bin").catch(console.error).then(done);
});
gulp.task('patch:clean', function(done) {
@ -38,7 +42,3 @@ gulp.task('patch:clean', function(done) {
gulp.task('patch:apply', function(done) {
patch.apply().catch(console.error).then(done);
});
gulp.task('update:ini', function(done) {
ini.updateAddonINI().catch(console.error).then(done);
});

View File

@ -1,19 +1,16 @@
/* 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 = {
"stability": "experimental"
};
const { Cc, Ci, components } = require("chrome");
const { Ci, components } = require("chrome");
const { parseStack, sourceURI } = require("toolkit/loader");
const { readURISync } = require("../net/url");
exports.sourceURI = sourceURI
function safeGetFileLine(path, line) {
try {
var scheme = require("../url").URL(path).scheme;

View File

@ -10,6 +10,7 @@ module.metadata = {
const { Class } = require('../core/heritage');
const { EventTarget } = require('../event/target');
const { on, off, emit } = require('../event/core');
const { events } = require('./sandbox/events');
const { requiresAddonGlobal } = require('./utils');
const { delay: async } = require('../lang/functional');
const { Ci, Cu, Cc } = require('chrome');
@ -20,8 +21,7 @@ const { merge } = require('../util/object');
const { getTabForContentWindow } = require('../tabs/utils');
const { getInnerId } = require('../window/utils');
const { PlainTextConsole } = require('../console/plain-text');
const { data } = require('../self');
const { isChildLoader } = require('../remote/core');
const { data } = require('../self');const { isChildLoader } = require('../remote/core');
// WeakMap of sandboxes so we can access private values
const sandboxes = new WeakMap();
@ -166,6 +166,7 @@ const WorkerSandbox = Class({
get top() top,
get parent() parent
});
// Use the Greasemonkey naming convention to provide access to the
// unwrapped window object so the content script can access document
// JavaScript values.
@ -261,6 +262,11 @@ const WorkerSandbox = Class({
win.console = con;
};
emit(events, "content-script-before-inserted", {
window: window,
worker: worker
});
// The order of `contentScriptFile` and `contentScript` evaluation is
// intentional, so programs can load libraries like jQuery from script URLs
// and use them in scripts.
@ -273,6 +279,7 @@ const WorkerSandbox = Class({
if (contentScriptFile)
importScripts.apply(null, [this].concat(contentScriptFile));
if (contentScript) {
evaluateIn(
this,

View File

@ -2,6 +2,11 @@
* 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/. */
exports.minimalTest = function(test) {
test.assert(true);
"use strict";
module.metadata = {
"stability": "experimental"
};
const events = {};
exports.events = events;

View File

@ -1,129 +0,0 @@
/* 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 = {
"stability": "deprecated"
};
const { Cc, Ci, Cu, components } = require("chrome");
const { when: unload } = require("../system/unload")
var trackedObjects = {};
const Compacter = {
notify: function() {
var newTrackedObjects = {};
for (let name in trackedObjects) {
let oldBin = trackedObjects[name];
let newBin = [];
let strongRefs = [];
for (let i = 0, l = oldBin.length; i < l; i++) {
let strongRef = oldBin[i].weakref.get();
if (strongRef && strongRefs.indexOf(strongRef) == -1) {
strongRefs.push(strongRef);
newBin.push(oldBin[i]);
}
}
if (newBin.length)
newTrackedObjects[name] = newBin;
}
trackedObjects = newTrackedObjects;
}
};
var timer = Cc["@mozilla.org/timer;1"]
.createInstance(Ci.nsITimer);
timer.initWithCallback(Compacter,
5000,
Ci.nsITimer.TYPE_REPEATING_SLACK);
function track(object, bin, stackFrameNumber) {
var frame = components.stack.caller;
var weakref = Cu.getWeakReference(object);
if (!bin && 'constructor' in object)
bin = object.constructor.name;
if (bin == "Object")
bin = frame.name;
if (!bin)
bin = "generic";
if (!(bin in trackedObjects))
trackedObjects[bin] = [];
if (stackFrameNumber > 0)
for (var i = 0; i < stackFrameNumber; i++)
frame = frame.caller;
trackedObjects[bin].push({weakref: weakref,
created: new Date(),
filename: frame.filename,
lineNo: frame.lineNumber,
bin: bin});
}
exports.track = track;
var getBins = exports.getBins = function getBins() {
var names = [];
for (let name in trackedObjects)
names.push(name);
return names;
};
function getObjects(bin) {
var results = [];
function getLiveObjectsInBin(bin) {
for (let i = 0, l = bin.length; i < l; i++) {
let object = bin[i].weakref.get();
if (object) {
results.push(bin[i]);
}
}
}
if (bin) {
if (bin in trackedObjects)
getLiveObjectsInBin(trackedObjects[bin]);
}
else {
for (let name in trackedObjects)
getLiveObjectsInBin(trackedObjects[name]);
}
return results;
}
exports.getObjects = getObjects;
function gc() {
// Components.utils.forceGC() doesn't currently perform
// cycle collection, which means that e.g. DOM elements
// won't be collected by it. Fortunately, there are
// other ways...
var test_utils = Cc["@mozilla.org/appshell/appShellService;1"]
.getService(Ci.nsIAppShellService)
.hiddenDOMWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
test_utils.garbageCollect();
// Clean metadata for dead objects
Compacter.notify();
// Not sure why, but sometimes it appears that we don't get
// them all with just one CC, so let's do it again.
test_utils.garbageCollect();
};
exports.gc = gc;
unload(_ => {
trackedObjects = {};
if (timer) {
timer.cancel();
timer = null;
}
});

View File

@ -30,7 +30,6 @@ const unload = require('../system/unload');
const events = require('../system/events');
const { getInnerId } = require("../window/utils");
const { WorkerSandbox } = require('../content/sandbox');
const { getTabForWindow } = require('../tabs/helpers');
const { isPrivate } = require('../private-browsing/utils');
// A weak map of workers to hold private attributes that
@ -118,14 +117,6 @@ const Worker = Class({
return model.window ? model.window.document.URL : null;
},
get tab () {
let model = modelFor(this);
// model.window will be null after detach
if (model.window)
return getTabForWindow(model.window);
return null;
},
// Implemented to provide some of the previous features of exposing sandbox
// so that Worker can be extended
getSandbox: function () {

View File

@ -8,7 +8,6 @@ module.metadata = {
};
const file = require("../io/file");
const memory = require('./memory');
const { Loader } = require("../test/loader");
const { isNative } = require('@loader/options');
@ -132,7 +131,6 @@ let loader = Loader(module);
const NOT_TESTS = ['setup', 'teardown'];
var TestFinder = exports.TestFinder = function TestFinder(options) {
memory.track(this);
this.filter = options.filter;
this.testInProcess = options.testInProcess === false ? false : true;
this.testOutOfProcess = options.testOutOfProcess === true ? true : false;

View File

@ -7,7 +7,6 @@ module.metadata = {
"stability": "deprecated"
};
const memory = require("./memory");
const timer = require("../timers");
const cfxArgs = require("../test/options");
const { getTabs, closeTab, getURI, getTabId, getSelectedTab } = require("../tabs/utils");
@ -47,7 +46,6 @@ const TestRunner = function TestRunner(options) {
this.fs = options.fs;
this.console = options.console || console;
memory.track(this);
this.passed = 0;
this.failed = 0;
this.testRunSummary = [];
@ -283,40 +281,46 @@ TestRunner.prototype = {
}
this.isDone = true;
this.pass("This test is done.");
if (this.test.teardown) {
this.test.teardown(this);
}
if (this.waitTimeout !== null) {
timer.clearTimeout(this.waitTimeout);
this.waitTimeout = null;
}
// Do not leave any callback set when calling to `waitUntil`
this.waitUntilCallback = null;
if (this.test.passed == 0 && this.test.failed == 0) {
this._logTestFailed("empty test");
if ("testMessage" in this.console) {
this.console.testMessage(false, false, this.test.name, "Empty test");
}
else {
this.console.error("fail:", "Empty test")
}
this.failed++;
this.test.failed++;
}
let wins = windows(null, { includePrivate: true });
let winPromises = wins.map(win => {
let { promise, resolve } = defer();
if (["interactive", "complete"].indexOf(win.document.readyState) >= 0) {
resolve()
}
else {
win.addEventListener("DOMContentLoaded", function onLoad() {
win.removeEventListener("DOMContentLoaded", onLoad, false);
resolve();
}, false);
}
return promise;
let winPromises = wins.map(win => {
return new Promise(resolve => {
if (["interactive", "complete"].indexOf(win.document.readyState) >= 0) {
resolve()
}
else {
win.addEventListener("DOMContentLoaded", function onLoad() {
win.removeEventListener("DOMContentLoaded", onLoad, false);
resolve();
}, false);
}
});
});
PromiseDebugging.flushUncaughtErrors();
@ -358,9 +362,17 @@ TestRunner.prototype = {
}
}
return null;
return failure;
}).
then(failure => {
if (!failure) {
this.pass("There was a clean UI.");
return null;
}
return cleanUI().then(() => {
this.pass("There is a clean UI.");
});
}).
then(cleanUI).
then(() => {
this.testRunSummary.push({
name: this.test.name,

View File

@ -1,90 +0,0 @@
/* 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 = {
"stability": "unstable"
};
const { Cc, Ci, Cu } = require("chrome");
const base64 = require("../base64");
const IOService = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
const { deprecateFunction } = require('../util/deprecate');
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm");
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
const FaviconService = Cc["@mozilla.org/browser/favicon-service;1"].
getService(Ci.nsIFaviconService);
const PNG_B64 = "data:image/png;base64,";
const DEF_FAVICON_URI = "chrome://mozapps/skin/places/defaultFavicon.png";
let DEF_FAVICON = null;
/**
* Takes URI of the page and returns associated favicon URI.
* If page under passed uri has no favicon then base64 encoded data URI of
* default faveicon is returned.
* @param {String} uri
* @returns {String}
*/
function getFaviconURIForLocation(uri) {
let pageURI = NetUtil.newURI(uri);
try {
return FaviconService.getFaviconDataAsDataURL(
FaviconService.getFaviconForPage(pageURI));
}
catch(e) {
if (!DEF_FAVICON) {
DEF_FAVICON = PNG_B64 +
base64.encode(getChromeURIContent(DEF_FAVICON_URI));
}
return DEF_FAVICON;
}
}
exports.getFaviconURIForLocation = getFaviconURIForLocation;
/**
* Takes chrome URI and returns content under that URI.
* @param {String} chromeURI
* @returns {String}
*/
function getChromeURIContent(chromeURI) {
let channel = IOService.newChannel2(chromeURI,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
let input = channel.open();
let stream = Cc["@mozilla.org/binaryinputstream;1"].
createInstance(Ci.nsIBinaryInputStream);
stream.setInputStream(input);
let content = stream.readBytes(input.available());
stream.close();
input.close();
return content;
}
exports.getChromeURIContent = deprecateFunction(getChromeURIContent,
'getChromeURIContent is deprecated, ' +
'please use require("sdk/net/url").readURI instead.'
);
/**
* Creates a base-64 encoded ASCII string from a string of binary data.
*/
exports.base64Encode = deprecateFunction(base64.encode,
'base64Encode is deprecated, ' +
'please use require("sdk/base64").encode instead.'
);
/**
* Decodes a string of data which has been encoded using base-64 encoding.
*/
exports.base64Decode = deprecateFunction(base64.decode,
'base64Dencode is deprecated, ' +
'please use require("sdk/base64").decode instead.'
);

View File

@ -1,17 +1,15 @@
/* 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 = {
"stability": "experimental"
};
const {Cc,Ci,Cu,components} = require("chrome");
var NetUtil = {};
Cu.import("resource://gre/modules/NetUtil.jsm", NetUtil);
NetUtil = NetUtil.NetUtil;
const { Cc, Ci, Cu, components } = require("chrome");
const { ensure } = require("../system/unload");
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
// NetUtil.asyncCopy() uses this buffer length, and since we call it, for best
// performance we use it, too.
@ -19,8 +17,6 @@ const BUFFER_BYTE_LEN = 0x8000;
const PR_UINT32_MAX = 0xffffffff;
const DEFAULT_CHARSET = "UTF-8";
exports.TextReader = TextReader;
exports.TextWriter = TextWriter;
/**
* An input stream that reads text from a backing stream using a given text
@ -35,7 +31,6 @@ exports.TextWriter = TextWriter;
* documentation on how to determine other valid values for this.
*/
function TextReader(inputStream, charset) {
const self = this;
charset = checkCharset(charset);
let stream = Cc["@mozilla.org/intl/converter-input-stream;1"].
@ -89,6 +84,7 @@ function TextReader(inputStream, charset) {
return str;
};
}
exports.TextReader = TextReader;
/**
* A buffered output stream that writes text to a backing stream using a given
@ -103,7 +99,6 @@ function TextReader(inputStream, charset) {
* for documentation on how to determine other valid values for this.
*/
function TextWriter(outputStream, charset) {
const self = this;
charset = checkCharset(charset);
let stream = outputStream;
@ -169,7 +164,7 @@ function TextWriter(outputStream, charset) {
this.writeAsync = function TextWriter_writeAsync(str, callback) {
manager.ensureOpened();
let istream = uconv.convertToInputStream(str);
NetUtil.asyncCopy(istream, stream, function (result) {
NetUtil.asyncCopy(istream, stream, (result) => {
let err = components.isSuccessCode(result) ? undefined :
new Error("An error occured while writing to the stream: " + result);
if (err)
@ -180,7 +175,7 @@ function TextWriter(outputStream, charset) {
if (typeof(callback) === "function") {
try {
callback.call(self, err);
callback.call(this, err);
}
catch (exc) {
console.exception(exc);
@ -189,34 +184,32 @@ function TextWriter(outputStream, charset) {
});
};
}
exports.TextWriter = TextWriter;
// This manages the lifetime of stream, a TextReader or TextWriter. It defines
// closed and close() on stream and registers an unload listener that closes
// rawStream if it's still opened. It also provides ensureOpened(), which
// throws an exception if the stream is closed.
function StreamManager(stream, rawStream) {
const self = this;
this.rawStream = rawStream;
this.opened = true;
/**
* True iff the stream is closed.
*/
stream.__defineGetter__("closed", function stream_closed() {
return !self.opened;
});
stream.__defineGetter__("closed", () => !this.opened);
/**
* Closes both the stream and its backing stream. If the stream is already
* closed, an exception is thrown. For TextWriters, this first flushes the
* backing stream's buffer.
*/
stream.close = function stream_close() {
self.ensureOpened();
self.unload();
stream.close = () => {
this.ensureOpened();
this.unload();
};
require("../system/unload").ensure(this);
ensure(this);
}
StreamManager.prototype = {

View File

@ -1,7 +1,6 @@
/* 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 = {
@ -13,7 +12,7 @@ module.metadata = {
};
const { Cc, Ci } = require('chrome');
const { defer, all, resolve } = require('../../core/promise');
const { all } = require('../../core/promise');
const { safeMerge, omit } = require('../../util/object');
const historyService = Cc['@mozilla.org/browser/nav-history-service;1']
.getService(Ci.nsINavHistoryService);
@ -45,13 +44,11 @@ const PLACES_PROPERTIES = [
];
function execute (queries, options) {
let deferred = defer();
let root = historyService
.executeQueries(queries, queries.length, options).root;
let items = collect([], root);
deferred.resolve(items);
return deferred.promise;
return new Promise(resolve => {
let root = historyService
.executeQueries(queries, queries.length, options).root;
resolve(collect([], root));
});
}
function collect (acc, node) {
@ -69,40 +66,35 @@ function collect (acc, node) {
}
function query (queries, options) {
queries = queries || [];
options = options || {};
let deferred = defer();
let optionsObj, queryObjs;
return new Promise((resolve, reject) => {
queries = queries || [];
options = options || {};
let optionsObj, queryObjs;
try {
optionsObj = historyService.getNewQueryOptions();
queryObjs = [].concat(queries).map(createQuery);
if (!queryObjs.length) {
queryObjs = [historyService.getNewQuery()];
}
safeMerge(optionsObj, options);
} catch (e) {
deferred.reject(e);
return deferred.promise;
}
/*
* Currently `places:` queries are not supported
*/
optionsObj.excludeQueries = true;
/*
* Currently `places:` queries are not supported
*/
optionsObj.excludeQueries = true;
execute(queryObjs, optionsObj).then(function (results) {
if (optionsObj.queryType === 0) {
return results.map(normalize);
} else if (optionsObj.queryType === 1) {
// Formats query results into more standard
// data structures for returning
return all(results.map(({itemId}) =>
send('sdk-places-bookmarks-get', { id: itemId })));
}
}).then(deferred.resolve, deferred.reject);
return deferred.promise;
execute(queryObjs, optionsObj).then((results) => {
if (optionsObj.queryType === 0) {
return results.map(normalize);
}
else if (optionsObj.queryType === 1) {
// Formats query results into more standard
// data structures for returning
return all(results.map(({itemId}) =>
send('sdk-places-bookmarks-get', { id: itemId })));
}
}).then(resolve, reject);
});
}
exports.query = query;
@ -140,7 +132,7 @@ function queryReceiver (message) {
/*
* Converts a nsINavHistoryResultNode into a plain object
*
*
* https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryResultNode
*/
function normalize (historyObj) {
@ -150,7 +142,8 @@ function normalize (historyObj) {
else if (prop === 'time') {
// Cast from microseconds to milliseconds
obj.time = Math.floor(historyObj.time / 1000)
} else if (prop === 'accessCount')
}
else if (prop === 'accessCount')
obj.visitCount = historyObj[prop];
else
obj[prop] = historyObj[prop];

View File

@ -51,14 +51,14 @@ exports.TreeNode = TreeNode;
/*
* Descends down from `node` applying `fn` to each in order.
* `fn` can return values or promises -- if promise returned,
* children are not processed until resolved. `fn` is passed
* children are not processed until resolved. `fn` is passed
* one argument, the current node, `curr`.
*/
function walk (curr, fn) {
return promised(fn)(curr).then(val => {
return all(curr.children.map(child => walk(child, fn)));
});
}
}
/*
* Descends from the TreeNode `node`, returning
@ -122,7 +122,7 @@ exports.isRootGroup = isRootGroup;
/*
* Merges appropriate options into query based off of url
* 4 scenarios:
*
*
* 'moz.com' // domain: moz.com, domainIsHost: true
* --> 'http://moz.com', 'http://moz.com/thunderbird'
* '*.moz.com' // domain: moz.com, domainIsHost: false
@ -177,9 +177,9 @@ function createQuery (type, query) {
let qObj = {
searchTerms: query.query
};
urlQueryParser(qObj, query.url);
// 0 === history
if (type === 0) {
// PRTime used by query is in microseconds, not milliseconds
@ -194,7 +194,7 @@ function createQuery (type, query) {
else if (type === 1) {
qObj.tags = query.tags;
qObj.folder = query.group && query.group.id;
}
}
// 2 === unified (not implemented on platform)
else if (type === 2) {

View File

@ -27,6 +27,9 @@ const metadata = options.metadata || {};
const permissions = metadata.permissions || {};
const isPacked = rootURI && rootURI.indexOf("jar:") === 0;
const isPrivateBrowsingSupported = 'private-browsing' in permissions &&
permissions['private-browsing'] === true;
const uri = (path="") =>
path.includes(":") ? path : addonDataURI + path.replace(/^\.\//, "");
@ -55,4 +58,4 @@ exports.data = Object.freeze({
return readURISync(uri(path));
}
});
exports.isPrivateBrowsingSupported = permissions['private-browsing'] === true;
exports.isPrivateBrowsingSupported = isPrivateBrowsingSupported;

View File

@ -14,16 +14,6 @@ module.metadata = {
const { getTabForContentWindow, getTabForBrowser: getRawTabForBrowser } = require('./utils');
const { modelFor } = require('../model/core');
function getTabForWindow(win) {
let tab = getTabForContentWindow(win);
// We were unable to find the related tab!
if (!tab)
return null;
return modelFor(tab);
}
exports.getTabForWindow = getTabForWindow;
exports.getTabForRawTab = modelFor;
function getTabForBrowser(browser) {

View File

@ -71,26 +71,6 @@ const Tab = Class({
},
set url(url) setTabURL(tabNS(this).tab, url),
/**
* URI of the favicon for the page currently loaded in this tab.
* @type {String}
*/
get favicon() {
/*
* Synchronous favicon services were never supported on Fennec,
* and as of FF22, are now deprecated. When/if favicon services
* are supported for Fennec, this getter should reference
* `require('sdk/places/favicon').getFavicon`
*/
console.error(
'tab.favicon is deprecated, and currently ' +
'favicon helpers are not yet supported by Fennec'
);
// return 16x16 blank default
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAEklEQVQ4jWNgGAWjYBSMAggAAAQQAAF/TXiOAAAAAElFTkSuQmCC';
},
getThumbnail: function() {
// TODO: implement!
console.error(ERR_FENNEC_MSG);

View File

@ -15,8 +15,6 @@ const { getBrowserForTab, setTabURL, getTabId, getTabURL, getTabForBrowser,
getTabs, getTabTitle, setTabTitle, getIndex, closeTab, reload, move,
activateTab, pin, unpin, isTab } = require('./utils');
const { isBrowser, getInnerId, isWindowPrivate } = require('../window/utils');
const { getFaviconURIForLocation } = require("../io/data");
const { deprecateUsage } = require('../util/deprecate');
const { getThumbnailURIForWindow, BLANK } = require("../content/thumbnail");
const { when } = require('../system/unload');
const { ignoreWindow, isPrivate } = require('../private-browsing/utils')
@ -96,14 +94,6 @@ const Tab = Class({
setTabURL(viewsFor.get(this), val);
},
get favicon() {
deprecateUsage(
'tab.favicon is deprecated, ' +
'please use require("sdk/places/favicon").getFavicon instead.'
);
return isDestroyed(this) ? undefined : getFaviconURIForLocation(this.url);
},
get contentType() {
return isDestroyed(this) ? undefined : browser(this).documentContentType;
},

View File

@ -15,7 +15,6 @@ const { PlainTextConsole } = require("../console/plain-text");
const { when: unload } = require("../system/unload");
const { format, fromException } = require("../console/traceback");
const system = require("../system");
const memory = require('../deprecated/memory');
const { gc: gcPromise } = require('./memory');
const { defer } = require('../core/promise');
const { extend } = require('../core/heritage');
@ -150,7 +149,7 @@ function reportMemoryUsage() {
return emptyPromise();
}
return gcPromise().then((function () {
return gcPromise().then((() => {
var mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
.getService(Ci.nsIMemoryReporterManager);
let count = 0;
@ -158,11 +157,6 @@ function reportMemoryUsage() {
print(((++count == 1) ? "\n" : "") + description + ": " + amount + "\n");
}
mgr.getReportsForThisProcess(logReporter, null, /* anonymize = */ false);
var weakrefs = [info.weakref.get()
for (info of memory.getObjects())];
weakrefs = [weakref for (weakref of weakrefs) if (weakref)];
print("Tracked memory objects in testing sandbox: " + weakrefs.length + "\n");
}));
}
@ -216,16 +210,6 @@ function showResults() {
function cleanup() {
let coverObject = {};
try {
for (let name in loader.modules)
memory.track(loader.modules[name],
"module global scope: " + name);
memory.track(loader, "Cuddlefish Loader");
if (profileMemory) {
gWeakrefInfo = [{ weakref: info.weakref, bin: info.bin }
for (info of memory.getObjects())];
}
loader.unload();
if (loader.globals.console.errorsLogged && !results.failed) {
@ -251,7 +235,7 @@ function cleanup() {
consoleListener.unregister();
memory.gc();
Cu.forceGC();
}
catch (e) {
results.failed++;
@ -278,7 +262,7 @@ function cleanup() {
}
function getPotentialLeaks() {
memory.gc();
Cu.forceGC();
// Things we can assume are part of the platform and so aren't leaks
let GOOD_BASE_URLS = [

View File

@ -4,17 +4,8 @@
'use strict';
const { Cu } = require("chrome");
const memory = require('../deprecated/memory');
const { defer } = require('../core/promise');
function gc() {
let { promise, resolve } = defer();
Cu.forceGC();
memory.gc();
Cu.schedulePreciseGC(_ => resolve());
return promise;
return new Promise(resolve => Cu.schedulePreciseGC(resolve));
}
exports.gc = gc;

View File

@ -1,36 +0,0 @@
/* 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 = {
"stability": "experimental"
};
const makeDescriptor = (name, method) => ({
get() {
if (!Object.hasOwnProperty.call(this, name)) {
Object.defineProperty(this, name, {value: method.bind(this)});
return this[name];
} else {
return method;
}
}
});
const Bond = function(methods) {
let descriptor = {};
let members = [...Object.getOwnPropertyNames(methods),
...Object.getOwnPropertySymbols(methods)];
for (let name of members) {
let method = methods[name];
if (typeof(method) !== "function") {
throw new TypeError(`Property named "${name}" passed to Bond must be a function`);
}
descriptor[name] = makeDescriptor(name, method);
}
return Object.create(Bond.prototype, descriptor);
}
exports.Bond = Bond;

View File

@ -1,7 +1,6 @@
/* 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 = {
@ -10,9 +9,7 @@ module.metadata = {
const { Class } = require('../core/heritage');
const { MatchPattern } = require('./match-pattern');
const { on, off, emit } = require('../event/core');
const { method } = require('../lang/functional');
const objectUtil = require('./object');
const { emit } = require('../event/core');
const { EventTarget } = require('../event/target');
const { List, addListItem, removeListItem } = require('./list');

View File

@ -1,22 +1,16 @@
/* 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';
"use strict";
const { Cc, Ci, Cu } = require("chrome");
const { defer } = require("../core/promise");
const { Cc, Ci } = require("chrome");
const getZipReader = function getZipReader(aFile) {
let { promise, resolve, reject } = defer();
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(Ci.nsIZipReader);
try {
function getZipReader(aFile) {
return new Promise(resolve => {
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(Ci.nsIZipReader);
zipReader.open(aFile);
}
catch(e){
reject(e);
}
resolve(zipReader);
return promise;
resolve(zipReader);
});
};
exports.getZipReader = getZipReader;

View File

@ -874,7 +874,8 @@ function Loader(options) {
metadata: {
addonID: options.id,
URI: "Addon-SDK"
}
},
prototype: options.sandboxPrototype || {}
});
}

View File

@ -13,7 +13,6 @@
"l10n/prefs": "sdk/l10n/prefs",
"list": "sdk/util/list",
"loader": "sdk/loader/loader",
"memory": "sdk/deprecated/memory",
"namespace": "sdk/core/namespace",
"preferences-service": "sdk/preferences/service",
"promise": "sdk/core/promise",

View File

@ -22,6 +22,7 @@
"async": "0.9.0",
"chai": "2.1.1",
"fs-extra": "0.18.2",
"fx-runner": "0.0.7",
"glob": "4.4.2",
"gulp": "3.8.11",
"ini-parser": "0.0.2",

View File

@ -236,10 +236,6 @@ parser_groups = (
help="Where to put the finished .xpi",
default=None,
cmds=['xpi'])),
(("", "--manifest-overload",), dict(dest="manifest_overload",
help="JSON file to overload package.json properties",
default=None,
cmds=['xpi'])),
(("", "--abort-on-missing-module",), dict(dest="abort_on_missing",
help="Abort if required module is missing",
action="store_true",
@ -661,10 +657,6 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
target_cfg_json = os.path.join(options.pkgdir, 'package.json')
target_cfg = packaging.get_config_in_dir(options.pkgdir)
if options.manifest_overload:
for k, v in packaging.load_json_file(options.manifest_overload).items():
target_cfg[k] = v
# At this point, we're either building an XPI or running Jetpack code in
# a Mozilla application (which includes running tests).

View File

@ -1,17 +0,0 @@
/* 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/. */
const { Cc, Ci } = require("chrome");
exports.main = function(options, callbacks) {
// Close Firefox window. Firefox should quit.
require("sdk/deprecated/window-utils").activeBrowserWindow.close();
// But not on Mac where it stay alive! We have to request application quit.
if (require("sdk/system/runtime").OS == "Darwin") {
let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
getService(Ci.nsIAppStartup);
appStartup.quit(appStartup.eAttemptQuit);
}
}

View File

@ -1,3 +0,0 @@
{
"version": "1.0-nightly"
}

View File

@ -1,6 +0,0 @@
{
"id": "simplest-test",
"directories": {
"lib": "."
}
}

View File

@ -182,35 +182,6 @@ class TestCfxQuits(unittest.TestCase):
container)
self.fail(standardMsg)
def test_cfx_run(self):
addon_path = os.path.join(tests_path,
"addons", "simplest-test")
rc, out, err = self.run_cfx(addon_path, ["run"])
self.assertEqual(rc, 0)
self.assertIn("Program terminated successfully.", err)
def test_cfx_test(self):
addon_path = os.path.join(tests_path, "addons", "simplest-test")
rc, out, err = self.run_cfx(addon_path, ["test"])
self.assertEqual(rc, 0)
self.assertIn("1 of 1 tests passed.", err)
self.assertIn("Program terminated successfully.", err)
def test_cfx_xpi(self):
addon_path = os.path.join(tests_path,
"addons", "simplest-test")
rc, out, err = self.run_cfx(addon_path, \
["xpi", "--manifest-overload", "manifest-overload.json"])
self.assertEqual(rc, 0)
# Ensure that the addon version from our manifest overload is used
# in install.rdf
xpi_path = os.path.join(addon_path, "simplest-test.xpi")
xpi = zipfile.ZipFile(xpi_path, "r")
manifest = xpi.read("install.rdf")
self.assertIn("<em:version>1.0-nightly</em:version>", manifest)
xpi.close()
os.remove(xpi_path)
def test_cfx_init(self):
# Create an empty test directory
addon_path = os.path.abspath(os.path.join(".test_tmp", "test-cfx-init"))
@ -232,7 +203,7 @@ class TestCfxQuits(unittest.TestCase):
# run cfx test
rc, out, err = self.run_cfx(addon_path, ["test"])
self.assertEqual(rc, 0)
self.assertIn("2 of 2 tests passed.", err)
self.assertIn("6 of 6 tests passed.", err)
self.assertIn("Program terminated successfully.", err)

View File

@ -6,3 +6,5 @@
self.port.on('echo', _ => {
self.port.emit('echo', '');
});
self.port.emit('start', '');

View File

@ -67,23 +67,31 @@ exports.testChromeLocale = function(assert) {
'locales en-US folder was copied correctly');
}
exports.testChromeInPanel = function(assert, done) {
exports.testChromeInPanel = function*(assert) {
let panel = Panel({
contentURL: 'chrome://test/content/panel.html',
contentScriptWhen: 'start',
contentScriptWhen: 'end',
contentScriptFile: data.url('panel.js')
});
panel.once('show', _ => {
assert.pass('panel shown');
panel.port.once('echo', _ => {
assert.pass('got echo');
panel.destroy();
assert.pass('panel is destroyed');
done();
});
yield new Promise(resolve => panel.port.once('start', resolve));
assert.pass('start was emitted');
yield new Promise(resolve => {
panel.once('show', resolve);
panel.show();
});
assert.pass('panel shown');
yield new Promise(resolve => {
panel.port.once('echo', resolve);
panel.port.emit('echo');
});
panel.show();
assert.pass('got echo');
panel.destroy();
assert.pass('panel is destroyed');
}
require('sdk/test/runner').runTestsFromModule(module);

View File

@ -1,122 +1,17 @@
/* 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 { getTabForWindow } = require('sdk/tabs/helpers');
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");
// The primary test tab
var primaryTab;
// We have an auxiliary tab to test background tabs.
var auxTab;
// The window for the outer iframe in the primary test page
var iframeWin;
exports["test GetTabForWindow"] = function(assert, done) {
assert.equal(getTabForWindow(windowUtils.activeWindow), null,
"getTabForWindow return null on topwindow");
assert.equal(getTabForWindow(windowUtils.activeBrowserWindow), null,
"getTabForWindow return null on topwindow");
let subSubDocument = encodeURIComponent(
'Sub iframe<br/>'+
'<iframe id="sub-sub-iframe" src="data:text/html;charset=utf-8,SubSubIframe" />');
let subDocument = encodeURIComponent(
'Iframe<br/>'+
'<iframe id="sub-iframe" src="data:text/html;charset=utf-8,'+subSubDocument+'" />');
let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(
'Content<br/><iframe id="iframe" src="data:text/html;charset=utf-8,'+subDocument+'" />');
// Open up a new tab in the background.
//
// This lets us test whether GetTabForWindow works even when the tab in
// question is not active.
tabs.open({
inBackground: true,
url: "about:mozilla",
onReady: function(tab) { auxTab = tab; step2(url, assert);},
onActivate: function(tab) { step3(assert, done); }
});
};
function step2(url, assert) {
tabs.open({
url: url,
onReady: function(tab) {
primaryTab = tab;
let window = windowUtils.activeBrowserWindow.content;
let matchedTab = getTabForWindow(window);
assert.equal(matchedTab, tab,
"We are able to find the tab with his content window object");
let timer = require("sdk/timers");
function waitForFrames() {
let iframe = window.document.getElementById("iframe");
if (!iframe) {
timer.setTimeout(waitForFrames, 100);
return;
}
iframeWin = iframe.contentWindow;
let subIframe = iframeWin.document.getElementById("sub-iframe");
if (!subIframe) {
timer.setTimeout(waitForFrames, 100);
return;
}
let subIframeWin = subIframe.contentWindow;
let subSubIframe = subIframeWin.document.getElementById("sub-sub-iframe");
if (!subSubIframe) {
timer.setTimeout(waitForFrames, 100);
return;
}
let subSubIframeWin = subSubIframe.contentWindow;
matchedTab = getTabForWindow(iframeWin);
assert.equal(matchedTab, tab,
"We are able to find the tab with an iframe window object");
matchedTab = getTabForWindow(subIframeWin);
assert.equal(matchedTab, tab,
"We are able to find the tab with a sub-iframe window object");
matchedTab = getTabForWindow(subSubIframeWin);
assert.equal(matchedTab, tab,
"We are able to find the tab with a sub-sub-iframe window object");
// Put our primary tab in the background and test again.
// The onActivate listener will take us to step3.
auxTab.activate();
}
waitForFrames();
}
});
}
function step3(assert, done) {
let matchedTab = getTabForWindow(iframeWin);
assert.equal(matchedTab, primaryTab,
"We get the correct tab even when it's in the background");
primaryTab.close(function () {
auxTab.close(function () { done();});
});
}
exports["test behavior on close"] = function(assert, done) {
tabs.open({
url: "about:mozilla",
onReady: function(tab) {
@ -156,7 +51,6 @@ exports["test viewFor(tab)"] = (assert, done) => {
tabs.open({ url: "about:mozilla" });
};
exports["test modelFor(xulTab)"] = (assert, done) => {
tabs.open({
url: "about:mozilla",

View File

@ -147,19 +147,9 @@ exports["test compatibility"] = function(assert) {
assert.equal(require("tabs/tab.js"),
require("sdk/tabs/tab"), "sdk/tabs/tab -> tabs/tab.js");
assert.equal(require("memory"),
require("sdk/deprecated/memory"), "sdk/deprecated/memory -> memory");
assert.equal(require("environment"),
require("sdk/system/environment"), "sdk/system/environment -> environment");
if (app.is("Firefox")) {
// This module fails on fennec because of favicon xpcom component
// being not implemented on it.
assert.equal(require("utils/data"),
require("sdk/io/data"), "sdk/io/data -> utils/data");
}
assert.equal(require("test/assert"),
require("sdk/test/assert"), "sdk/test/assert -> test/assert");

View File

@ -33,13 +33,6 @@ function invalidResolve (assert) {
}
exports.invalidResolve = invalidResolve;
function invalidReject (assert) {
return function (e) {
assert.fail('Reject state should not be called: ' + e);
};
}
exports.invalidReject = invalidReject;
// Removes all children of group
function clearBookmarks (group) {
group

View File

@ -24,7 +24,7 @@ const {
MENU, TOOLBAR, UNSORTED
} = require('sdk/places/bookmarks');
const {
invalidResolve, invalidReject, createTree,
invalidResolve, createTree,
compareWithHost, createBookmark, createBookmarkItem,
createBookmarkTree, addVisits, resetPlaces
} = require('./places-helper');
@ -369,28 +369,27 @@ exports.testPromisedSave = function (assert, done) {
}).then(done).catch(assert.fail);
};
exports.testPromisedErrorSave = function (assert, done) {
exports.testPromisedErrorSave = function*(assert) {
let bookmarks = [
{ title: 'moz1', url: 'http://moz1.com', type: 'bookmark'},
{ title: 'moz2', url: 'invalidurl', type: 'bookmark'},
{ title: 'moz3', url: 'http://moz3.com', type: 'bookmark'}
];
saveP(bookmarks).then(invalidResolve, reason => {
yield saveP(bookmarks).then(() => {
assert.fail("should not resolve");
}, reason => {
assert.ok(
/The `url` property must be a valid URL/.test(reason),
'Error event called with correct reason');
});
bookmarks[1].url = 'http://moz2.com';
return saveP(bookmarks);
}).
then(res => searchP({ query: 'moz' })).
then(res => {
assert.equal(res.length, 3, 'all 3 should be saved upon retry');
res.map(item => assert.ok(/moz\d\.com/.test(item.url), 'correct item'));
done();
}, invalidReject).
catch(assert.fail);
bookmarks[1].url = 'http://moz2.com';
yield saveP(bookmarks);
let res = yield searchP({ query: 'moz' });
assert.equal(res.length, 3, 'all 3 should be saved upon retry');
res.map(item => assert.ok(/moz\d\.com/.test(item.url), 'correct item'));
};
exports.testMovingChildren = function (assert, done) {
@ -692,61 +691,63 @@ exports.testSearchTags = function (assert, done) {
* 'http://mozilla.com/'
* 'http://mozilla.com/*'
*/
exports.testSearchURL = function (assert, done) {
createBookmarkTree().then(() => {
return searchP({ url: 'mozilla.org' });
}).then(data => {
assert.equal(data.length, 2, 'only URLs with host domain');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
return searchP({ url: '*.mozilla.org' });
}).then(data => {
assert.equal(data.length, 3, 'returns domain and when host is other than domain');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
assert.equal(data[2].url, 'http://developer.mozilla.org/en-US/');
return searchP({ url: 'http://mozilla.org' });
}).then(data => {
assert.equal(data.length, 1, 'only exact URL match');
assert.equal(data[0].url, 'http://mozilla.org/');
return searchP({ url: 'http://mozilla.org/*' });
}).then(data => {
assert.equal(data.length, 2, 'only URLs that begin with query');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
return searchP([{ url: 'mozilla.org' }, { url: 'component.fm' }]);
}).then(data => {
assert.equal(data.length, 3, 'returns URLs that match EITHER query');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
assert.equal(data[2].url, 'http://component.fm/');
}).then(done).catch(assert.fail);
exports.testSearchURLForBookmarks = function*(assert) {
yield createBookmarkTree()
let data = yield searchP({ url: 'mozilla.org' });
assert.equal(data.length, 2, 'only URLs with host domain');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
data = yield searchP({ url: '*.mozilla.org' });
assert.equal(data.length, 3, 'returns domain and when host is other than domain');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
assert.equal(data[2].url, 'http://developer.mozilla.org/en-US/');
data = yield searchP({ url: 'http://mozilla.org' });
assert.equal(data.length, 1, 'only exact URL match');
assert.equal(data[0].url, 'http://mozilla.org/');
data = yield searchP({ url: 'http://mozilla.org/*' });
assert.equal(data.length, 2, 'only URLs that begin with query');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
data = yield searchP([{ url: 'mozilla.org' }, { url: 'component.fm' }]);
assert.equal(data.length, 3, 'returns URLs that match EITHER query');
assert.equal(data[0].url, 'http://mozilla.org/');
assert.equal(data[1].url, 'http://mozilla.org/thunderbird/');
assert.equal(data[2].url, 'http://component.fm/');
};
/*
* Searches url, title, tags
*/
exports.testSearchQuery = function (assert, done) {
createBookmarkTree().then(() => {
return searchP({ query: 'thunder' });
}).then(data => {
assert.equal(data.length, 3);
assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
assert.equal(data[2].title, 'thunderbird', 'query matches tag, url, or title');
return searchP([{ query: 'rust' }, { query: 'component' }]);
}).then(data => {
// rust OR component
assert.equal(data.length, 3);
assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
assert.equal(data[2].title, 'web audio components', 'query matches tag, url, or title');
return searchP([{ query: 'moz', tags: ['javascript']}]);
}).then(data => {
assert.equal(data.length, 1);
assert.equal(data[0].title, 'mdn',
'only one item matches moz query AND has a javascript tag');
}).then(done).catch(assert.fail);
exports.testSearchQueryForBookmarks = function*(assert) {
yield createBookmarkTree();
let data = yield searchP({ query: 'thunder' });
assert.equal(data.length, 3);
assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
assert.equal(data[2].title, 'thunderbird', 'query matches tag, url, or title');
data = yield searchP([{ query: 'rust' }, { query: 'component' }]);
// rust OR component
assert.equal(data.length, 3);
assert.equal(data[0].title, 'mozilla.com', 'query matches tag, url, or title');
assert.equal(data[1].title, 'mozilla.org', 'query matches tag, url, or title');
assert.equal(data[2].title, 'web audio components', 'query matches tag, url, or title');
data = yield searchP([{ query: 'moz', tags: ['javascript']}]);
assert.equal(data.length, 1);
assert.equal(data[0].title, 'mdn',
'only one item matches moz query AND has a javascript tag');
};
/*
@ -827,7 +828,7 @@ exports.testSearchCount = function (assert, done) {
}
};
exports.testSearchSort = function (assert, done) {
exports.testSearchSortForBookmarks = function (assert, done) {
let urls = [
'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
'http://developer.mozilla.com/', 'http://bandcamp.com/'

View File

@ -27,7 +27,7 @@ const isOSX10_6 = (() => {
const { search } = require('sdk/places/history');
const {
invalidResolve, invalidReject, createTree, createBookmark,
invalidResolve, createTree, createBookmark,
compareWithHost, addVisits, resetPlaces, createBookmarkItem,
removeVisits, historyBatch
} = require('./places-helper');

View File

@ -19,45 +19,44 @@ const {
search
} = require('sdk/places/history');
const {
invalidResolve, invalidReject, createTree,
invalidResolve, createTree,
compareWithHost, addVisits, resetPlaces
} = require('./places-helper');
const { promisedEmitter } = require('sdk/places/utils');
exports.testEmptyQuery = function (assert, done) {
exports.testEmptyQuery = function*(assert) {
let within = toBeWithin();
addVisits([
yield addVisits([
'http://simplequery-1.com', 'http://simplequery-2.com'
]).then(searchP).then(results => {
assert.equal(results.length, 2, 'Correct number of entries returned');
assert.equal(results[0].url, 'http://simplequery-1.com/',
'matches url');
assert.equal(results[1].url, 'http://simplequery-2.com/',
'matches url');
assert.equal(results[0].title, 'Test visit for ' + results[0].url,
'title matches');
assert.equal(results[1].title, 'Test visit for ' + results[1].url,
'title matches');
assert.equal(results[0].visitCount, 1, 'matches access');
assert.equal(results[1].visitCount, 1, 'matches access');
assert.ok(within(results[0].time), 'accurate access time');
assert.ok(within(results[1].time), 'accurate access time');
assert.equal(Object.keys(results[0]).length, 4,
'no addition exposed properties on history result');
done();
}, invalidReject);
]);
let results = yield searchP();
assert.equal(results.length, 2, 'Correct number of entries returned');
assert.equal(results[0].url, 'http://simplequery-1.com/',
'matches url');
assert.equal(results[1].url, 'http://simplequery-2.com/',
'matches url');
assert.equal(results[0].title, 'Test visit for ' + results[0].url,
'title matches');
assert.equal(results[1].title, 'Test visit for ' + results[1].url,
'title matches');
assert.equal(results[0].visitCount, 1, 'matches access');
assert.equal(results[1].visitCount, 1, 'matches access');
assert.ok(within(results[0].time), 'accurate access time');
assert.ok(within(results[1].time), 'accurate access time');
assert.equal(Object.keys(results[0]).length, 4,
'no addition exposed properties on history result');
};
exports.testVisitCount = function (assert, done) {
addVisits([
exports.testVisitCount = function*(assert) {
yield addVisits([
'http://simplequery-1.com', 'http://simplequery-1.com',
'http://simplequery-1.com', 'http://simplequery-1.com'
]).then(searchP).then(results => {
assert.equal(results.length, 1, 'Correct number of entries returned');
assert.equal(results[0].url, 'http://simplequery-1.com/', 'correct url');
assert.equal(results[0].visitCount, 4, 'matches access count');
done();
}, invalidReject);
]);
let results = yield searchP();
assert.equal(results.length, 1, 'Correct number of entries returned');
assert.equal(results[0].url, 'http://simplequery-1.com/', 'correct url');
assert.equal(results[0].visitCount, 4, 'matches access count');
};
/*
@ -67,24 +66,23 @@ exports.testVisitCount = function (assert, done) {
* 'http://mozilla.org/'
* 'http://mozilla.org/*'
*/
exports.testSearchURL = function (assert, done) {
addVisits([
exports.testSearchURLForHistory = function*(assert) {
yield addVisits([
'http://developer.mozilla.org', 'http://mozilla.org',
'http://mozilla.org/index', 'https://mozilla.org'
]).then(() => searchP({ url: '*.mozilla.org' }))
.then(results => {
assert.equal(results.length, 4, 'returns all entries');
return searchP({ url: 'mozilla.org' });
}).then(results => {
assert.equal(results.length, 3, 'returns entries where mozilla.org is host');
return searchP({ url: 'http://mozilla.org/' });
}).then(results => {
assert.equal(results.length, 1, 'should just be an exact match');
return searchP({ url: 'http://mozilla.org/*' });
}).then(results => {
assert.equal(results.length, 2, 'should match anything starting with substring');
done();
});
]);
let results = yield searchP({ url: 'http://mozilla.org/' });
assert.equal(results.length, 1, 'should just be an exact match');
results = yield searchP({ url: '*.mozilla.org' });
assert.equal(results.length, 4, 'returns all entries');
results = yield searchP({ url: 'mozilla.org' });
assert.equal(results.length, 3, 'returns entries where mozilla.org is host');
results = yield searchP({ url: 'http://mozilla.org/*' });
assert.equal(results.length, 2, 'should match anything starting with substring');
};
// Disabling due to intermittent Bug 892619
@ -124,23 +122,21 @@ exports.testSearchTimeRange = function (assert, done) {
});
};
*/
exports.testSearchQuery = function (assert, done) {
addVisits([
exports.testSearchQueryForHistory = function*(assert) {
yield addVisits([
'http://mozilla.com', 'http://webaud.io', 'http://mozilla.com/webfwd'
]).then(() => {
return searchP({ query: 'moz' });
}).then(results => {
assert.equal(results.length, 2, 'should return urls that match substring');
results.map(({url}) => {
assert.ok(/moz/.test(url), 'correct item');
});
return searchP([{ query: 'webfwd' }, { query: 'aud.io' }]);
}).then(results => {
assert.equal(results.length, 2, 'should OR separate queries');
results.map(({url}) => {
assert.ok(/webfwd|aud\.io/.test(url), 'correct item');
});
done();
]);
let results = yield searchP({ query: 'moz' });
assert.equal(results.length, 2, 'should return urls that match substring');
results.map(({url}) => {
assert.ok(/moz/.test(url), 'correct item');
});
results = yield searchP([{ query: 'webfwd' }, { query: 'aud.io' }]);
assert.equal(results.length, 2, 'should OR separate queries');
results.map(({url}) => {
assert.ok(/webfwd|aud\.io/.test(url), 'correct item');
});
};
@ -168,51 +164,50 @@ exports.testSearchCount = function (assert, done) {
}
};
exports.testSearchSort = function (assert, done) {
let places = [
'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
'http://developer.mozilla.com/', 'http://bandcamp.com/'
];
addVisits(places).then(() => {
return searchP({}, { sort: 'title' });
}).then(results => {
checkOrder(results, [4,3,0,2,1]);
return searchP({}, { sort: 'title', descending: true });
}).then(results => {
checkOrder(results, [1,2,0,3,4]);
return searchP({}, { sort: 'url' });
}).then(results => {
checkOrder(results, [4,3,0,2,1]);
return searchP({}, { sort: 'url', descending: true });
}).then(results => {
checkOrder(results, [1,2,0,3,4]);
return addVisits('http://mozilla.com') // for visit conut
.then(() => addVisits('http://github.com')); // for checking date
}).then(() => {
return searchP({}, { sort: 'visitCount' });
}).then(results => {
assert.equal(results[5].url, 'http://mozilla.com/',
'last entry is the highest visit count');
return searchP({}, { sort: 'visitCount', descending: true });
}).then(results => {
assert.equal(results[0].url, 'http://mozilla.com/',
'first entry is the highest visit count');
return searchP({}, { sort: 'date' });
}).then(results => {
assert.equal(results[5].url, 'http://github.com/',
'latest visited should be first');
return searchP({}, { sort: 'date', descending: true });
}).then(results => {
assert.equal(results[0].url, 'http://github.com/',
'latest visited should be at the end');
}).then(done);
exports.testSearchSortForHistory = function*(assert) {
function checkOrder (results, nums) {
assert.equal(results.length, nums.length, 'expected return count');
for (let i = 0; i < nums.length; i++) {
assert.equal(results[i].url, places[nums[i]], 'successful order');
}
}
let places = [
'http://mozilla.com/', 'http://webaud.io/', 'http://mozilla.com/webfwd/',
'http://developer.mozilla.com/', 'http://bandcamp.com/'
];
yield addVisits(places);
let results = yield searchP({}, { sort: 'title' });
checkOrder(results, [4,3,0,2,1]);
results = yield searchP({}, { sort: 'title', descending: true });
checkOrder(results, [1,2,0,3,4]);
results = yield searchP({}, { sort: 'url' });
checkOrder(results, [4,3,0,2,1]);
results = yield searchP({}, { sort: 'url', descending: true });
checkOrder(results, [1,2,0,3,4]);
yield addVisits('http://mozilla.com'); // for visit conut
yield addVisits('http://github.com'); // for checking date
results = yield searchP({}, { sort: 'visitCount' });
assert.equal(results[5].url, 'http://mozilla.com/',
'last entry is the highest visit count');
results = yield searchP({}, { sort: 'visitCount', descending: true });
assert.equal(results[0].url, 'http://mozilla.com/',
'first entry is the highest visit count');
results = yield searchP({}, { sort: 'date' });
assert.equal(results[5].url, 'http://github.com/',
'latest visited should be first');
results = yield searchP({}, { sort: 'date', descending: true });
assert.equal(results[0].url, 'http://github.com/',
'latest visited should be at the end');
};
exports.testEmitters = function (assert, done) {

View File

@ -21,7 +21,7 @@ require('sdk/places/host/host-bookmarks');
require('sdk/places/host/host-tags');
require('sdk/places/host/host-query');
const {
invalidResolve, invalidReject, createTree,
invalidResolve, createTree,
compareWithHost, createBookmark, createBookmarkTree, resetPlaces
} = require('./places-helper');
@ -32,7 +32,7 @@ const hsrv = Cc['@mozilla.org/browser/nav-history-service;1'].
const tagsrv = Cc['@mozilla.org/browser/tagging-service;1'].
getService(Ci.nsITaggingService);
exports.testBookmarksCreate = function (assert, done) {
exports.testBookmarksCreate = function*(assert) {
let items = [{
title: 'my title',
url: 'http://test-places-host.com/testBookmarksCreate/',
@ -47,13 +47,11 @@ exports.testBookmarksCreate = function (assert, done) {
group: bmsrv.unfiledBookmarksFolder
}];
all(items.map(function (item) {
return send('sdk-places-bookmarks-create', item).then(function (data) {
yield all(items.map((item) => {
return send('sdk-places-bookmarks-create', item).then((data) => {
compareWithHost(assert, data);
}, invalidReject(assert));
})).then(function () {
done();
}, invalidReject(assert));
});
}));
};
exports.testBookmarksCreateFail = function (assert, done) {

View File

@ -1,5 +1,6 @@
/* 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";
exports.local = true;

View File

@ -6,10 +6,10 @@
var { isNative } = require("@loader/options");
exports["test local vs sdk module"] = function (assert) {
assert.notEqual(require("memory"),
require("sdk/deprecated/memory"),
assert.notEqual(require("list"),
require("sdk/util/list"),
"Local module takes the priority over sdk modules");
assert.ok(require("memory").local,
assert.ok(require("list").local,
"this module is really the local one");
}

View File

@ -9,5 +9,10 @@
</head>
<body>
<p>This is an add-on page test!</p>
<script>
function getTestURL() {
return window.document.documentURI + "";
}
</script>
</body>
</html>

View File

@ -4,3 +4,4 @@
'use strict';
exports.console = console;
exports.globalFoo = (typeof globalFoo !== "undefined") ? globalFoo : null;

View File

@ -0,0 +1,21 @@
<!-- 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/. -->
<html>
<head>
<meta charset="UTF-8">
<title>Worker test</title>
</head>
<body>
<p id="paragraph">Lorem ipsum dolor sit amet.</p>
<script>
if ("addon" in window) {
var count = 1;
addon.port.on("get-result", () => {
addon.port.emit("result" + count++, extras.test().getTestURL())
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,31 @@
<!-- 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/. -->
<html>
<head>
<meta charset="UTF-8">
<title>Worker test</title>
</head>
<body>
<p id="paragraph">Lorem ipsum dolor sit amet.</p>
<script>
if ("addon" in window) {
var count = 1;
addon.port.on("get-result", () => {
console.log("get-result recieved");
addon.port.emit("result" + count++, extras && extras.test())
});
}
window.addEventListener("message", function getMessage({ data }) {
if (data.name == "start") {
window.postMessage({
name: "extras",
result: window.extras === undefined
}, '*');
}
}, false);
</script>
</body>
</html>

View File

@ -9,5 +9,17 @@
</head>
<body>
<p>bar</p>
<script>
function getTestURL() {
return window.document.documentURI + "";
}
function changesInWindow() {
window.document.documentElement.setAttribute('test', 'changes in window');
return null;
}
function getAUQLUE() {
return "AUQLUE" in window;
}
</script>
</body>
</html>

View File

@ -4,26 +4,27 @@ support-files =
commonjs-test-adapter/**
context-menu/**
event/**
fixtures.js
fixtures/**
framescript-manager/**
framescript-util/**
loader/**
lib/**
loader/**
modules/**
page-mod/**
path/**
private-browsing/**
querystring/**
sidebar/**
tabs/**
test-context-menu.html
traits/**
util.js
windows/**
zip/**
fixtures.js
pagemod-test-helpers.js
test-context-menu.html
util.js
[test-addon-bootstrap.js]
[test-addon-extras.js]
[test-addon-installer.js]
[test-addon-window.js]
[test-api-utils.js]
@ -33,7 +34,6 @@ support-files =
[test-browser-events.js]
[test-buffer.js]
[test-byte-streams.js]
[test-bond.js]
[test-child_process.js]
[test-chrome.js]
[test-clipboard.js]
@ -72,19 +72,20 @@ skip-if = true
[test-hotkeys.js]
[test-httpd.js]
[test-indexed-db.js]
[test-jetpack-id.js]
[test-keyboard-observer.js]
[test-keyboard-utils.js]
[test-lang-type.js]
[test-l10n-locale.js]
[test-l10n-plural-rules.js]
[test-lang-type.js]
[test-libxul.js]
[test-list.js]
[test-loader.js]
[test-match-pattern.js]
[test-memory.js]
[test-method.js]
[test-module.js]
[test-modules.js]
[test-mozilla-toolkit-versioning.js]
[test-mpl2-license-header.js]
skip-if = true
[test-namespace.js]
@ -95,6 +96,7 @@ skip-if = true
[test-notifications.js]
[test-object.js]
[test-observers.js]
[test-page-mod-debug.js]
[test-page-mod.js]
[test-page-worker.js]
[test-panel.js]
@ -116,6 +118,7 @@ skip-if = true
[test-self.js]
[test-sequence.js]
[test-set-exports.js]
[test-shared-require.js]
[test-simple-prefs.js]
[test-simple-storage.js]
[test-system-events.js]

View File

@ -0,0 +1,11 @@
/* 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";
// Test module to check presense of user defined globals.
// Related to bug 827792.
exports.getCom = function() {
return com;
};

View File

@ -9,7 +9,7 @@ const { Loader } = require("sdk/test/loader");
const { openTab, getBrowserForTab, closeTab } = require("sdk/tabs/utils");
const { getMostRecentBrowserWindow } = require("sdk/window/utils");
const { merge } = require("sdk/util/object");
const httpd = require("./lib/httpd");
const httpd = require("../lib/httpd");
const { cleanUI } = require("sdk/test/utils");
const PORT = 8099;
@ -17,7 +17,7 @@ const PATH = '/test-contentScriptWhen.html';
function createLoader () {
let options = merge({}, require('@loader/options'),
{ id: "testloader", prefixURI: require('./fixtures').url() });
{ id: "testloader", prefixURI: require('../fixtures').url() });
return Loader(module, null, options);
}
exports.createLoader = createLoader;
@ -32,7 +32,7 @@ exports.openNewTab = openNewTab;
// an evil function enables the creation of tests
// that depend on delicate event timing. do not use.
function testPageMod(assert, done, testURL, pageModOptions,
testCallback, timeout) {
testCallback, timeout) {
let loader = createLoader();
let { PageMod } = loader.require("sdk/page-mod");
let pageMods = [new PageMod(opts) for each (opts in pageModOptions)];
@ -46,7 +46,7 @@ function testPageMod(assert, done, testURL, pageModOptions,
// If we delay even more contentScriptWhen:'end', we may want to modify
// this code again.
setTimeout(testCallback, timeout,
b.contentWindow.wrappedJSObject,
b.contentWindow.wrappedJSObject, // TODO: remove this CPOW
function () {
pageMods.forEach(function(mod) mod.destroy());
// XXX leaks reported if we don't close the tab?

View File

@ -11,6 +11,7 @@ const { browserWindows: windows } = require('sdk/windows');
const { defer } = require('sdk/core/promise');
const tabs = require('sdk/tabs');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
const { cleanUI } = require("sdk/test/utils");
// test openDialog() from window/utils with private option
// test isActive state in pwpb case
@ -42,15 +43,18 @@ exports.testPerWindowPrivateBrowsingGetter = function*(assert) {
yield close(win)
}
exports.testIsPrivateOnWindowOpen = function(assert, done) {
windows.open({
isPrivate: true,
onOpen: function(window) {
assert.equal(isPrivate(window), false, 'isPrivate for a window is true when it should be');
assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
window.close(done);
}
exports.testIsPrivateOnWindowOpen = function*(assert) {
let window = yield new Promise(resolve => {
windows.open({
isPrivate: true,
onOpen: resolve
});
});
assert.equal(isPrivate(window), false, 'isPrivate for a window is true when it should be');
assert.equal(isPrivate(window.tabs[0]), false, 'isPrivate for a tab is false when it should be');
yield cleanUI();
}
exports.testIsPrivateOnWindowOpenFromPrivate = function(assert, done) {

View File

@ -98,10 +98,6 @@ exports.testAutomaticDestroy = function(assert, done) {
// TEST: tab properties
exports.testTabProperties = function(assert, done) {
setPref(DEPRECATE_PREF, true);
let { loader, messages } = LoaderWithHookedConsole();
let tabs = loader.require('sdk/tabs');
let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
let tabsLen = tabs.length;
tabs.open({
@ -109,13 +105,6 @@ exports.testTabProperties = function(assert, done) {
onReady: function(tab) {
assert.equal(tab.title, "foo", "title of the new tab matches");
assert.equal(tab.url, url, "URL of the new tab matches");
assert.ok(tab.favicon, "favicon of the new tab is not empty");
// TODO: remove need for this test by implementing the favicon feature
assert.equal(messages[0].msg,
"tab.favicon is deprecated, and " +
"currently favicon helpers are not yet supported " +
"by Fennec",
"favicon logs an error for now");
assert.equal(tab.style, null, "style of the new tab matches");
assert.equal(tab.index, tabsLen, "index of the new tab matches");
assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");

View File

@ -12,12 +12,16 @@ const { viewFor } = require('sdk/view/core');
const { getOwnerWindow } = require('sdk/tabs/utils');
const { windows, onFocus, getMostRecentBrowserWindow } = require('sdk/window/utils');
const { open, focus, close } = require('sdk/window/helpers');
const { observer: windowObserver } = require("sdk/windows/observer");
const tabs = require('sdk/tabs');
const { browserWindows } = require('sdk/windows');
const { set: setPref } = require("sdk/preferences/service");
const { set: setPref, get: getPref, reset: resetPref } = require("sdk/preferences/service");
const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
const OPEN_IN_NEW_WINDOW_PREF = 'browser.link.open_newwindow';
const DISABLE_POPUP_PREF = 'dom.disable_open_during_load';
const fixtures = require("../fixtures");
const { base64jpeg } = fixtures;
const { cleanUI, before, after } = require("sdk/test/utils");
// Bug 682681 - tab.title should never be empty
exports.testBug682681_aboutURI = function(assert, done) {
@ -160,11 +164,8 @@ exports.testAutomaticDestroyEventClose = function(assert, done) {
};
exports.testTabPropertiesInNewWindow = function(assert, done) {
let warning = "DEPRECATED: tab.favicon is deprecated, please use require(\"sdk/places/favicon\").getFavicon instead.\n"
const { LoaderWithFilteredConsole } = require("sdk/test/loader");
let loader = LoaderWithFilteredConsole(module, function(type, message) {
if (type == "error" && message.substring(0, warning.length) == warning)
return false;
return true;
});
@ -185,7 +186,7 @@ exports.testTabPropertiesInNewWindow = function(assert, done) {
onReady: function(tab) {
assert.equal(tab.title, "foo", "title of the new tab matches");
assert.equal(tab.url, url, "URL of the new tab matches");
assert.ok(tab.favicon, "favicon of the new tab is not empty");
assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
assert.equal(tab.style, null, "style of the new tab matches");
assert.equal(tab.index, 0, "index of the new tab matches");
assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
@ -196,7 +197,7 @@ exports.testTabPropertiesInNewWindow = function(assert, done) {
onLoad: function(tab) {
assert.equal(tab.title, "foo", "title of the new tab matches");
assert.equal(tab.url, url, "URL of the new tab matches");
assert.ok(tab.favicon, "favicon of the new tab is not empty");
assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
assert.equal(tab.style, null, "style of the new tab matches");
assert.equal(tab.index, 0, "index of the new tab matches");
assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
@ -208,11 +209,8 @@ exports.testTabPropertiesInNewWindow = function(assert, done) {
};
exports.testTabPropertiesInSameWindow = function(assert, done) {
let warning = "DEPRECATED: tab.favicon is deprecated, please use require(\"sdk/places/favicon\").getFavicon instead.\n"
const { LoaderWithFilteredConsole } = require("sdk/test/loader");
let loader = LoaderWithFilteredConsole(module, function(type, message) {
if (type == "error" && message.substring(0, warning.length) == warning)
return false;
return true;
});
@ -234,7 +232,7 @@ exports.testTabPropertiesInSameWindow = function(assert, done) {
onReady: function(tab) {
assert.equal(tab.title, "foo", "title of the new tab matches");
assert.equal(tab.url, url, "URL of the new tab matches");
assert.ok(tab.favicon, "favicon of the new tab is not empty");
assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
assert.equal(tab.style, null, "style of the new tab matches");
assert.equal(tab.index, tabCount, "index of the new tab matches");
assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
@ -245,7 +243,7 @@ exports.testTabPropertiesInSameWindow = function(assert, done) {
onLoad: function(tab) {
assert.equal(tab.title, "foo", "title of the new tab matches");
assert.equal(tab.url, url, "URL of the new tab matches");
assert.ok(tab.favicon, "favicon of the new tab is not empty");
assert.equal(tab.favicon, undefined, "favicon of the new tab is undefined");
assert.equal(tab.style, null, "style of the new tab matches");
assert.equal(tab.index, tabCount, "index of the new tab matches");
assert.notEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
@ -372,31 +370,28 @@ exports.testTabMove = function(assert, done) {
}).then(null, assert.fail);
};
exports.testIgnoreClosing = function(assert, done) {
let originalWindow = viewFor(browserWindows.activeWindow);
openBrowserWindow(function(window, browser) {
onFocus(window).then(() => {
let url = "data:text/html;charset=utf-8,foobar";
exports.testIgnoreClosing = function*(assert) {
let url = "data:text/html;charset=utf-8,foobar";
let originalWindow = getMostRecentBrowserWindow();
assert.equal(tabs.length, 2, "should be two windows open each with one tab");
let window = yield open().then(focus);
tabs.on('ready', function onReady(tab) {
tabs.removeListener('ready', onReady);
assert.equal(tabs.length, 2, "should be two windows open each with one tab");
let win = tab.window;
assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
assert.equal(tabs.length, 3, "should be three tabs in total");
yield new Promise(resolve => {
tabs.once("ready", (tab) => {
let win = tab.window;
assert.equal(win.tabs.length, 2, "should be two tabs in the new window");
assert.equal(tabs.length, 3, "should be three tabs in total");
tab.close(function() {
assert.equal(win.tabs.length, 1, "should be one tab in the new window");
assert.equal(tabs.length, 2, "should be two tabs in total");
close(window).then(onFocus(originalWindow)).then(done).then(null, assert.fail);
});
tab.close(() => {
assert.equal(win.tabs.length, 1, "should be one tab in the new window");
assert.equal(tabs.length, 2, "should be two tabs in total");
resolve();
});
tabs.open(url);
});
tabs.open(url);
});
};
@ -537,23 +532,23 @@ exports.testTabsEvent_onOpen = function(assert, done) {
};
// TEST: onClose event handler
exports.testTabsEvent_onClose = function(assert, done) {
open().then(focus).then(window => {
let url = "data:text/html;charset=utf-8,onclose";
let eventCount = 0;
exports.testTabsEvent_onClose = function*(assert) {
let window = yield open().then(focus);
let url = "data:text/html;charset=utf-8,onclose";
let eventCount = 0;
// add listener via property assignment
function listener1(tab) {
eventCount++;
}
tabs.on('close', listener1);
// add listener via property assignment
function listener1(tab) {
eventCount++;
}
tabs.on("close", listener1);
yield new Promise(resolve => {
// add listener via collection add
tabs.on('close', function listener2(tab) {
tabs.on("close", function listener2(tab) {
assert.equal(++eventCount, 2, "both listeners notified");
tabs.removeListener('close', listener1);
tabs.removeListener('close', listener2);
close(window).then(done).then(null, assert.fail);
tabs.removeListener("close", listener2);
resolve();
});
tabs.on('ready', function onReady(tab) {
@ -562,7 +557,13 @@ exports.testTabsEvent_onClose = function(assert, done) {
});
tabs.open(url);
}).then(null, assert.fail);
});
tabs.removeListener("close", listener1);
assert.pass("done test!");
yield close(window);
assert.pass("window was closed!");
};
// TEST: onClose event handler when a window is closed
@ -671,32 +672,38 @@ exports.testTabsEvent_onActivate = function(assert, done) {
};
// onDeactivate event handler
exports.testTabsEvent_onDeactivate = function(assert, done) {
open().then(focus).then(window => {
let url = "data:text/html;charset=utf-8,ondeactivate";
let eventCount = 0;
exports.testTabsEvent_onDeactivate = function*(assert) {
let window = yield open().then(focus);
// add listener via property assignment
function listener1(tab) {
eventCount++;
};
tabs.on('deactivate', listener1);
let url = "data:text/html;charset=utf-8,ondeactivate";
let eventCount = 0;
// add listener via property assignment
function listener1(tab) {
eventCount++;
assert.pass("listener1 was called " + eventCount);
};
tabs.on('deactivate', listener1);
yield new Promise(resolve => {
// add listener via collection add
tabs.on('deactivate', function listener2(tab) {
assert.equal(++eventCount, 2, "both listeners notified");
tabs.removeListener('deactivate', listener1);
tabs.removeListener('deactivate', listener2);
close(window).then(done).then(null, assert.fail);
resolve();
});
tabs.on('open', function onOpen(tab) {
assert.pass("tab opened");
tabs.removeListener('open', onOpen);
tabs.open("data:text/html;charset=utf-8,foo");
});
tabs.open(url);
}).then(null, assert.fail);
});
tabs.removeListener('deactivate', listener1);
assert.pass("listeners were removed");
};
// pinning
@ -726,13 +733,16 @@ exports.testTabsEvent_pinning = function(assert, done) {
};
// TEST: per-tab event handlers
exports.testPerTabEvents = function(assert, done) {
open().then(focus).then(window => {
let eventCount = 0;
exports.testPerTabEvents = function*(assert) {
let window = yield open().then(focus);
let eventCount = 0;
let tab = yield new Promise(resolve => {
tabs.open({
url: "data:text/html;charset=utf-8,foo",
onOpen: function(tab) {
onOpen: (tab) => {
assert.pass("the tab was opened");
// add listener via property assignment
function listener1() {
eventCount++;
@ -741,14 +751,18 @@ exports.testPerTabEvents = function(assert, done) {
// add listener via collection add
tab.on('ready', function listener2() {
assert.equal(eventCount, 1, "both listeners notified");
assert.equal(eventCount, 1, "listener1 called before listener2");
tab.removeListener('ready', listener1);
tab.removeListener('ready', listener2);
close(window).then(done).then(null, assert.fail);
assert.pass("removed listeners");
eventCount++;
resolve();
});
}
});
}).then(null, assert.fail);
});
assert.equal(eventCount, 2, "both listeners were notified.");
};
exports.testAttachOnOpen = function (assert, done) {
@ -1038,29 +1052,6 @@ exports.testOnLoadEventWithImage = function(assert, done) {
});
};
exports.testFaviconGetterDeprecation = function (assert, done) {
setPref(DEPRECATE_PREF, true);
const { LoaderWithHookedConsole } = require("sdk/test/loader");
let { loader, messages } = LoaderWithHookedConsole(module);
let tabs = loader.require('sdk/tabs');
tabs.open({
url: 'data:text/html;charset=utf-8,',
onOpen: function (tab) {
let favicon = tab.favicon;
assert.equal(messages.length, 1, 'only one error is dispatched');
assert.ok(messages[0].type, 'error', 'the console message is an error');
let msg = messages[0].msg;
assert.ok(msg.indexOf('tab.favicon is deprecated') !== -1,
'message contains the given message');
tab.close(done);
loader.unload();
}
});
}
exports.testNoDeadObjects = function(assert, done) {
let loader = Loader(module);
let myTabs = loader.require("sdk/tabs");
@ -1203,6 +1194,56 @@ exports.testTabDestroy = function(assert, done) {
})
};
// related to bug 942511
// https://bugzilla.mozilla.org/show_bug.cgi?id=942511
exports['test active tab properties defined on popup closed'] = function (assert, done) {
setPref(OPEN_IN_NEW_WINDOW_PREF, 2);
setPref(DISABLE_POPUP_PREF, false);
let tabID = "";
let popupClosed = false;
tabs.open({
url: 'about:blank',
onReady: function (tab) {
tabID = tab.id;
tab.attach({
contentScript: 'var popup = window.open("about:blank");' +
'popup.close();'
});
windowObserver.once('close', () => {
popupClosed = true;
});
windowObserver.on('activate', () => {
// Only when the 'activate' event is fired after the popup was closed.
if (popupClosed) {
popupClosed = false;
let activeTabID = tabs.activeTab.id;
if (activeTabID) {
assert.equal(tabID, activeTabID, 'ActiveTab properties are correct');
}
else {
assert.fail('ActiveTab properties undefined on popup closed');
}
tab.close(done);
}
});
}
});
};
after(exports, function*(name, assert) {
resetPopupPrefs();
yield cleanUI();
});
const resetPopupPrefs = () => {
resetPref(OPEN_IN_NEW_WINDOW_PREF);
resetPref(DISABLE_POPUP_PREF);
};
/******************* helpers *********************/
// Utility function to open a new browser window.

View File

@ -0,0 +1,171 @@
/* 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 { Ci, Cu, Cc, components } = require("chrome");
const self = require("sdk/self");
const { before, after } = require("sdk/test/utils");
const fixtures = require("./fixtures");
const { Loader } = require("sdk/test/loader");
const { merge } = require("sdk/util/object");
exports["test changing result from addon extras in panel"] = function(assert, done) {
let loader = Loader(module, null, null, {
modules: {
"sdk/self": merge({}, self, {
data: merge({}, self.data, {url: fixtures.url})
})
}
});
const { Panel } = loader.require("sdk/panel");
const { events } = loader.require("sdk/content/sandbox/events");
const { on } = loader.require("sdk/event/core");
const { isAddonContent } = loader.require("sdk/content/utils");
var result = 1;
var extrasVal = {
test: function() {
return result;
}
};
on(events, "content-script-before-inserted", ({ window, worker }) => {
assert.pass("content-script-before-inserted");
if (isAddonContent({ contentURL: window.location.href })) {
let extraStuff = Cu.cloneInto(extrasVal, window, {
cloneFunctions: true
});
getUnsafeWindow(window).extras = extraStuff;
assert.pass("content-script-before-inserted done!");
}
});
let panel = Panel({
contentURL: "./test-addon-extras.html"
});
panel.port.once("result1", (result) => {
assert.equal(result, 1, "result is a number");
result = true;
panel.port.emit("get-result");
});
panel.port.once("result2", (result) => {
assert.equal(result, true, "result is a boolean");
loader.unload();
done();
});
panel.port.emit("get-result");
}
exports["test window result from addon extras in panel"] = function*(assert) {
let loader = Loader(module, null, null, {
modules: {
"sdk/self": merge({}, self, {
data: merge({}, self.data, {url: fixtures.url})
})
}
});
const { Panel } = loader.require('sdk/panel');
const { Page } = loader.require('sdk/page-worker');
const { getActiveView } = loader.require("sdk/view/core");
const { getDocShell } = loader.require('sdk/frame/utils');
const { events } = loader.require("sdk/content/sandbox/events");
const { on } = loader.require("sdk/event/core");
const { isAddonContent } = loader.require("sdk/content/utils");
// make a page worker and wait for it to load
var page = yield new Promise(resolve => {
assert.pass("Creating the background page");
let page = Page({
contentURL: "./test.html",
contentScriptWhen: "end",
contentScript: "self.port.emit('end', unsafeWindow.getTestURL() + '')"
});
page.port.once("end", (url) => {
assert.equal(url, fixtures.url("./test.html"), "url is correct");
resolve(page);
});
});
assert.pass("Created the background page");
var extrasVal = {
test: function() {
assert.pass("start test function");
let frame = getActiveView(page);
let window = getUnsafeWindow(frame.contentWindow);
assert.equal(typeof window.getTestURL, "function", "window.getTestURL is a function");
return window;
}
};
on(events, "content-script-before-inserted", ({ window, worker }) => {
let url = window.location.href;
assert.pass("content-script-before-inserted " + url);
if (isAddonContent({ contentURL: url })) {
let extraStuff = Cu.cloneInto(extrasVal, window, {
cloneFunctions: true
});
getUnsafeWindow(window).extras = extraStuff;
assert.pass("content-script-before-inserted done!");
}
});
let panel = Panel({
contentURL: "./test-addon-extras-window.html"
});
yield new Promise(resolve => {
panel.port.once("result1", (result) => {
assert.equal(result, fixtures.url("./test.html"), "result1 is a window");
resolve();
});
assert.pass("emit get-result");
panel.port.emit("get-result");
});
page.destroy();
page = yield new Promise(resolve => {
let page = Page({
contentURL: "./index.html",
contentScriptWhen: "end",
contentScript: "self.port.emit('end')"
});
page.port.once("end", () => resolve(page));
});
yield new Promise(resolve => {
panel.port.once("result2", (result) => {
assert.equal(result, fixtures.url("./index.html"), "result2 is a window");
resolve();
});
assert.pass("emit get-result");
panel.port.emit("get-result");
});
loader.unload();
}
function getUnsafeWindow (win) {
return win.wrappedJSObject || win;
}
require("sdk/test").run(exports);

View File

@ -1,169 +0,0 @@
/* 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 { Bond } = require("sdk/util/bond");
const { Class } = require("sdk/core/heritage");
exports["test bonds on constructors"] = assert => {
const MyClass = function(name) {
this.name = name;
}
MyClass.prototype = Bond({
hello() {
return `Hello my name is ${this.name}`
}
})
Object.assign(MyClass.prototype, {
constructor: MyClass,
readName() {
return this.name
}
});
const i1 = new MyClass("James Bond");
assert.equal(i1.hello(), "Hello my name is James Bond");
assert.equal(i1.hello.call({name: "Hack"}), "Hello my name is James Bond");
assert.equal(i1.readName(), "James Bond");
assert.equal(i1.readName.call({name: "Hack"}), "Hack");
const hello = i1.hello
assert.equal(hello(), "Hello my name is James Bond");
};
exports["test subclassing"] = assert => {
const MyClass = function(name) {
this.name = name;
}
MyClass.prototype = Bond({
hello() {
return `Hello my name is ${this.name}`
}
});
const i1 = new MyClass("James Bond");
assert.equal(i1.hello(), "Hello my name is James Bond");
assert.equal(i1.hello.call({name: "Hack"}), "Hello my name is James Bond");
const i1Hello = i1.hello
assert.equal(i1Hello(), "Hello my name is James Bond");
const MySubClass = function(...args) {
MyClass.call(this, ...args)
}
MySubClass.prototype = Object.create(MyClass.prototype)
const i2 = new MySubClass("Your father");
assert.equal(i2.hello(), "Hello my name is Your father");
assert.equal(i2.hello.call({name: "Hack"}), "Hello my name is Your father");
const i2Hello = i2.hello
assert.equal(i2Hello(), "Hello my name is Your father");
};
exports["test access on prototype"] = assert => {
const MyClass = function(name) {
this.name = name;
}
MyClass.prototype = Bond({
hello() {
return `Hello my name is ${this.name}`
}
});
assert.equal(MyClass.prototype.hello(), "Hello my name is undefined");
assert.ok(Object.getOwnPropertyDescriptor(MyClass.prototype, "hello").get,
"hello is still a getter");
assert.equal(MyClass.prototype.hello.call({name: "this"}),
"Hello my name is this",
"passing `this` on prototype methods work");
const i1 = new MyClass("James Bond");
assert.equal(i1.hello(), "Hello my name is James Bond");
assert.ok(!Object.getOwnPropertyDescriptor(i1, "hello").get,
"hello is not a getter on instance");
assert.equal(i1.hello.call({name: "Hack"}), "Hello my name is James Bond");
const i1Hello = i1.hello
assert.equal(i1Hello(), "Hello my name is James Bond");
};
exports["test bonds with Class"] = assert => {
const MyClass = Class({
extends: Bond({
hello() {
return `Hello my name is ${this.name}`
}
}),
initialize(name) {
this.name = name;
}
});
const i1 = new MyClass("James Bond");
assert.equal(i1.hello(), "Hello my name is James Bond");
assert.equal(i1.hello.call({name: "Hack"}), "Hello my name is James Bond");
const hello = i1.hello
assert.equal(hello(), "Hello my name is James Bond");
};
exports["test with mixin"] = assert => {
const MyClass = Class({
implements: [
Bond({
hello() {
return `Hello my name is ${this.name}`
}
})
],
initialize(name) {
this.name = name;
}
});
const i1 = new MyClass("James Bond");
assert.equal(i1.hello(), "Hello my name is James Bond");
assert.equal(i1.hello.call({name: "Hack"}), "Hello my name is James Bond");
const hello = i1.hello
assert.equal(hello(), "Hello my name is James Bond");
const MyComposedClass = Class({
implements: [
MyClass,
Bond({
bye() {
return `Bye ${this.name}`
}
})
],
initialize(name) {
this.name = name;
}
});
const i2 = new MyComposedClass("Major Tom");
assert.equal(i2.hello(), "Hello my name is Major Tom");
assert.equal(i2.hello.call({name: "Hack"}), "Hello my name is Major Tom");
const i2Hello = i2.hello
assert.equal(i2Hello(), "Hello my name is Major Tom");
assert.equal(i2.bye(), "Bye Major Tom");
assert.equal(i2.bye.call({name: "Hack"}), "Bye Major Tom");
const i2Bye = i2.bye
assert.equal(i2Bye(), "Bye Major Tom");
};
require("sdk/test").run(exports);

View File

@ -1,7 +1,6 @@
/* 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 { pathFor } = require('sdk/system');

View File

@ -6,11 +6,11 @@
const { Hotkey } = require("sdk/hotkeys");
const { keyDown } = require("sdk/dom/events/keys");
const { Loader } = require('sdk/test/loader');
const timer = require("sdk/timers");
const winUtils = require("sdk/deprecated/window-utils");
const { getMostRecentBrowserWindow } = require("sdk/window/utils");
const element = getMostRecentBrowserWindow().document.documentElement;
exports["test hotkey: function key"] = function(assert, done) {
var element = winUtils.activeBrowserWindow.document.documentElement;
var showHotKey = Hotkey({
combo: "f1",
onPress: function() {
@ -35,7 +35,6 @@ exports["test hotkey: function key"] = function(assert, done) {
};
exports["test hotkey: accel alt shift"] = function(assert, done) {
var element = winUtils.activeBrowserWindow.document.documentElement;
var showHotKey = Hotkey({
combo: "accel-shift-6",
onPress: function() {
@ -58,7 +57,6 @@ exports["test hotkey: accel alt shift"] = function(assert, done) {
};
exports["test hotkey meta & control"] = function(assert, done) {
var element = winUtils.activeBrowserWindow.document.documentElement;
var showHotKey = Hotkey({
combo: "meta-3",
onPress: function() {
@ -81,7 +79,6 @@ exports["test hotkey meta & control"] = function(assert, done) {
};
exports["test hotkey: control-1 / meta--"] = function(assert, done) {
var element = winUtils.activeBrowserWindow.document.documentElement;
var showHotKey = Hotkey({
combo: "control-1",
onPress: function() {
@ -125,27 +122,23 @@ exports["test invalid combos"] = function(assert) {
};
exports["test no exception on unmodified keypress"] = function(assert) {
var element = winUtils.activeBrowserWindow.document.documentElement;
var someHotkey = Hotkey({
combo: "control-alt-1",
onPress: function() {
}
onPress: () => {}
});
keyDown(element, "a");
assert.pass("No exception throw, unmodified keypress passed");
someHotkey.destroy();
};
exports["test hotkey: automatic destroy"] = function(assert, done) {
exports["test hotkey: automatic destroy"] = function*(assert) {
// Hacky way to be able to create unloadable modules via makeSandboxedLoader.
let loader = Loader(module);
var called = false;
var element = loader.require("sdk/deprecated/window-utils").activeBrowserWindow.document.documentElement;
var hotkey = loader.require("sdk/hotkeys").Hotkey({
combo: "accel-shift-x",
onPress: function() {
called = true;
}
onPress: () => called = true
});
// Unload the module so that previous hotkey is automatically destroyed
@ -154,10 +147,37 @@ exports["test hotkey: automatic destroy"] = function(assert, done) {
// Ensure that the hotkey is really destroyed
keyDown(element, "accel-shift-x");
timer.setTimeout(function () {
assert.ok(!called, "Hotkey is destroyed and not called.");
done();
}, 0);
assert.ok(!called, "Hotkey is destroyed and not called.");
// create a new hotkey for a different set
yield new Promise(resolve => {
let key = Hotkey({
combo: "accel-shift-y",
onPress: () => {
key.destroy();
assert.pass("accel-shift-y was pressed.");
resolve();
}
});
keyDown(element, "accel-shift-y");
});
assert.ok(!called, "Hotkey is still not called, in time it would take.");
// create a new hotkey for the same set
yield new Promise(resolve => {
let key = Hotkey({
combo: "accel-shift-x",
onPress: () => {
key.destroy();
assert.pass("accel-shift-x was pressed.");
resolve();
}
});
keyDown(element, "accel-shift-x");
});
assert.ok(!called, "Hotkey is still not called, and reusing is ok.");
};
require("sdk/test").run(exports);

View File

@ -3,10 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let xulApp = require("sdk/system/xul-app");
if (xulApp.versionInRange(xulApp.platformVersion, "16.0a1", "*")) {
new function tests() {
const { indexedDB, IDBKeyRange, DOMException
} = require("sdk/indexed-db");
@ -183,11 +179,4 @@ function testRead(assert, done) {
};
};
}
} else {
exports.testDB = function(assert) {
assert.pass("IndexedDB is not implemented")
}
}
require("sdk/test").run(exports);

View File

@ -367,6 +367,16 @@ exports['test shared globals'] = function(assert) {
unload(loader);
}
exports['test prototype of global'] = function (assert) {
let uri = root + '/fixtures/loader/globals/';
let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
sandboxPrototype: { globalFoo: 5 }});
let program = main(loader, 'main');
assert.ok(program.globalFoo === 5, '`globalFoo` exists');
};
exports["test require#resolve"] = function(assert) {
let foundRoot = require.resolve("sdk/tabs").replace(/sdk\/tabs.js$/, "");
assert.ok(root, foundRoot, "correct resolution root");
@ -524,4 +534,22 @@ exports['test lazy globals'] = function (assert) {
assert.ok(gotFoo, "foo has been accessed only when we first try to use it");
};
exports['test user global'] = function(assert) {
// Test case for bug 827792
let com = {};
let loader = require('toolkit/loader');
let loadOptions = require('@loader/options');
let options = loader.override(loadOptions,
{globals: loader.override(loadOptions.globals,
{com: com,
console: console,
dump: dump})});
let subloader = loader.Loader(options);
let userRequire = loader.Require(subloader, module);
let userModule = userRequire("./loader/user-global");
assert.equal(userModule.getCom(), com,
"user module returns expected `com` global");
};
require('sdk/test').run(exports);

View File

@ -1,22 +0,0 @@
/* 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 memory = require("sdk/deprecated/memory");
const { gc } = require("sdk/test/memory");
exports.testMemory = function(assert) {
var obj = {};
memory.track(obj, "testMemory.testObj");
var objs = memory.getObjects("testMemory.testObj");
assert.equal(objs[0].weakref.get(), obj);
obj = null;
gc().then(function() {
assert.equal(objs[0].weakref.get(), null);
});
};
require('sdk/test').run(exports);

View File

@ -10,6 +10,8 @@ const { id } = require("sdk/self");
const { getAddonByID } = require("sdk/addon/manager");
const { mapcat, map, filter, fromEnumerator } = require("sdk/util/sequence");
const { readURISync } = require('sdk/net/url');
const { Request } = require('sdk/request');
const { defer } = require("sdk/core/promise");
const ios = Cc['@mozilla.org/network/io-service;1'].
getService(Ci.nsIIOService);
@ -57,26 +59,42 @@ const getEntries = directory => mapcat(entry => {
return [];
}, filter(() => true, getDirectoryEntries(directory)));
function readURL(url) {
let { promise, resolve } = defer();
Request({
url: url,
overrideMimeType: "text/plain",
onComplete: (response) => resolve(response.text)
}).get();
return promise;
}
exports["test MPL2 license header"] = function*(assert) {
let addon = yield getAddonByID(id);
let xpiURI = addon.getResourceURI();
let rootURL = xpiURI.spec;
assert.ok(rootURL, rootURL);
let files = [...getEntries(xpiURI.QueryInterface(Ci.nsIFileURL).file)];
assert.ok(files.length > 1, files.length + " files found.");
let failures = [];
let success = 0;
files.forEach(file => {
const URI = ios.newFileURI(file);
let leafName = URI.spec.replace(rootURL, "");
let contents = readURISync(URI);
for (let i = 0, len = files.length; i < len; i++) {
let file = files[i];
assert.ok(file.path, "Trying " + file.path);
const URI = ios.newFileURI(file);
let leafName = URI.spec.replace(rootURL, "");
let contents = yield readURL(URI.spec);
if (!MPL2_LICENSE_TEST.test(contents)) {
failures.push(leafName);
}
});
}
assert.equal(1, failures.length, "we expect one failure");
assert.ok(/test-mpl2-license-header\.js$/.test(failures[0]), "the only failure is this file");

View File

@ -0,0 +1,66 @@
/* 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 { Cc, Ci, Cu } = require("chrome");
const { PageMod } = require("sdk/page-mod");
const { testPageMod, handleReadyState, openNewTab,
contentScriptWhenServer, createLoader } = require("./page-mod/helpers");
const { cleanUI, after } = require("sdk/test/utils");
const { open, getFrames, getMostRecentBrowserWindow, getInnerId } = require("sdk/window/utils");
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const { require: devtoolsRequire } = devtools;
const contentGlobals = devtoolsRequire("devtools/server/content-globals");
// The following adds Debugger constructor to the global namespace.
const { addDebuggerToGlobal } = require('resource://gre/modules/jsdebugger.jsm');
addDebuggerToGlobal(this);
exports.testDebugMetadata = function(assert, done) {
let dbg = new Debugger;
let globalDebuggees = [];
dbg.onNewGlobalObject = function(global) {
globalDebuggees.push(global);
}
let mods = testPageMod(assert, done, "about:", [{
include: "about:",
contentScriptWhen: "start",
contentScript: "null;",
}], function(win, done) {
assert.ok(globalDebuggees.some(function(global) {
try {
let metadata = Cu.getSandboxMetadata(global.unsafeDereference());
return metadata && metadata.addonID && metadata.SDKContentScript &&
metadata['inner-window-id'] == getInnerId(win);
} catch(e) {
// Some of the globals might not be Sandbox instances and thus
// will cause getSandboxMetadata to fail.
return false;
}
}), "one of the globals is a content script");
done();
}
);
};
exports.testDevToolsExtensionsGetContentGlobals = function(assert, done) {
let mods = testPageMod(assert, done, "about:", [{
include: "about:",
contentScriptWhen: "start",
contentScript: "null;",
}], function(win, done) {
assert.equal(contentGlobals.getContentGlobals({ 'inner-window-id': getInnerId(win) }).length, 1);
done();
}
);
};
after(exports, function*(name, assert) {
assert.pass("cleaning ui.");
yield cleanUI();
});
require('sdk/test').run(exports);

View File

@ -3,118 +3,186 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Cc, Ci, Cu } = require("chrome");
const { PageMod } = require("sdk/page-mod");
const { testPageMod, handleReadyState, openNewTab,
contentScriptWhenServer, createLoader } = require("./pagemod-test-helpers");
const { Loader } = require('sdk/test/loader');
contentScriptWhenServer, createLoader } = require("./page-mod/helpers");
const { Loader } = require("sdk/test/loader");
const tabs = require("sdk/tabs");
const { setTimeout } = require("sdk/timers");
const { Cc, Ci, Cu } = require("chrome");
const system = require("sdk/system/events");
const { open, getFrames, getMostRecentBrowserWindow, getInnerId } = require('sdk/window/utils');
const { open, getFrames, getMostRecentBrowserWindow, getInnerId } = require("sdk/window/utils");
const { getTabContentWindow, getActiveTab, setTabURL, openTab, closeTab,
getBrowserForTab } = require('sdk/tabs/utils');
getBrowserForTab } = require("sdk/tabs/utils");
const xulApp = require("sdk/system/xul-app");
const { isPrivateBrowsingSupported } = require('sdk/self');
const { isPrivate } = require('sdk/private-browsing');
const { openWebpage } = require('./private-browsing/helper');
const { isTabPBSupported, isWindowPBSupported } = require('sdk/private-browsing/utils');
const { isPrivateBrowsingSupported } = require("sdk/self");
const { isPrivate } = require("sdk/private-browsing");
const { openWebpage } = require("./private-browsing/helper");
const { isTabPBSupported, isWindowPBSupported } = require("sdk/private-browsing/utils");
const promise = require("sdk/core/promise");
const { pb } = require('./private-browsing/helper');
const { pb } = require("./private-browsing/helper");
const { URL } = require("sdk/url");
const { defer, all } = require('sdk/core/promise');
const { defer, all, resolve } = require("sdk/core/promise");
const { waitUntil } = require("sdk/test/utils");
const data = require("./fixtures");
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const { require: devtoolsRequire } = devtools;
const contentGlobals = devtoolsRequire("devtools/server/content-globals");
const { cleanUI } = require("sdk/test/utils");
const { cleanUI, after } = require("sdk/test/utils");
const testPageURI = data.url("test.html");
// The following adds Debugger constructor to the global namespace.
const { addDebuggerToGlobal } = require('resource://gre/modules/jsdebugger.jsm');
addDebuggerToGlobal(this);
function Isolate(worker) {
return "(" + worker + ")()";
}
/* Tests for the PageMod APIs */
exports.testPageMod1 = function(assert, done) {
let mods = testPageMod(assert, done, "about:", [{
include: /about:/,
contentScriptWhen: 'end',
contentScript: 'new ' + function WorkerScope() {
window.document.body.setAttribute("JEP-107", "worked");
},
onAttach: function() {
assert.equal(this, mods[0], "The 'this' object is the page mod.");
}
}],
function(win, done) {
assert.equal(
win.document.body.getAttribute("JEP-107"),
"worked",
"PageMod.onReady test"
);
done();
exports.testPageMod1 = function*(assert) {
let modAttached = defer();
let mod = PageMod({
include: /about:/,
contentScriptWhen: "end",
contentScript: "new " + function WorkerScope() {
window.document.body.setAttribute("JEP-107", "worked");
self.port.once("done", () => {
self.port.emit("results", window.document.body.getAttribute("JEP-107"))
});
},
100
);
onAttach: function(worker) {
assert.equal(this, mod, "The 'this' object is the page mod.");
mod.port.once("results", modAttached.resolve)
mod.port.emit("done");
}
});
let tab = yield new Promise(resolve => {
tabs.open({
url: "about:",
inBackground: true,
onReady: resolve
})
});
assert.pass("test tab was opened.");
let worked = yield modAttached.promise;
assert.pass("test mod was attached.");
mod.destroy();
assert.pass("test mod was destroyed.");
assert.equal(worked, "worked", "PageMod.onReady test");
};
exports.testPageMod2 = function(assert, done) {
testPageMod(assert, done, "about:", [{
include: "about:*",
contentScript: [
'new ' + function contentScript() {
window.AUQLUE = function() { return 42; }
try {
window.AUQLUE()
}
catch(e) {
throw new Error("PageMod scripts executed in order");
}
document.documentElement.setAttribute("first", "true");
},
'new ' + function contentScript() {
document.documentElement.setAttribute("second", "true");
exports.testPageMod2 = function*(assert) {
let modAttached = defer();
let mod = PageMod({
include: testPageURI,
contentScriptWhen: "end",
contentScript: [
'new ' + function contentScript() {
window.AUQLUE = function() { return 42; }
try {
window.AUQLUE()
}
]
}], function(win, done) {
assert.equal(win.document.documentElement.getAttribute("first"),
"true",
"PageMod test #2: first script has run");
assert.equal(win.document.documentElement.getAttribute("second"),
"true",
"PageMod test #2: second script has run");
assert.equal("AUQLUE" in win, false,
"PageMod test #2: scripts get a wrapped window");
done();
},
100
);
catch(e) {
throw new Error("PageMod scripts executed in order");
}
document.documentElement.setAttribute("first", "true");
},
'new ' + function contentScript() {
document.documentElement.setAttribute("second", "true");
self.port.once("done", () => {
self.port.emit("results", {
"first": window.document.documentElement.getAttribute("first"),
"second": window.document.documentElement.getAttribute("second"),
"AUQLUE": unsafeWindow.getAUQLUE()
});
});
}
],
onAttach: modAttached.resolve
});
let tab = yield new Promise(resolve => {
tabs.open({
url: testPageURI,
inBackground: true,
onReady: resolve
})
});
assert.pass("test tab was opened.");
let worker = yield modAttached.promise;
assert.pass("test mod was attached.");
let results = yield new Promise(resolve => {
worker.port.once("results", resolve)
worker.port.emit("done");
});
mod.destroy();
assert.pass("test mod was destroyed.");
assert.equal(results["first"],
"true",
"PageMod test #2: first script has run");
assert.equal(results["second"],
"true",
"PageMod test #2: second script has run");
assert.equal(results["AUQLUE"], false,
"PageMod test #2: scripts get a wrapped window");
};
exports.testPageModIncludes = function(assert, done) {
var asserts = [];
exports.testPageModIncludes = function*(assert) {
var modsAttached = [];
var modNumber = 0;
var modAttached = defer();
let includes = [
"*",
"*.google.com",
"resource:*",
"resource:",
testPageURI
];
let expected = [
false,
false,
true,
false,
true
]
let mod = PageMod({
include: testPageURI,
contentScript: 'new ' + function() {
self.port.on("get-local-storage", () => {
let result = {};
self.options.forEach(include => {
result[include] = !!window.localStorage[include]
});
self.port.emit("got-local-storage", result);
window.localStorage.clear();
});
},
contentScriptOptions: includes,
onAttach: modAttached.resolve
});
function createPageModTest(include, expectedMatch) {
// Create an 'onload' test function...
asserts.push(function(test, win) {
var matches = include in win.localStorage;
assert.ok(expectedMatch ? matches : !matches,
"'" + include + "' match test, expected: " + expectedMatch);
});
var modIndex = modNumber++;
let attached = defer();
modsAttached.push(expectedMatch ? attached.promise : resolve());
// ...and corresponding PageMod options
return {
return PageMod({
include: include,
contentScript: 'new ' + function() {
self.on("message", function(msg) {
window.localStorage[msg] = true;
window.localStorage[msg] = true
self.port.emit('done');
});
},
// The testPageMod callback with test assertions is called on 'end',
@ -122,27 +190,56 @@ exports.testPageModIncludes = function(assert, done) {
// so we attach it on 'start'.
contentScriptWhen: 'start',
onAttach: function(worker) {
assert.pass("mod " + modIndex + " was attached");
worker.port.once("done", () => {
assert.pass("mod " + modIndex + " is done");
attached.resolve(worker);
});
worker.postMessage(this.include[0]);
}
};
});
}
testPageMod(assert, done, testPageURI, [
createPageModTest("*", false),
createPageModTest("*.google.com", false),
createPageModTest("resource:*", true),
createPageModTest("resource:", false),
createPageModTest(testPageURI, true)
],
function (win, done) {
waitUntil(() => win.localStorage[testPageURI],
testPageURI + " page-mod to be executed")
.then(() => {
asserts.forEach(fn => fn(assert, win));
win.localStorage.clear();
done();
});
let mods = [
createPageModTest("*", false),
createPageModTest("*.google.com", false),
createPageModTest("resource:*", true),
createPageModTest("resource:", false),
createPageModTest(testPageURI, true)
];
let tab = yield new Promise(resolve => {
tabs.open({
url: testPageURI,
inBackground: true,
onReady: resolve
});
});
assert.pass("tab was opened");
yield all(modsAttached);
assert.pass("all mods were attached.");
mods.forEach(mod => mod.destroy());
assert.pass("all mods were destroyed.");
yield modAttached.promise;
assert.pass("final test mod was attached.");
yield new Promise(resolve => {
mod.port.on("got-local-storage", (storage) => {
includes.forEach((include, i) => {
assert.equal(storage[include], expected[i], "localStorage is correct for " + include);
});
resolve();
});
mod.port.emit("get-local-storage");
});
assert.pass("final test of localStorage is complete.");
mod.destroy();
assert.pass("final test mod was destroyed.");
};
exports.testPageModExcludes = function(assert, done) {
@ -257,96 +354,116 @@ exports.testPageModValidationExclude = function(assert) {
};
/* Tests for internal functions. */
exports.testCommunication1 = function(assert, done) {
let workerDone = false,
callbackDone = null;
exports.testCommunication1 = function*(assert) {
let workerDone = defer();
testPageMod(assert, done, "about:", [{
include: "about:*",
contentScriptWhen: 'end',
contentScript: 'new ' + function WorkerScope() {
self.on('message', function(msg) {
document.body.setAttribute('JEP-107', 'worked');
self.postMessage(document.body.getAttribute('JEP-107'));
})
},
onAttach: function(worker) {
worker.on('error', function(e) {
assert.fail('Errors where reported');
});
worker.on('message', function(value) {
assert.equal(
"worked",
value,
"test comunication"
);
workerDone = true;
if (callbackDone)
callbackDone();
});
worker.postMessage('do it!')
}
}],
function(win, done) {
(callbackDone = function() {
if (workerDone) {
assert.equal(
'worked',
win.document.body.getAttribute('JEP-107'),
'attribute should be modified'
);
done();
}
})();
let mod = PageMod({
include: "about:*",
contentScriptWhen: "end",
contentScript: 'new ' + function WorkerScope() {
self.on('message', function(msg) {
document.body.setAttribute('JEP-107', 'worked');
self.postMessage(document.body.getAttribute('JEP-107'));
});
self.port.on('get-jep-107', () => {
self.port.emit('got-jep-107', document.body.getAttribute('JEP-107'));
});
},
onAttach: function(worker) {
worker.on('error', function(e) {
assert.fail('Errors where reported');
});
worker.on('message', function(value) {
assert.equal(
"worked",
value,
"test comunication"
);
workerDone.resolve();
});
worker.postMessage("do it!")
}
);
});
let tab = yield new Promise(resolve => {
tabs.open({
url: "about:",
onReady: resolve
});
});
assert.pass("opened tab");
yield workerDone.promise;
assert.pass("the worker has made a change");
let value = yield new Promise(resolve => {
mod.port.once("got-jep-107", resolve);
mod.port.emit("get-jep-107");
});
assert.equal("worked", value, "attribute should be modified");
mod.destroy();
assert.pass("the worker was destroyed");
};
exports.testCommunication2 = function(assert, done) {
let callbackDone = null,
window;
exports.testCommunication2 = function*(assert) {
let workerDone = defer();
let url = data.url("test.html");
testPageMod(assert, done, "about:license", [{
include: "about:*",
contentScriptWhen: 'start',
contentScript: 'new ' + function WorkerScope() {
document.documentElement.setAttribute('AUQLUE', 42);
window.addEventListener('load', function listener() {
self.postMessage('onload');
}, false);
self.on("message", function() {
self.postMessage(document.documentElement.getAttribute("test"))
let mod = PageMod({
include: url,
contentScriptWhen: 'start',
contentScript: 'new ' + function WorkerScope() {
document.documentElement.setAttribute('AUQLUE', 42);
window.addEventListener('load', function listener() {
self.postMessage({
msg: 'onload',
AUQLUE: document.documentElement.getAttribute('AUQLUE')
});
},
onAttach: function(worker) {
worker.on('error', function(e) {
assert.fail('Errors where reported');
}, false);
self.on("message", function(msg) {
if (msg == "get window.test") {
unsafeWindow.changesInWindow();
}
self.postMessage({
msg: document.documentElement.getAttribute("test")
});
worker.on('message', function(msg) {
if ('onload' == msg) {
assert.equal(
'42',
window.document.documentElement.getAttribute('AUQLUE'),
'PageMod scripts executed in order'
);
window.document.documentElement.setAttribute('test', 'changes in window');
worker.postMessage('get window.test')
} else {
assert.equal(
'changes in window',
msg,
'PageMod test #2: second script has run'
)
callbackDone();
}
});
}
}],
function(win, done) {
window = win;
callbackDone = done;
});
},
onAttach: function(worker) {
worker.on('error', function(e) {
assert.fail('Errors where reported');
});
worker.on('message', function({ msg, AUQLUE }) {
if ('onload' == msg) {
assert.equal('42', AUQLUE, 'PageMod scripts executed in order');
worker.postMessage('get window.test');
}
else {
assert.equal('changes in window', msg, 'PageMod test #2: second script has run');
workerDone.resolve();
}
});
}
);
});
let tab = yield new Promise(resolve => {
tabs.open({
url: url,
inBackground: true,
onReady: resolve
});
});
assert.pass("opened tab");
yield workerDone.promise;
mod.destroy();
assert.pass("the worker was destroyed");
};
exports.testEventEmitter = function(assert, done) {
@ -1074,55 +1191,83 @@ exports.testPageModCss = function(assert, done) {
);
};
exports.testPageModCssList = function(assert, done) {
let [pageMod] = testPageMod(assert, done,
'data:text/html;charset=utf-8,<div style="width:320px; max-width: 480px!important">css test</div>', [{
include: "data:*",
contentStyleFile: [
// Highlight evaluation order in this list
"data:text/css;charset=utf-8,div { border: 1px solid black; }",
"data:text/css;charset=utf-8,div { border: 10px solid black; }",
// Highlight evaluation order between contentStylesheet & contentStylesheetFile
"data:text/css;charset=utf-8s,div { height: 1000px; }",
// Highlight precedence between the author and user style sheet
"data:text/css;charset=utf-8,div { width: 200px; max-width: 640px!important}",
],
contentStyle: [
"div { height: 10px; }",
"div { height: 100px; }"
]
}],
function(win, done) {
let div = win.document.querySelector("div"),
style = win.getComputedStyle(div);
exports.testPageModCssList = function*(assert) {
const URL = 'data:text/html;charset=utf-8,<div style="width:320px; max-width: 480px!important">css test</div>';
let modAttached = defer();
assert.equal(
div.clientHeight,
100,
"PageMod contentStyle list works and is evaluated after contentStyleFile"
);
let pageMod = PageMod({
include: "data:*",
contentStyleFile: [
// Highlight evaluation order in this list
"data:text/css;charset=utf-8,div { border: 1px solid black; }",
"data:text/css;charset=utf-8,div { border: 10px solid black; }",
// Highlight evaluation order between contentStylesheet & contentStylesheetFile
"data:text/css;charset=utf-8s,div { height: 1000px; }",
// Highlight precedence between the author and user style sheet
"data:text/css;charset=utf-8,div { width: 200px; max-width: 640px!important}",
],
contentStyle: [
"div { height: 10px; }",
"div { height: 100px; }"
],
contentScript: 'new ' + function WorkerScope() {
self.port.on('get-results', () => {
let div = window.document.querySelector('div');
let style = window.getComputedStyle(div);
assert.equal(
div.offsetHeight,
120,
"PageMod contentStyleFile list works"
);
self.port.emit("results", {
clientHeight: div.clientHeight,
offsetHeight: div.offsetHeight,
width: style.width,
maxWidth: style.maxWidth
});
})
},
onAttach: modAttached.resolve
});
assert.equal(
style.width,
"320px",
"PageMod add-on author/page author style sheet precedence works"
);
let tab = yield new Promise(resolve => {
tabs.open({
url: URL,
onReady: resolve
});
});
assert.pass("the tab was opened");
assert.equal(
style.maxWidth,
"480px",
"PageMod add-on author/page author style sheet precedence with !important works"
);
yield modAttached.promise;
assert.pass("the mod has been attached");
done();
}
let results = yield new Promise(resolve => {
pageMod.port.on("results", resolve);
pageMod.port.emit("get-results");
})
assert.equal(
results.clientHeight,
100,
"PageMod contentStyle list works and is evaluated after contentStyleFile"
);
assert.equal(
results.offsetHeight,
120,
"PageMod contentStyleFile list works"
);
assert.equal(
results.width,
"320px",
"PageMod add-on author/page author style sheet precedence works"
);
assert.equal(
results.maxWidth,
"480px",
"PageMod add-on author/page author style sheet precedence with !important works"
);
pageMod.destroy();
assert.pass("the page mod was destroyed");
};
exports.testPageModCssDestroy = function(assert, done) {
@ -1417,30 +1562,49 @@ exports.testIFramePostMessage = function(assert, done) {
});
};
exports.testEvents = function(assert, done) {
exports.testEvents = function*(assert) {
let modAttached = defer();
let content = "<script>\n new " + function DocumentScope() {
window.addEventListener("ContentScriptEvent", function () {
window.document.body.setAttribute("receivedEvent", true);
window.document.body.setAttribute("receivedEvent", "ok");
}, false);
} + "\n</script>";
let url = "data:text/html;charset=utf-8," + encodeURIComponent(content);
testPageMod(assert, done, url, [{
include: "data:*",
contentScript: 'new ' + function WorkerScope() {
let evt = document.createEvent("Event");
evt.initEvent("ContentScriptEvent", true, true);
document.body.dispatchEvent(evt);
}
}],
function(win, done) {
assert.ok(
win.document.body.getAttribute("receivedEvent"),
"Content script sent an event and document received it"
);
done();
let mod = PageMod({
include: "data:*",
contentScript: 'new ' + function WorkerScope() {
let evt = document.createEvent("Event");
evt.initEvent("ContentScriptEvent", true, true);
document.body.dispatchEvent(evt);
self.port.on("get-result", () => {
self.port.emit("result", {
receivedEvent: window.document.body.getAttribute("receivedEvent")
});
});
},
100
);
onAttach: modAttached.resolve
});
let tab = yield new Promise(resolve => {
tabs.open({
url: url,
onReady: resolve
});
});
assert.pass("the tab is ready");
yield modAttached.promise;
assert.pass("the mod was attached")
let result = yield new Promise(resolve => {
mod.port.once("result", resolve);
mod.port.emit("get-result");
});
assert.equal(result.receivedEvent, "ok",
"Content script sent an event and document received it");
};
exports["test page-mod on private tab"] = function (assert, done) {
@ -1507,46 +1671,6 @@ exports.testWorkerTabClose = function(assert, done) {
);
};
exports.testDebugMetadata = function(assert, done) {
let dbg = new Debugger;
let globalDebuggees = [];
dbg.onNewGlobalObject = function(global) {
globalDebuggees.push(global);
}
let mods = testPageMod(assert, done, "about:", [{
include: "about:",
contentScriptWhen: "start",
contentScript: "null;",
}], function(win, done) {
assert.ok(globalDebuggees.some(function(global) {
try {
let metadata = Cu.getSandboxMetadata(global.unsafeDereference());
return metadata && metadata.addonID && metadata.SDKContentScript &&
metadata['inner-window-id'] == getInnerId(win);
} catch(e) {
// Some of the globals might not be Sandbox instances and thus
// will cause getSandboxMetadata to fail.
return false;
}
}), "one of the globals is a content script");
done();
}
);
};
exports.testDevToolsExtensionsGetContentGlobals = function(assert, done) {
let mods = testPageMod(assert, done, "about:", [{
include: "about:",
contentScriptWhen: "start",
contentScript: "null;",
}], function(win, done) {
assert.equal(contentGlobals.getContentGlobals({ 'inner-window-id': getInnerId(win) }).length, 1);
done();
}
);
};
exports.testDetachOnDestroy = function(assert, done) {
let tab;
const TEST_URL = 'data:text/html;charset=utf-8,detach';
@ -2063,4 +2187,9 @@ exports.testDontInjectConsole = function(assert, done) {
let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
}
after(exports, function*(name, assert) {
assert.pass("cleaning ui.");
yield cleanUI();
});
require('sdk/test').run(exports);

View File

@ -22,6 +22,7 @@ const { getMostRecentBrowserWindow } = require('sdk/window/utils');
const { URL } = require('sdk/url');
const { wait } = require('./event/helpers');
const packaging = require('@loader/options');
const { cleanUI, after } = require("sdk/test/utils");
const fixtures = require('./fixtures')
@ -335,65 +336,27 @@ exports["test Anchor And Arrow"] = function(assert, done) {
let { Panel } = loader.require('sdk/panel');
let count = 0;
let queue = [];
let tab;
let url = 'data:text/html;charset=utf-8,' +
'<html><head><title>foo</title></head><body>' +
'</body></html>';
function newPanel(anchor) {
let panel = yield new Promise(resolve => {
let browserWindow = getMostRecentBrowserWindow();
let anchor = browserWindow.document.getElementById("identity-box");
let panel = Panel({
contentURL: "data:text/html;charset=utf-8,<html><body style='padding: 0; margin: 0; " +
"background: gray; text-align: center;'>Anchor: " +
anchor.id + "</body></html>",
width: 200,
height: 100,
onShow: function () {
panel.destroy();
next();
}
onShow: () => resolve(panel)
});
queue.push({ panel: panel, anchor: anchor });
}
function next () {
if (!queue.length) {
assert.pass("All anchored panel test displayed");
tab.close(function () {
done();
});
return;
}
let { panel, anchor } = queue.shift();
panel.show(null, anchor);
}
let tabs= require("sdk/tabs");
let url = 'data:text/html;charset=utf-8,' +
'<html><head><title>foo</title></head><body>' +
'<style>div {background: gray; position: absolute; width: 300px; ' +
'border: 2px solid black;}</style>' +
'<div id="tl" style="top: 0px; left: 0px;">Top Left</div>' +
'<div id="tr" style="top: 0px; right: 0px;">Top Right</div>' +
'<div id="bl" style="bottom: 0px; left: 0px;">Bottom Left</div>' +
'<div id="br" style="bottom: 0px; right: 0px;">Bottom right</div>' +
'</body></html>';
tabs.open({
url: url,
onReady: function(_tab) {
tab = _tab;
let browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator).
getMostRecentWindow("navigator:browser");
let window = browserWindow.content;
newPanel(window.document.getElementById('tl'));
newPanel(window.document.getElementById('tr'));
newPanel(window.document.getElementById('bl'));
newPanel(window.document.getElementById('br'));
let anchor = browserWindow.document.getElementById("identity-box");
newPanel(anchor);
next();
}
});
assert.pass("All anchored panel test displayed");
panel.destroy();
assert.pass("panel was destroyed.");
};
exports["test Panel Focus True"] = function(assert, done) {
@ -1352,6 +1315,11 @@ exports["test Panel without contentURL and contentScriptWhen=start should show"]
loader.unload();
}
after(exports, function*(name, assert) {
yield cleanUI();
assert.pass("ui was cleaned.");
});
if (packaging.isNative) {
module.exports = {
"test skip on jpm": (assert) => assert.pass("skipping this file with jpm")

View File

@ -5,7 +5,6 @@
const tabs = require("sdk/tabs");
const windowUtils = require("sdk/deprecated/window-utils");
const { getTabForWindow } = require('sdk/tabs/helpers');
const windows = require("sdk/windows").browserWindows;
const app = require("sdk/system/xul-app");
const { viewFor } = require("sdk/view/core");
@ -13,15 +12,6 @@ const { modelFor } = require("sdk/model/core");
const { getTabId, isTab } = require("sdk/tabs/utils");
const { defer } = require("sdk/lang/functional");
// The primary test tab
var primaryTab;
// We have an auxiliary tab to test background tabs.
var auxTab;
// The window for the outer iframe in the primary test page
var iframeWin;
function tabExistenceInTabs(assert, found, tab, tabs) {
let tabFound = false;
@ -43,99 +33,6 @@ function tabExistenceInTabs(assert, found, tab, tabs) {
assert.ok(!tabFound, 'the tab was not found as expected');
}
exports["test GetTabForWindow"] = function(assert, done) {
assert.equal(getTabForWindow(windowUtils.activeWindow), null,
"getTabForWindow return null on topwindow");
assert.equal(getTabForWindow(windowUtils.activeBrowserWindow), null,
"getTabForWindow return null on topwindow");
let subSubDocument = encodeURIComponent(
'Sub iframe<br/>'+
'<iframe id="sub-sub-iframe" src="data:text/html;charset=utf-8,SubSubIframe" />');
let subDocument = encodeURIComponent(
'Iframe<br/>'+
'<iframe id="sub-iframe" src="data:text/html;charset=utf-8,'+subSubDocument+'" />');
let url = 'data:text/html;charset=utf-8,' + encodeURIComponent(
'Content<br/><iframe id="iframe" src="data:text/html;charset=utf-8,'+subDocument+'" />');
// Open up a new tab in the background.
//
// This lets us test whether GetTabForWindow works even when the tab in
// question is not active.
tabs.open({
inBackground: true,
url: "about:mozilla",
onReady: function(tab) { auxTab = tab; step2(url, assert);},
onActivate: function(tab) { step3(assert, done); }
});
};
function step2(url, assert) {
tabs.open({
url: url,
onReady: function(tab) {
primaryTab = tab;
let window = windowUtils.activeBrowserWindow.content;
let matchedTab = getTabForWindow(window);
assert.equal(matchedTab, tab,
"We are able to find the tab with his content window object");
let timer = require("sdk/timers");
function waitForFrames() {
let iframe = window.document.getElementById("iframe");
if (!iframe) {
timer.setTimeout(waitForFrames, 100);
return;
}
iframeWin = iframe.contentWindow;
let subIframe = iframeWin.document.getElementById("sub-iframe");
if (!subIframe) {
timer.setTimeout(waitForFrames, 100);
return;
}
let subIframeWin = subIframe.contentWindow;
let subSubIframe = subIframeWin.document.getElementById("sub-sub-iframe");
if (!subSubIframe) {
timer.setTimeout(waitForFrames, 100);
return;
}
let subSubIframeWin = subSubIframe.contentWindow;
matchedTab = getTabForWindow(iframeWin);
assert.equal(matchedTab, tab,
"We are able to find the tab with an iframe window object");
matchedTab = getTabForWindow(subIframeWin);
assert.equal(matchedTab, tab,
"We are able to find the tab with a sub-iframe window object");
matchedTab = getTabForWindow(subSubIframeWin);
assert.equal(matchedTab, tab,
"We are able to find the tab with a sub-sub-iframe window object");
// Put our primary tab in the background and test again.
// The onActivate listener will take us to step3.
auxTab.activate();
}
waitForFrames();
}
});
}
function step3(assert, done) {
let matchedTab = getTabForWindow(iframeWin);
assert.equal(matchedTab, primaryTab,
"We get the correct tab even when it's in the background");
primaryTab.close(function () {
auxTab.close(function () { done();});
});
}
exports.testBehaviorOnCloseAfterReady = function(assert, done) {
tabs.open({
url: "about:mozilla",

View File

@ -7,6 +7,8 @@
const { setTimeout } = require('sdk/timers');
const { waitUntil, cleanUI } = require('sdk/test/utils');
const tabs = require('sdk/tabs');
const fixtures = require("./fixtures");
const testURI = fixtures.url("test.html");
exports.testWaitUntil = function (assert, done) {
let bool = false;
@ -44,29 +46,36 @@ exports.testWaitUntilInterval = function (assert, done) {
setTimeout(() => { bool = true; }, 10);
};
exports.testCleanUIWithExtraTabAndWindow = function(assert, done) {
tabs.open({
url: "about:blank",
inNewWindow: true,
onOpen: () => {
cleanUI().then(() => {
assert.pass("the ui was cleaned");
assert.equal(tabs.length, 1, 'there is only one tab open');
}).then(done).catch(assert.fail);
}
exports.testCleanUIWithExtraTabAndWindow = function*(assert) {
let tab = yield new Promise(resolve => {
tabs.open({
url: testURI,
inNewWindow: true,
onReady: resolve
});
});
assert.equal(tabs.length, 2, 'there are two tabs open');
yield cleanUI()
assert.pass("the ui was cleaned");
assert.equal(tabs.length, 1, 'there is only one tab open');
}
exports.testCleanUIWithOnlyExtraTab = function(assert, done) {
tabs.open({
url: "about:blank",
onOpen: () => {
cleanUI().then(() => {
assert.pass("the ui was cleaned");
assert.equal(tabs.length, 1, 'there is only one tab open');
}).then(done).catch(assert.fail);
}
exports.testCleanUIWithOnlyExtraTab = function*(assert) {
let tab = yield new Promise(resolve => {
tabs.open({
url: testURI,
inBackground: true,
onReady: resolve
});
});
assert.equal(tabs.length, 2, 'there are two tabs open');
yield cleanUI();
assert.pass("the ui was cleaned.");
assert.equal(tabs.length, 1, 'there is only one tab open');
}
require('sdk/test').run(exports);

View File

@ -18,6 +18,7 @@ const { getMostRecentBrowserWindow } = require('sdk/window/utils');
const { partial } = require('sdk/lang/functional');
const { wait } = require('./event/helpers');
const { gc } = require('sdk/test/memory');
const { emit, once } = require("sdk/event/core");
const openBrowserWindow = partial(open, null, {features: {toolbar: true}});
const openPrivateBrowserWindow = partial(open, null,
@ -716,7 +717,11 @@ exports['test button tab state'] = function*(assert) {
'tab badgeColor inherited from global');
// check the node properties
yield wait();
yield new Promise(resolve => {
let target = {};
once(target, "ready", resolve);
emit(target, "ready");
});
assert.equal(node.getAttribute('label'), state.label,
'node label is correct');
@ -737,7 +742,11 @@ exports['test button tab state'] = function*(assert) {
// This is made in order to avoid to check the node before it
// is updated, need a better check
yield wait();
yield new Promise(resolve => {
let target = {};
once(target, "ready", resolve);
emit(target, "ready");
});
state = button.state(mainTab);

View File

@ -123,7 +123,6 @@ exports.testWaitUntilTimeoutInCallback = function(test) {
expected.push(["print", "TEST-START | wait4ever\n"]);
expected.push(["error", "fail:", "Timed out (after: START)"]);
expected.push(["error", "test assertion never became true:\n", "assertion failed, value is false\n"]);
expected.push(["print", "TEST-END | wait4ever\n"]);
}
else {
expected.push(["info", "executing 'wait4ever'"]);
@ -132,17 +131,19 @@ exports.testWaitUntilTimeoutInCallback = function(test) {
}
function checkExpected(name, args) {
if (expected.length == 0 || expected[0][0] != name) {
test.fail("Saw an unexpected console." + name + "() call " + args);
var index = message;
if (message++ >= expected.length) {
return;
}
message++;
let expectedArgs = expected.shift().slice(1);
for (let i = 0; i < expectedArgs.length; i++)
let expectedArgs = expected[index].slice(1);
for (let i = 0; i < expectedArgs.length; i++) {
test.assertEqual(args[i], expectedArgs[i], "Should have seen the right message in argument " + i + " of message " + message);
if (expected.length == 0)
}
if (message >= expected.length) {
test.done();
}
}
let runner = new (require("sdk/deprecated/unit-test").TestRunner)({

View File

@ -1,118 +1,81 @@
/* 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';
"use strict";
const { Cu } = require('chrome');
const { Loader } = require('sdk/test/loader');
const { gc } = require("sdk/test/memory");
const { Cu } = require("chrome");
const memory = require("sdk/test/memory");
const { add, remove, has, clear, iterator } = require("sdk/lang/weak-set");
const { setInterval, clearInterval } = require("sdk/timers");
exports['test adding item'] = function*(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
function gc(assert) {
let wait = 1;
let interval = setInterval(function() {
assert.pass("waited " + (wait++ * 0.250) + "secs for gc()..");
}, 250);
return memory.gc().then(() => {
assert.pass("gc completed!");
clearInterval(interval);
});
}
exports['test add/remove/iterate/clear item'] = function*(assert) {
let addItems = {};
let removeItems = {};
let iterateItems = {};
let clearItems = {};
let nonReferencedItems = {};
let items = {};
let item = {};
add(items, item);
yield gc();
assert.ok(has(items, item), 'the item is in the weak set');
loader.unload();
};
exports['test remove item'] = function*(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
let items = {};
let item = {};
add(items, item);
remove(items, item);
yield gc();
assert.ok(!has(items, item), 'the item is not in weak set');
loader.unload();
};
exports['test iterate'] = function*(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
let items = {};
let addedItems = [{}, {}];
add(items, addedItems[0]);
add(items, addedItems[1]);
add(items, addedItems[0]); // weak set shouldn't add this twice
assert.pass("adding things to items");
add(addItems, item);
add(removeItems, item);
add(iterateItems, addedItems[0]);
add(iterateItems, addedItems[1]);
add(iterateItems, addedItems[0]); // weak set shouldn't add this twice
add(clearItems, addedItems[0]);
add(clearItems, addedItems[1]);
add(nonReferencedItems, {});
yield gc();
assert.pass("removing things from removeItems");
remove(removeItems, item);
assert.pass("clear things from clearItems");
clear(clearItems);
assert.pass("starting gc..");
yield gc(assert);
let count = 0;
for (let item of iterator(items)) {
assert.equal(item, addedItems[count],
'item in the expected order');
assert.equal(has(addItems, item), true, 'the addItems is in the weak set');
assert.equal(has(removeItems, item), false, 'the removeItems is not in weak set');
assert.pass("iterating iterateItems..");
for (let item of iterator(iterateItems)) {
assert.equal(item, addedItems[count], "item in the expected order");
count++;
}
assert.equal(count, 2, 'items in the expected number');
loader.unload();
};
exports['test clear'] = function*(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
let items = {};
let addedItems = [{}, {}];
add(items, addedItems[0]);
add(items, addedItems[1]);
clear(items)
yield gc();
let count = 0;
for (let item of iterator(items)) {
assert.fail('the loop should not be executed');
assert.pass("iterating clearItems..");
for (let item of iterator(clearItems)) {
assert.fail("the loop should not be executed");
count++
}
assert.equal(count, 0, 'no items in the weak set');
loader.unload();
};
exports['test adding item without reference'] = function*(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
let items = {};
add(items, {});
yield gc();
let count = 0;
for (let item of iterator(items)) {
assert.fail('the loop should not be executed');
for (let item of iterator(nonReferencedItems)) {
assert.fail("the loop should not be executed");
count++
}
assert.equal(count, 0, 'no items in the weak set');
loader.unload();
assert.equal(count, 2, 'items in the expected number');
};
exports['test adding non object or null item'] = function(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
let items = {};
assert.throws(() => {
@ -147,9 +110,6 @@ exports['test adding non object or null item'] = function(assert) {
};
exports['test adding to non object or null item'] = function(assert) {
let loader = Loader(module);
let { add, remove, has, clear, iterator } = loader.require('sdk/lang/weak-set');
let item = {};
assert.throws(() => {
@ -183,4 +143,4 @@ exports['test adding to non object or null item'] = function(assert) {
'only non-null object are allowed');
};
require('sdk/test').run(exports);
require("sdk/test").run(exports);

View File

@ -10,6 +10,7 @@ const { viewFor } = require('sdk/view/core');
const { modelFor } = require('sdk/model/core');
const { Ci } = require("chrome");
const { isBrowser, getWindowTitle } = require("sdk/window/utils");
const { after, cleanUI } = require("sdk/test/utils");
// TEST: browserWindows Iterator
exports.testBrowserWindowsIterator = function(assert) {
@ -65,20 +66,18 @@ exports.testWindowActivateMethod_simple = function(assert) {
};
exports["test getView(window)"] = function(assert, done) {
browserWindows.once("open", window => {
const view = viewFor(window);
assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
assert.ok(isBrowser(view), "view is a browser window");
assert.equal(getWindowTitle(view), window.title,
"window has a right title");
window.close(done);
exports["test getView(window)"] = function*(assert) {
let window = yield new Promise(resolve => {
browserWindows.once("open", resolve);
browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
});
const view = viewFor(window);
browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
assert.ok(isBrowser(view), "view is a browser window");
assert.equal(getWindowTitle(view), window.title,
"window has a right title");
};
@ -97,4 +96,9 @@ exports["test modelFor(window)"] = function(assert, done) {
browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
};
after(exports, function*(name, assert) {
assert.pass("cleaning the ui.");
yield cleanUI();
});
require('sdk/test').run(exports);

View File

@ -1,10 +1,11 @@
/* 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";
var xulApp = require("sdk/system/xul-app");
exports["test xulapp"] = function(assert) {
exports["test xulapp"] = function (assert) {
assert.equal(typeof(xulApp.ID), "string",
"ID is a string");
assert.equal(typeof(xulApp.name), "string",
@ -14,26 +15,26 @@ exports["test xulapp"] = function(assert) {
assert.equal(typeof(xulApp.platformVersion), "string",
"platformVersion is a string");
assert.throws(function() { xulApp.is("blargy"); },
/Unkown Mozilla Application: blargy/,
"is() throws error on bad app name");
assert.throws(function() { xulApp.isOneOf(["blargy"]); },
/Unkown Mozilla Application: blargy/,
"isOneOf() throws error on bad app name");
assert.throws(() => xulApp.is("blargy"),
/Unkown Mozilla Application: blargy/,
"is() throws error on bad app name");
assert.throws(() => xulApp.isOneOf(["blargy"]),
/Unkown Mozilla Application: blargy/,
"isOneOf() throws error on bad app name");
function testSupport(name) {
var item = xulApp.is(name);
assert.ok(item === true || item === false,
"is('" + name + "') is true or false.");
"is('" + name + "') is true or false.");
}
var apps = ["Firefox", "Mozilla", "SeaMonkey", "Fennec", "Thunderbird"];
apps.forEach(testSupport);
assert.ok(xulApp.isOneOf(apps) == true ||
xulApp.isOneOf(apps) == false,
"isOneOf() returns true or false.");
assert.ok(xulApp.isOneOf(apps) == true || xulApp.isOneOf(apps) == false,
"isOneOf() returns true or false.");
assert.equal(xulApp.versionInRange(xulApp.platformVersion, "1.9", "*"),
true, "platformVersion in range [1.9, *)");

View File

@ -327,7 +327,6 @@ exports.testTrackWindows = function(assert, done) {
// listen to global deactivate events
browserWindows.on("deactivate", windowsDeactivation);
function openWindow() {
windows.push(browserWindows.open({
url: "data:text/html;charset=utf-8,<i>testTrackWindows</i>",
@ -350,8 +349,10 @@ exports.testTrackWindows = function(assert, done) {
else {
(function closeWindows(windows) {
if (!windows.length) {
assert.pass('the last window was closed');
browserWindows.removeListener("activate", windowsActivation);
browserWindows.removeListener("deactivate", windowsDeactivation);
assert.pass('removed listeners');
return done();
}