зеркало из https://github.com/mozilla/pjs.git
Bug 733631 - Create a unit test infrastructure for the webapp runtime. r=myk,felipc,ctalbert
This commit is contained in:
Родитель
67e4a38f15
Коммит
7d8f11c66d
|
@ -188,7 +188,13 @@
|
|||
function runTests() {
|
||||
var windowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].
|
||||
getService(Ci.nsIWindowMediator);
|
||||
var testWin = windowMediator.getMostRecentWindow("navigator:browser");
|
||||
var winType = gConfig.testRoot == "browser" ? "navigator:browser" :
|
||||
gConfig.testRoot == "webapprtChrome" ? "webapprt:webapp" :
|
||||
null;
|
||||
if (!winType) {
|
||||
throw new Error("Unrecognized gConfig.testRoot: " + gConfig.testRoot);
|
||||
}
|
||||
var testWin = windowMediator.getMostRecentWindow(winType);
|
||||
|
||||
setStatus("Running...");
|
||||
testWin.focus();
|
||||
|
|
|
@ -13,7 +13,7 @@ function testOnLoad() {
|
|||
window.removeEventListener("load", testOnLoad, false);
|
||||
|
||||
gConfig = readConfig();
|
||||
if (gConfig.testRoot == "browser") {
|
||||
if (gConfig.testRoot == "browser" || gConfig.testRoot == "webapprtChrome") {
|
||||
// Make sure to launch the test harness for the first opened window only
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
@ -110,7 +110,10 @@ Tester.prototype = {
|
|||
: this.currentTest ? "Found an unexpected {elt} at the end of test run"
|
||||
: "Found an unexpected {elt}";
|
||||
|
||||
if (this.currentTest && window.gBrowser && gBrowser.tabs.length > 1) {
|
||||
if (gConfig.testRoot == "browser" &&
|
||||
this.currentTest &&
|
||||
window.gBrowser &&
|
||||
gBrowser.tabs.length > 1) {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
let lastTab = gBrowser.tabContainer.lastChild;
|
||||
let msg = baseMsg.replace("{elt}", "tab") +
|
||||
|
|
|
@ -139,6 +139,16 @@ class MochitestOptions(optparse.OptionParser):
|
|||
help = "run browser chrome Mochitests")
|
||||
defaults["browserChrome"] = False
|
||||
|
||||
self.add_option("--webapprt-content",
|
||||
action = "store_true", dest = "webapprtContent",
|
||||
help = "run WebappRT content tests")
|
||||
defaults["webapprtContent"] = False
|
||||
|
||||
self.add_option("--webapprt-chrome",
|
||||
action = "store_true", dest = "webapprtChrome",
|
||||
help = "run WebappRT chrome tests")
|
||||
defaults["webapprtChrome"] = False
|
||||
|
||||
self.add_option("--a11y",
|
||||
action = "store_true", dest = "a11y",
|
||||
help = "run accessibility Mochitests");
|
||||
|
@ -304,6 +314,9 @@ See <http://mochikit.com/doc/html/MochiKit/Logging.html> for details on the logg
|
|||
options.testManifest = options.excludeTests
|
||||
options.runOnly = False
|
||||
|
||||
if options.webapprtContent and options.webapprtChrome:
|
||||
self.error("Only one of --webapprt-content and --webapprt-chrome may be given.")
|
||||
|
||||
return options
|
||||
|
||||
|
||||
|
@ -323,6 +336,7 @@ class MochitestServer:
|
|||
self.webServer = options.webServer
|
||||
self.httpPort = options.httpPort
|
||||
self.shutdownURL = "http://%(server)s:%(port)s/server/shutdown" % { "server" : self.webServer, "port" : self.httpPort }
|
||||
self.testPrefix = "'webapprt_'" if options.webapprtContent else "undefined"
|
||||
|
||||
def start(self):
|
||||
"Run the Mochitest server, returning the process ID of the server."
|
||||
|
@ -335,8 +349,8 @@ class MochitestServer:
|
|||
args = ["-g", self._xrePath,
|
||||
"-v", "170",
|
||||
"-f", "./" + "httpd.js",
|
||||
"-e", "const _PROFILE_PATH = '%(profile)s';const _SERVER_PORT = '%(port)s'; const _SERVER_ADDR ='%(server)s';" %
|
||||
{"profile" : self._profileDir.replace('\\', '\\\\'), "port" : self.httpPort, "server" : self.webServer },
|
||||
"-e", "const _PROFILE_PATH = '%(profile)s';const _SERVER_PORT = '%(port)s'; const _SERVER_ADDR = '%(server)s'; const _TEST_PREFIX = %(testPrefix)s;" %
|
||||
{"profile" : self._profileDir.replace('\\', '\\\\'), "port" : self.httpPort, "server" : self.webServer, "testPrefix" : self.testPrefix },
|
||||
"-f", "./" + "server.js"]
|
||||
|
||||
xpcshell = os.path.join(self._utilityPath,
|
||||
|
@ -547,7 +561,7 @@ class Mochitest(object):
|
|||
# allow relative paths for logFile
|
||||
if options.logFile:
|
||||
options.logFile = self.getLogFilePath(options.logFile)
|
||||
if options.browserChrome or options.chrome or options.a11y:
|
||||
if options.browserChrome or options.chrome or options.a11y or options.webapprtChrome:
|
||||
self.makeTestConfig(options)
|
||||
else:
|
||||
if options.autorun:
|
||||
|
@ -641,6 +655,10 @@ class Mochitest(object):
|
|||
if len(self.urlOpts) > 0:
|
||||
testURL += "?" + "&".join(self.urlOpts)
|
||||
|
||||
if options.webapprtContent:
|
||||
options.browserArgs.extend(('-test-mode', testURL))
|
||||
testURL = None
|
||||
|
||||
# Remove the leak detection file so it can't "leak" to the tests run.
|
||||
# The file is not there if leak logging was not enabled in the application build.
|
||||
if os.path.exists(self.leak_report_file):
|
||||
|
@ -655,7 +673,9 @@ class Mochitest(object):
|
|||
timeout = 330.0 # default JS harness timeout is 300 seconds
|
||||
|
||||
# it's a debug build, we can parse leaked DOMWindows and docShells
|
||||
if Automation.IS_DEBUG_BUILD:
|
||||
# but skip for WebappRT chrome tests, where DOMWindow "leaks" aren't
|
||||
# meaningful. See https://bugzilla.mozilla.org/show_bug.cgi?id=733631#c46
|
||||
if Automation.IS_DEBUG_BUILD and not options.webapprtChrome:
|
||||
logger = ShutdownLeakLogger(self.automation.log)
|
||||
else:
|
||||
logger = None
|
||||
|
@ -733,7 +753,9 @@ class Mochitest(object):
|
|||
testRoot = 'browser'
|
||||
elif (options.a11y):
|
||||
testRoot = 'a11y'
|
||||
|
||||
elif (options.webapprtChrome):
|
||||
testRoot = 'webapprtChrome'
|
||||
|
||||
if "MOZ_HIDE_RESULTS_TABLE" in os.environ and os.environ["MOZ_HIDE_RESULTS_TABLE"] == "1":
|
||||
options.hideResultsTable = True
|
||||
|
||||
|
@ -795,13 +817,15 @@ toolbar#nav-bar {
|
|||
self.automation.log.warning("TEST-UNEXPECTED-FAIL | invalid setup: missing mochikit extension")
|
||||
return None
|
||||
|
||||
# Support Firefox (browser), B2G (shell) and SeaMonkey (navigator).
|
||||
# Support Firefox (browser), B2G (shell), SeaMonkey (navigator), and Webapp
|
||||
# Runtime (webapp).
|
||||
chrome = ""
|
||||
if options.browserChrome or options.chrome or options.a11y:
|
||||
if options.browserChrome or options.chrome or options.a11y or options.webapprtChrome:
|
||||
chrome += """
|
||||
overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||
overlay chrome://browser/content/shell.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||
overlay chrome://navigator/content/navigator.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||
overlay chrome://webapprt/content/webapp.xul chrome://mochikit/content/browser-test-overlay.xul
|
||||
"""
|
||||
|
||||
self.installChromeJar(jarDir, chrome, options)
|
||||
|
|
|
@ -431,8 +431,10 @@ function isTest(filename, pattern)
|
|||
return pattern.test(filename);
|
||||
|
||||
// File name is a URL style path to a test file, make sure that we check for
|
||||
// tests that start with test_.
|
||||
testPattern = /^test_/;
|
||||
// tests that start with the appropriate prefix.
|
||||
var testPrefix = typeof(_TEST_PREFIX) == "string" ? _TEST_PREFIX : "test_";
|
||||
var testPattern = new RegExp("^" + testPrefix);
|
||||
|
||||
pathPieces = filename.split('/');
|
||||
|
||||
return testPattern.test(pathPieces[pathPieces.length - 1]) &&
|
||||
|
|
|
@ -129,6 +129,16 @@ else
|
|||
endif
|
||||
$(CHECK_TEST_ERROR)
|
||||
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
webapprt_stub_path = $(TARGET_DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/webapprt-stub$(BIN_SUFFIX)
|
||||
webapprt-test-content:
|
||||
$(RUN_MOCHITEST) --webapprt-content --appname $(webapprt_stub_path)
|
||||
$(CHECK_TEST_ERROR)
|
||||
webapprt-test-chrome:
|
||||
$(RUN_MOCHITEST) --webapprt-chrome --appname $(webapprt_stub_path) --browser-arg -test-mode
|
||||
$(CHECK_TEST_ERROR)
|
||||
endif
|
||||
|
||||
# Usage: |make [EXTRA_TEST_ARGS=...] *test|.
|
||||
RUN_REFTEST = rm -f ./$@.log && $(PYTHON) _tests/reftest/runreftest.py \
|
||||
$(SYMBOLS_PATH) $(EXTRA_TEST_ARGS) $(1) | tee ./$@.log
|
||||
|
|
|
@ -17,16 +17,61 @@ CommandLineHandler.prototype = {
|
|||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
|
||||
|
||||
handle: function handle(cmdLine) {
|
||||
let args = Cc["@mozilla.org/hash-property-bag;1"].
|
||||
createInstance(Ci.nsIWritablePropertyBag);
|
||||
let inTestMode = this._handleTestMode(cmdLine, args);
|
||||
Services.obs.notifyObservers(args, "webapprt-command-line", null);
|
||||
|
||||
// Initialize DOMApplicationRegistry by importing Webapps.jsm, but only
|
||||
// after broadcasting webapprt-command-line. Webapps.jsm calls
|
||||
// DOMApplicationRegistry.init() when it's first imported. init() accesses
|
||||
// the WebappRegD directory, which in test mode is special-cased by
|
||||
// DirectoryProvider.js after it observes webapprt-command-line.
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
|
||||
if (!inTestMode) {
|
||||
startUp();
|
||||
} else {
|
||||
// startUp() accesses WebappRT.config, which in test mode is not valid
|
||||
// until WebappRT.jsm observes an app installation.
|
||||
Services.obs.addObserver(function onInstall(subj, topic, data) {
|
||||
Services.obs.removeObserver(onInstall, "webapprt-test-did-install");
|
||||
startUp();
|
||||
}, "webapprt-test-did-install", false);
|
||||
}
|
||||
|
||||
// Open the window with arguments to identify it as the main window
|
||||
Services.ww.openWindow(null,
|
||||
"chrome://webapprt/content/webapp.xul",
|
||||
"_blank",
|
||||
"chrome,dialog=no,resizable,scrollbars,centerscreen",
|
||||
[]);
|
||||
args);
|
||||
},
|
||||
|
||||
// Initialize window-independent handling of webapps- notifications
|
||||
Cu.import("resource://webapprt/modules/WebappsHandler.jsm");
|
||||
WebappsHandler.init();
|
||||
_handleTestMode: function _handleTestMode(cmdLine, args) {
|
||||
// -test-mode [url]
|
||||
let idx = cmdLine.findFlag("test-mode", true);
|
||||
if (idx < 0)
|
||||
return false;
|
||||
let url = null;
|
||||
let urlIdx = idx + 1;
|
||||
if (urlIdx < cmdLine.length) {
|
||||
let potentialURL = cmdLine.getArgument(urlIdx);
|
||||
if (potentialURL && potentialURL[0] != "-") {
|
||||
url = potentialURL;
|
||||
try {
|
||||
Services.io.newURI(url, null, null);
|
||||
} catch (err) {
|
||||
throw Components.Exception(
|
||||
"-test-mode argument is not a valid URL: " + url,
|
||||
Components.results.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
cmdLine.removeArguments(urlIdx, urlIdx);
|
||||
}
|
||||
}
|
||||
cmdLine.removeArguments(idx, idx);
|
||||
args.setProperty("test-mode", url);
|
||||
return true;
|
||||
},
|
||||
|
||||
helpInfo : "",
|
||||
|
@ -43,31 +88,40 @@ let NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
|||
* the command-line handler from being registered/accessible, since otherwise
|
||||
* the app won't start, which is catastrophic failure. That's why it's all
|
||||
* wrapped in a try/catch block. */
|
||||
function startUp(inTestMode) {
|
||||
try {
|
||||
if (!inTestMode) {
|
||||
// Initialize window-independent handling of webapps- notifications. Skip
|
||||
// this in test mode, since it interferes with test app installations.
|
||||
// We'll have to revisit this when we actually want to test installations
|
||||
// and other functionality provided by WebappsHandler.
|
||||
Cu.import("resource://webapprt/modules/WebappsHandler.jsm");
|
||||
WebappsHandler.init();
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialize DOMApplicationRegistry so it can receive/respond to messages.
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
// On firstrun, set permissions to their default values.
|
||||
if (!Services.prefs.getBoolPref("webapprt.firstrun")) {
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
let uri = Services.io.newURI(WebappRT.config.app.origin, null, null);
|
||||
|
||||
// On firstrun, set permissions to their default values.
|
||||
if (!Services.prefs.getBoolPref("webapprt.firstrun")) {
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
let uri = Services.io.newURI(WebappRT.config.app.origin, null, null);
|
||||
// Set AppCache-related permissions.
|
||||
Services.perms.add(uri, "pin-app",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.add(uri, "offline-app",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
// Set AppCache-related permissions.
|
||||
Services.perms.add(uri, "pin-app", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.add(uri, "offline-app",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.add(uri, "indexedDB",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.add(uri, "indexedDB-unlimited",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
Services.perms.add(uri, "indexedDB", Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
Services.perms.add(uri, "indexedDB-unlimited",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
|
||||
// Now that we've set the appropriate permissions, twiddle the firstrun flag
|
||||
// so we don't try to do so again.
|
||||
Services.prefs.setBoolPref("webapprt.firstrun", true);
|
||||
}
|
||||
} catch(ex) {
|
||||
// Now that we've set the appropriate permissions, twiddle the firstrun
|
||||
// flag so we don't try to do so again.
|
||||
Services.prefs.setBoolPref("webapprt.firstrun", true);
|
||||
}
|
||||
} catch(ex) {
|
||||
#ifdef MOZ_DEBUG
|
||||
dump(ex + "\n");
|
||||
dump(ex + "\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,14 @@ const NS_APP_CHROME_DIR_LIST = "AChromDL";
|
|||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://webapprt/modules/WebappRT.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let gInTestMode = false;
|
||||
Services.obs.addObserver(function observe(subj, topic, data) {
|
||||
Services.obs.removeObserver(observe, "webapprt-command-line");
|
||||
let args = subj.QueryInterface(Ci.nsIPropertyBag2);
|
||||
gInTestMode = args.hasKey("test-mode");
|
||||
}, "webapprt-command-line", false);
|
||||
|
||||
function DirectoryProvider() {}
|
||||
|
||||
|
@ -23,6 +31,13 @@ DirectoryProvider.prototype = {
|
|||
|
||||
getFile: function(prop, persistent) {
|
||||
if (prop == WEBAPP_REGISTRY_DIR) {
|
||||
if (gInTestMode) {
|
||||
// In test mode, apps are registered in the runtime's profile. Note
|
||||
// that in test mode WebappRT.config may not be valid at this point.
|
||||
// It's only valid after WebappRT.jsm observes an app installation, and
|
||||
// we can get here before any app is installed.
|
||||
return FileUtils.getDir("ProfD", []);
|
||||
}
|
||||
let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
dir.initWithPath(WebappRT.config.registryDir);
|
||||
return dir;
|
||||
|
|
|
@ -46,6 +46,10 @@ EXTRA_JS_MODULES = \
|
|||
PREF_JS_EXPORTS = $(srcdir)/prefs.js \
|
||||
$(NULL)
|
||||
|
||||
TEST_DIRS += \
|
||||
test \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
|
|
|
@ -9,12 +9,36 @@ const Ci = Components.interfaces;
|
|||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "FileUtils", function() {
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
return FileUtils;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function() {
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
return DOMApplicationRegistry;
|
||||
});
|
||||
|
||||
// In test mode, observe webapps-ask-install so tests can install apps.
|
||||
Services.obs.addObserver(function observeCmdLine(subj, topic, data) {
|
||||
Services.obs.removeObserver(observeCmdLine, "webapprt-command-line");
|
||||
let args = subj.QueryInterface(Ci.nsIPropertyBag2);
|
||||
if (!args.hasKey("test-mode"))
|
||||
return;
|
||||
Services.obs.addObserver(function observeInstall(subj, topic, data) {
|
||||
// observeInstall is present for the lifetime of the runtime.
|
||||
let config = JSON.parse(data);
|
||||
config.registryDir = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
|
||||
delete WebappRT.config;
|
||||
WebappRT.config = deepFreeze(config);
|
||||
DOMApplicationRegistry.confirmInstall(config);
|
||||
Services.obs.notifyObservers(null, "webapprt-test-did-install",
|
||||
JSON.stringify(config));
|
||||
}, "webapps-ask-install", false);
|
||||
}, "webapprt-command-line", false);
|
||||
|
||||
let WebappRT = {
|
||||
get config() {
|
||||
let webappFile = FileUtils.getFile("AppRegD", ["webapp.json"]);
|
||||
|
|
|
@ -12,10 +12,36 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
function onLoad() {
|
||||
window.removeEventListener("load", onLoad, false);
|
||||
|
||||
let cmdLineArgs = window.arguments && window.arguments[0] ?
|
||||
window.arguments[0].QueryInterface(Ci.nsIPropertyBag2) :
|
||||
null;
|
||||
|
||||
// In test mode, listen for test app installations and load the -test-mode URL
|
||||
// if present.
|
||||
if (cmdLineArgs && cmdLineArgs.hasKey("test-mode")) {
|
||||
Services.obs.addObserver(function observe(subj, topic, data) {
|
||||
// The observer is present for the lifetime of the runtime.
|
||||
initWindow(false);
|
||||
}, "webapprt-test-did-install", false);
|
||||
let testURL = cmdLineArgs.get("test-mode");
|
||||
if (testURL) {
|
||||
document.getElementById("content").loadURI(testURL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
initWindow(!!cmdLineArgs);
|
||||
}
|
||||
|
||||
window.addEventListener("load", onLoad, false);
|
||||
|
||||
function initWindow(isMainWindow) {
|
||||
// Set the title of the window to the name of the webapp
|
||||
let manifest = WebappRT.config.app.manifest;
|
||||
document.documentElement.setAttribute("title", manifest.name);
|
||||
|
||||
updateMenuItems();
|
||||
|
||||
// Listen for clicks to redirect <a target="_blank"> to the browser.
|
||||
// This doesn't capture clicks so content can capture them itself and do
|
||||
// something different if it doesn't want the default behavior.
|
||||
|
@ -23,7 +49,7 @@ function onLoad() {
|
|||
false, true);
|
||||
|
||||
// Only load the webapp on the initially launched main window
|
||||
if ("arguments" in window) {
|
||||
if (isMainWindow) {
|
||||
// Load the webapp's launch URL
|
||||
let installRecord = WebappRT.config.app;
|
||||
let url = Services.io.newURI(installRecord.origin, null, null);
|
||||
|
@ -32,7 +58,6 @@ function onLoad() {
|
|||
document.getElementById("content").setAttribute("src", url.spec);
|
||||
}
|
||||
}
|
||||
window.addEventListener("load", onLoad, false);
|
||||
|
||||
/**
|
||||
* Direct a click on <a target="_blank"> to the user's default browser.
|
||||
|
@ -66,11 +91,10 @@ function onContentClick(event) {
|
|||
event.preventDefault();
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// On Mac, we dynamically create the label for the Quit menuitem, using
|
||||
// a string property to inject the name of the webapp into it.
|
||||
window.addEventListener("load", function onLoadUpdateMenuItems() {
|
||||
window.removeEventListener("load", onLoadUpdateMenuItems, false);
|
||||
function updateMenuItems() {
|
||||
#ifdef XP_MACOSX
|
||||
let installRecord = WebappRT.config.app;
|
||||
let manifest = WebappRT.config.app.manifest;
|
||||
let bundle =
|
||||
|
@ -81,8 +105,8 @@ window.addEventListener("load", function onLoadUpdateMenuItems() {
|
|||
[manifest.name], 1);
|
||||
document.getElementById("menu_FileQuitItem").setAttribute("label", quitLabel);
|
||||
document.getElementById("menu_mac_hide_app").setAttribute("label", hideLabel);
|
||||
}, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
function updateEditUIVisibility() {
|
||||
#ifndef XP_MACOSX
|
||||
|
|
|
@ -90,6 +90,9 @@ main(int argc, char **argv)
|
|||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSDictionary *args = [[NSUserDefaults standardUserDefaults]
|
||||
volatileDomainForName:NSArgumentDomain];
|
||||
|
||||
NSString *firefoxPath = nil;
|
||||
NSString *alternateBinaryID = nil;
|
||||
|
||||
|
@ -199,11 +202,6 @@ main(int argc, char **argv)
|
|||
|
||||
NS_LogInit();
|
||||
{ // Scope for any XPCOM stuff we create
|
||||
nsINIParser parser;
|
||||
if (NS_FAILED(parser.Init(appEnv))) {
|
||||
NSLog(@"%s was not found\n", appEnv);
|
||||
@throw MakeException(@"Error", @"Unable to parse environment files for application startup");
|
||||
}
|
||||
|
||||
// Get the path to the runtime directory.
|
||||
char rtDir[MAXPATHLEN];
|
||||
|
@ -234,13 +232,24 @@ main(int argc, char **argv)
|
|||
@throw MakeException(@"Error", @"Unable to parse base INI file.");
|
||||
}
|
||||
|
||||
char profile[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {
|
||||
NSLog(@"Unable to retrieve profile from web app INI file");
|
||||
@throw MakeException(@"Error", @"Unable to retrieve installation profile.");
|
||||
NSString *profile = [args objectForKey:@"profile"];
|
||||
if (profile) {
|
||||
NSLog(@"Profile specified with -profile: %@", profile);
|
||||
}
|
||||
else {
|
||||
nsINIParser parser;
|
||||
if (NS_FAILED(parser.Init(appEnv))) {
|
||||
NSLog(@"%s was not found\n", appEnv);
|
||||
@throw MakeException(@"Error", @"Unable to parse environment files for application startup");
|
||||
}
|
||||
char profile[MAXPATHLEN];
|
||||
if (NS_FAILED(parser.GetString("Webapp", "Profile", profile, MAXPATHLEN))) {
|
||||
NSLog(@"Unable to retrieve profile from web app INI file");
|
||||
@throw MakeException(@"Error", @"Unable to retrieve installation profile.");
|
||||
}
|
||||
NSLog(@"setting app profile: %s", profile);
|
||||
SetAllocatedString(webShellAppData->profile, profile);
|
||||
}
|
||||
NSLog(@"setting app profile: %s", profile);
|
||||
SetAllocatedString(webShellAppData->profile, profile);
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
if (NS_FAILED(XRE_GetFileFromPath(rtDir, getter_AddRefs(directory)))) {
|
||||
|
@ -309,6 +318,14 @@ NSString
|
|||
//default is firefox
|
||||
NSString *binaryPath = nil;
|
||||
|
||||
// We're run from the Firefox bundle during WebappRT chrome and content tests.
|
||||
NSString *myBundlePath = [[NSBundle mainBundle] bundlePath];
|
||||
NSString *fxPath = [NSString stringWithFormat:@"%@%sfirefox-bin",
|
||||
myBundlePath, APP_CONTENTS_PATH];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:fxPath]) {
|
||||
return myBundlePath;
|
||||
}
|
||||
|
||||
//we look for these flavors of Firefox, in this order
|
||||
NSArray* launchBinarySearchList = [NSArray arrayWithObjects: @"org.mozilla.nightly",
|
||||
@"org.mozilla.aurora",
|
||||
|
|
|
@ -0,0 +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/.
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS += \
|
||||
chrome \
|
||||
content \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,23 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = webapprt/test/chrome
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
head.js \
|
||||
install.html \
|
||||
browser_sample.js \
|
||||
sample.webapp \
|
||||
sample.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/webapprtChrome/$(relativesrcdir)
|
|
@ -0,0 +1,19 @@
|
|||
// This is a sample WebappRT chrome test. It's just a browser-chrome mochitest.
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
ok(true, "true is true!");
|
||||
installWebapp("sample.webapp", undefined, function onInstall(appConfig) {
|
||||
is(document.documentElement.getAttribute("title"),
|
||||
appConfig.app.manifest.name,
|
||||
"Window title should be webapp name");
|
||||
let content = document.getElementById("content");
|
||||
let msg = content.contentDocument.getElementById("msg");
|
||||
var observer = new MutationObserver(function (mutations) {
|
||||
ok(/^Webapp getSelf OK:/.test(msg.textContent),
|
||||
"The webapp should have successfully installed and updated its msg");
|
||||
finish();
|
||||
});
|
||||
observer.observe(msg, { childList: true });
|
||||
});
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* 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 INSTALL_URL =
|
||||
"http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/install.html";
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/**
|
||||
* Installs the given webapp and navigates to it.
|
||||
*
|
||||
* @param manifestPath
|
||||
* The path of the webapp's manifest relative to
|
||||
* http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/.
|
||||
* @param parameters
|
||||
* The value to pass as the "parameters" argument to
|
||||
* mozIDOMApplicationRegistry.install, e.g., { receipts: ... }. Use
|
||||
* undefined to pass nothing.
|
||||
* @param callback
|
||||
* Called when the newly installed webapp is navigated to. It's passed
|
||||
* the webapp's config object.
|
||||
*/
|
||||
function installWebapp(manifestPath, parameters, onInstall) {
|
||||
// Three steps: (1) Load install.html, (2) listen for webapprt-test-did-
|
||||
// install to get the app config object, and then (3) listen for load of the
|
||||
// webapp page to call the callback. webapprt-test-did-install will be
|
||||
// broadcasted before install.html navigates to the webapp page. (This is due
|
||||
// to some implementation details: WebappRT.jsm confirms the installation by
|
||||
// calling DOMApplicationRegistry.confirmInstall, and then it immediately
|
||||
// broadcasts webapprt-test-did-install. confirmInstall asynchronously
|
||||
// notifies the mozApps consumer via onsuccess, which is when install.html
|
||||
// navigates to the webapp page.)
|
||||
|
||||
let content = document.getElementById("content");
|
||||
|
||||
Services.obs.addObserver(function observe(subj, topic, data) {
|
||||
// step 2
|
||||
Services.obs.removeObserver(observe, "webapprt-test-did-install");
|
||||
let appConfig = JSON.parse(data);
|
||||
|
||||
content.addEventListener("load", function onLoad(event) {
|
||||
// step 3
|
||||
content.removeEventListener("load", onLoad, true);
|
||||
let webappURL = appConfig.app.origin + appConfig.app.manifest.launch_path;
|
||||
is(event.target.URL, webappURL,
|
||||
"No other page should have loaded between installation and " +
|
||||
"the webapp's page load: " + event.target.URL);
|
||||
onInstall(appConfig);
|
||||
}, true);
|
||||
}, "webapprt-test-did-install", false);
|
||||
|
||||
// step 1
|
||||
let args = [["manifestPath", manifestPath]];
|
||||
if (parameters !== undefined) {
|
||||
args.push(["parameters", parameters]);
|
||||
}
|
||||
let queryStr = args.map(function ([key, val])
|
||||
key + "=" + encodeURIComponent(JSON.stringify(val))).
|
||||
join("&");
|
||||
let installURL = INSTALL_URL + "?" + queryStr;
|
||||
content.loadURI(installURL);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE HTML>
|
||||
|
||||
<!--
|
||||
Chrome tests load this file to install their webapps. Pass manifestPath=path
|
||||
in the query string to install the app with the manifest at
|
||||
http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/<path>.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
|
||||
function parseQueryStr() {
|
||||
return window.location.search.substr(1).split("&").
|
||||
map(function (pairStr) pairStr.split("=")).
|
||||
reduce(function (memo, [key, val]) {
|
||||
memo[key] = JSON.parse(decodeURIComponent(val));
|
||||
return memo;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function msg(str) {
|
||||
document.getElementById("msg").textContent = str;
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
var args = parseQueryStr();
|
||||
if (!args.manifestPath) {
|
||||
msg("No manifest path given, so standing by.");
|
||||
return;
|
||||
}
|
||||
var manifestURL =
|
||||
"http://mochi.test:8888/webapprtChrome/webapprt/test/chrome/" +
|
||||
args.manifestPath;
|
||||
var installArgs = [manifestURL, args.parameters];
|
||||
msg("Installing webapp with arguments " + installArgs.toSource() + "...");
|
||||
var install = navigator.mozApps.install.apply(navigator.mozApps, installArgs);
|
||||
install.onsuccess = function (event) {
|
||||
msg("Webapp installed, now navigating to it.");
|
||||
var testAppURL = install.result.origin +
|
||||
install.result.manifest.launch_path;
|
||||
window.location = testAppURL;
|
||||
};
|
||||
install.onerror = function () {
|
||||
msg("Webapp installation failed with " + install.error.name +
|
||||
" for manifest " + manifestURL);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="onLoad();" onunload="">
|
||||
<p id="msg">Installation page waiting for page load...</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE HTML>
|
||||
|
||||
<!--
|
||||
This is the webapp. It doesn't need to do anything in particular, just
|
||||
whatever you want to test from your browser_ test file.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
|
||||
function onLoad() {
|
||||
var msg = document.getElementById("msg");
|
||||
var self = navigator.mozApps.getSelf();
|
||||
self.onsuccess = function () {
|
||||
msg.textContent = "Webapp getSelf OK: " + self.result;
|
||||
};
|
||||
self.onerror = function () {
|
||||
msg.textContent = "Webapp getSelf failed: " + self.error.name;
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="onLoad();" onunload="">
|
||||
<p>This is the test webapp.</p>
|
||||
<p id="msg">Webapp waiting for page load...</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
{"name": "Sample Test Webapp", "description": "A webapp that demonstrates how to make a WebappRT test.", "launch_path": "/webapprtChrome/webapprt/test/chrome/sample.html" }
|
|
@ -0,0 +1,22 @@
|
|||
# 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/.
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = webapprt/test/content
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES = \
|
||||
helpers.js \
|
||||
webapprt_sample.html \
|
||||
sample.webapp \
|
||||
sample.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Shows a message on the page.
|
||||
*
|
||||
* @param str
|
||||
* The message to show.
|
||||
*/
|
||||
function msg(str) {
|
||||
document.getElementById("msg").textContent = str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the specified webapp and navigates to it in the iframe.
|
||||
*
|
||||
* @param manifestPath
|
||||
* The path of the manifest relative to
|
||||
* http://mochi.test:8888/tests/webapprt/test/content/.
|
||||
* @param parameters
|
||||
* The value to pass as the "parameters" argument to
|
||||
* mozIDOMApplicationRegistry.install, e.g., { receipts: ... }. Use
|
||||
* undefined to pass nothing.
|
||||
*/
|
||||
function installWebapp(manifestPath, parameters) {
|
||||
var manifestURL = "http://mochi.test:8888/tests/webapprt/test/content/" +
|
||||
manifestPath;
|
||||
var installArgs = [manifestURL, parameters];
|
||||
msg("Installing webapp with arguments " + installArgs.toSource() + "...");
|
||||
var install = navigator.mozApps.install.apply(navigator.mozApps, installArgs);
|
||||
install.onsuccess = function (event) {
|
||||
msg("Webapp installed.");
|
||||
var testAppURL = install.result.origin +
|
||||
install.result.manifest.launch_path +
|
||||
window.location.search;
|
||||
document.getElementById("webapp-iframe").src = testAppURL;
|
||||
};
|
||||
install.onerror = function () {
|
||||
msg("Webapp installation failed with " + install.error.name +
|
||||
" for manifest " + manifestURL);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* If webapprt_foo.html is loaded in the window, this function installs the
|
||||
* webapp whose manifest is named foo.webapp.
|
||||
*
|
||||
* @param parameters
|
||||
* The value to pass as the "parameters" argument to
|
||||
* mozIDOMApplicationRegistry.install, e.g., { receipts: ... }. Use
|
||||
* undefined to pass nothing.
|
||||
*/
|
||||
function installOwnWebapp(parameters) {
|
||||
var match = /webapprt_(.+)\.html$/.exec(window.location.pathname);
|
||||
if (!match) {
|
||||
throw new Error("Test URL is unconventional, so could not derive a " +
|
||||
"manifest URL from it: " + window.location);
|
||||
}
|
||||
installWebapp(match[1] + ".webapp", parameters);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE HTML>
|
||||
|
||||
<!--
|
||||
This file is the actual test. It's a webapp installed by webapprt_sample.html
|
||||
and loaded into its iframe. It's just a plain mochitest.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display">
|
||||
This is the test webapp.
|
||||
</p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
ok(true, "true is true!");
|
||||
|
||||
var self = navigator.mozApps.getSelf();
|
||||
self.onsuccess = function () {
|
||||
ok(true, "onsuccess should be called");
|
||||
ok(self.result, "result should be nonnull");
|
||||
ok(self.result.manifest, "manifest should be nonnull");
|
||||
is(self.result.manifest.name, "Sample Test Webapp", "manifest.name");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
self.onerror = function () {
|
||||
ok(false, "onerror should not be called");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
{"name": "Sample Test Webapp", "description": "A webapp that demonstrates how to make a WebappRT test.", "launch_path": "/tests/webapprt/test/content/sample.html" }
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML>
|
||||
|
||||
<!--
|
||||
Since its name is prefixed with webapprt_, this file is picked up by the
|
||||
mochitest harness. Once loaded, it installs the webapp, and when the
|
||||
installation completes, it loads the webapp into an iframe. The webapp is
|
||||
the actual test; see sample.html.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="helpers.js"></script>
|
||||
<script>
|
||||
|
||||
// If your installation page needs to do anything other than call
|
||||
// installOwnWebapp, you can do it here.
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="installOwnWebapp();">
|
||||
<p id="msg">Installation page waiting for page load...</p>
|
||||
<iframe id="webapp-iframe" width="100%" height="93%"></iframe>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче