Bug 1010387 - [appmgr v2] write tests and make good use of promises & tasks. r=janx r=jryans

---
 browser/devtools/app-manager/app-validator.js    |   2 +-
 browser/devtools/webide/content/newapp.js        |  30 +++-
 browser/devtools/webide/content/webide.js        | 180 +++++++++++++++--------
 browser/devtools/webide/modules/app-manager.js   |  27 +++-
 browser/devtools/webide/moz.build                |   1 +
 browser/devtools/webide/test/app.zip             | Bin 0 -> 480 bytes
 browser/devtools/webide/test/app/index.html      |   6 +
 browser/devtools/webide/test/app/manifest.webapp |   5 +
 browser/devtools/webide/test/chrome.ini          |  13 ++
 browser/devtools/webide/test/head.js             |  81 ++++++++++
 browser/devtools/webide/test/hosted_app.manifest |   3 +
 browser/devtools/webide/test/templates.json      |  14 ++
 browser/devtools/webide/test/test_basic.html     |  39 +++++
 browser/devtools/webide/test/test_import.html    |  65 ++++++++
 browser/devtools/webide/test/test_newapp.html    |  48 ++++++
 browser/devtools/webide/test/test_runtime.html   | 118 +++++++++++++++
 browser/devtools/webide/themes/details.css       |   1 -
 browser/devtools/webide/themes/newapp.css        |   4 -
 18 files changed, 558 insertions(+), 79 deletions(-)
 create mode 100644 browser/devtools/webide/test/app.zip
 create mode 100644 browser/devtools/webide/test/app/index.html
 create mode 100644 browser/devtools/webide/test/app/manifest.webapp
 create mode 100644 browser/devtools/webide/test/chrome.ini
 create mode 100644 browser/devtools/webide/test/head.js
 create mode 100644 browser/devtools/webide/test/hosted_app.manifest
 create mode 100644 browser/devtools/webide/test/templates.json
 create mode 100644 browser/devtools/webide/test/test_basic.html
 create mode 100644 browser/devtools/webide/test/test_import.html
 create mode 100644 browser/devtools/webide/test/test_newapp.html
 create mode 100644 browser/devtools/webide/test/test_runtime.html
This commit is contained in:
Paul Rouget 2014-05-21 09:29:43 +02:00
parent d05119d3c9
commit 19f1f1f91e
18 changed files with 555 additions and 76 deletions

View File

@ -100,7 +100,7 @@ AppValidator.prototype._getManifest = function () {
try {
Services.io.newURI(manifestURL, null, null);
} catch(e) {
this.error(strings.formatStringFromName("validator.invalidHostedManifestURL", [manifestURL, e.message]));
this.error(strings.formatStringFromName("validator.invalidHostedManifestURL", [manifestURL, e.message], 2));
return promise.resolve(null);
}
} else {

View File

@ -63,6 +63,14 @@ function getJSON() {
templatelistNode.appendChild(richlistitemNode);
}
templatelistNode.selectedIndex = 0;
/* Chrome mochitest support */
let testOptions = window.arguments[0].testOptions;
if (testOptions) {
templatelistNode.selectedIndex = testOptions.index;
document.querySelector("#project-name").value = testOptions.name;
doOK();
}
};
xhr.onerror = function() {
failAndBail("Can't download app templates");
@ -107,14 +115,22 @@ function doOK() {
return false;
}
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, "Select directory where to create app directory", Ci.nsIFilePicker.modeGetFolder);
let res = fp.show();
if (res == Ci.nsIFilePicker.returnCancel) {
AppManager.console.error("No directory selected");
return false;
let folder;
/* Chrome mochitest support */
let testOptions = window.arguments[0].testOptions;
if (testOptions) {
folder = testOptions.folder;
} else {
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, "Select directory where to create app directory", Ci.nsIFilePicker.modeGetFolder);
let res = fp.show();
if (res == Ci.nsIFilePicker.returnCancel) {
AppManager.console.error("No directory selected");
return false;
}
folder = fp.file;
}
let folder = fp.file;
// Create subfolder with fs-friendly name of project
let subfolder = projectName.replace(/\W/g, '').toLowerCase();

View File

@ -7,6 +7,8 @@ const Cu = Components.utils;
const Ci = Components.interfaces;
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
@ -14,6 +16,7 @@ const {Services} = Cu.import("resource://gre/modules/Services.jsm");
const {AppProjects} = require("devtools/app-manager/app-projects");
const {Connection} = require("devtools/client/connection-manager");
const {AppManager} = require("devtools/app-manager");
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const ProjectEditor = require("projecteditor/projecteditor");
const Strings = Services.strings.createBundle("chrome://webide/content/webide.properties");
@ -166,6 +169,7 @@ let UI = {
// Freeze the UI until the promise is resolved. A 30s timeout
// will unfreeze the UI, just in case the promise never gets
// resolved.
this.hidePanels();
let timeout = setTimeout(() => {
this.unbusy();
this.console.error("Operation timeout: " + operationDescription);
@ -174,10 +178,12 @@ let UI = {
promise.then(() => {
clearTimeout(timeout);
this.unbusy();
}, () => {
}, (e) => {
clearTimeout(timeout);
this.console.error("Error while processing: " + operationDescription + ": " + e);
this.unbusy();
});
return promise;
},
/********** RUNTIME **********/
@ -190,7 +196,7 @@ let UI = {
}
this.console.log("Found " + AppManager.runtimeList.usb.length + " USB devices.");
this.console.log("Found " + AppManager.runtimeList.simulators.length + " simulators.");
this.console.log("Found " + AppManager.runtimeList.simulator.length + " simulators.");
for (let runtime of AppManager.runtimeList.usb) {
let panelItemNode = document.createElement("toolbarbutton");
panelItemNode.className = "panel-item runtime-panel-item-usbruntime";
@ -206,7 +212,7 @@ let UI = {
while (simulatorListNode.hasChildNodes()) {
simulatorListNode.firstChild.remove();
}
for (let runtime of AppManager.runtimeList.simulators) {
for (let runtime of AppManager.runtimeList.simulator) {
let panelItemNode = document.createElement("toolbarbutton");
panelItemNode.className = "panel-item runtime-panel-item-simulator";
panelItemNode.setAttribute("label", runtime.getName());
@ -227,6 +233,7 @@ let UI = {
promise.then(
() => {this.console.success("Connected to " + name)},
() => {this.console.error("Can't connect to " + name)});
return promise;
},
updateRuntimeButton: function() {
@ -515,56 +522,95 @@ let Cmds = {
window.close();
},
newApp: function() {
UI.hidePanels();
let ret = {location:null};
window.openDialog("chrome://webide/content/newapp.xul", "newapp", "chrome,modal", ret);
if (!ret.location)
return;
let project = AppProjects.get(ret.location);
UI.busyUntil(AppManager.validateProject(project).then(() => {
UI.console.success("New project created at " + ret.location);
/**
* testOptions: { chrome mochitest support
* folder: nsIFile, where to store the app
* index: Number, index of the app in the template list
* name: String name of the app
* }
*/
newApp: function(testOptions) {
return UI.busyUntil(Task.spawn(function* () {
// Open newapp.xul, which will feed ret.location
let ret = {location: null, testOptions: testOptions};
window.openDialog("chrome://webide/content/newapp.xul", "newapp", "chrome,modal", ret);
if (!ret.location)
return;
// Retrieve added project
let project = AppProjects.get(ret.location);
// Validate project
yield AppManager.validateProject(project);
// Select project
AppManager.selectedProject = project;
}, (e) => UI.console.error("Error while create new app: " + e)), "creating new app");;
}), "creating new app");
},
importPackagedApp: function() {
UI.hidePanels();
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, Strings.GetStringFromName("importPackagedApp_title"), Ci.nsIFilePicker.modeGetFolder);
let res = fp.show();
if (res == Ci.nsIFilePicker.returnCancel)
return;
UI.busyUntil(AppProjects.addPackaged(fp.file)
.then(project => AppManager.validateProject(project))
.then(project => AppManager.selectedProject = project)
.then(( ) => { UI.console.log("New project successfuly added") },
(e) => { UI.console.error("Error while importing project: " + e) }),
"importing packaged app");
importPackagedApp: function(location) {
return UI.busyUntil(Task.spawn(function* () {
let directory;
if (!location) {
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, Strings.GetStringFromName("importPackagedApp_title"), Ci.nsIFilePicker.modeGetFolder);
let res = fp.show();
if (res == Ci.nsIFilePicker.returnCancel) {
return promise.resolve();
}
directory = fp.file;
} else {
directory = new FileUtils.File(location);
}
// Add project
let project = yield AppProjects.addPackaged(directory);
// Validate project
yield AppManager.validateProject(project);
// Select project
AppManager.selectedProject = project;
}), "importing packaged app");
},
importHostedApp: function() {
UI.hidePanels();
let promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
let ret = {value:null};
promptService.prompt(window,
Strings.GetStringFromName("importHostedApp_title"),
Strings.GetStringFromName("importHostedApp_header"),
ret, null, {});
let url = ret.value;
if (!url)
return;
UI.busyUntil(AppProjects.addHosted(url)
.then(project => AppManager.validateProject(project))
.then(project => AppManager.selectedProject = project)
.then(( ) => { UI.console.log("New project successfuly added") },
(e) => { UI.console.error("Error while importing project: " + e) }),
"importing hosted app");
importHostedApp: function(location) {
return UI.busyUntil(Task.spawn(function* () {
let ret = {value: null};
let url;
if (!location) {
Services.prompt.prompt(window,
Strings.GetStringFromName("importHostedApp_title"),
Strings.GetStringFromName("importHostedApp_header"),
ret, null, {});
location = ret.value;
}
if (!location) {
return;
}
// Add project
let project = yield AppProjects.addHosted(location)
// Validate project
yield AppManager.validateProject(project);
// Select project
AppManager.selectedProject = project;
}), "importing hosted app");
},
showProjectPanel: function() {
let deferred = promise.defer();
let panelNode = document.querySelector("#project-panel");
let panelVboxNode = document.querySelector("#project-panel > vbox");
let anchorNode = document.querySelector("#project-panel-button > .panel-button-anchor");
@ -603,10 +649,15 @@ let Cmds = {
// Open the popup only when the projects are added.
// Not doing it in the next tick can cause mis-calculations
// of the size of the panel.
function onPopupShown() {
panelNode.removeEventListener("popupshown", onPopupShown);
deferred.resolve();
}
panelNode.addEventListener("popupshown", onPopupShown);
panelNode.openPopup(anchorNode);
panelVboxNode.scrollTop = 0;
}, 0);
}, UI.console.error);
}, deferred.reject);
let runtimeappsHeaderNode = document.querySelector("#panel-header-runtimeapps");
@ -640,31 +691,40 @@ let Cmds = {
};
}, true);
}
return deferred.promise;
},
showRuntimePanel: function() {
let panel = document.querySelector("#runtime-panel");
let anchor = document.querySelector("#runtime-panel-button > .panel-button-anchor");
let deferred = promise.defer();
function onPopupShown() {
panel.removeEventListener("popupshown", onPopupShown);
deferred.resolve();
}
panel.addEventListener("popupshown", onPopupShown);
panel.openPopup(anchor);
return deferred.promise;
},
disconnectRuntime: function() {
UI.busyUntil(AppManager.disconnectRuntime());
return UI.busyUntil(AppManager.disconnectRuntime(), "disconnecting from runtime");
},
takeScreenshot: function() {
UI.hidePanels();
UI.busyUntil(AppManager.deviceFront.screenshotToDataURL().then(longstr => {
return UI.busyUntil(AppManager.deviceFront.screenshotToDataURL().then(longstr => {
return longstr.string().then(dataURL => {
longstr.release().then(null, UI.console.error);
UI.openInBrowser(dataURL);
});
}));
}), "taking screenshot");
},
showPermissionsTable: function() {
UI.hidePanels();
UI.busyUntil(AppManager.deviceFront.getRawPermissionsTable().then(json => {
return UI.busyUntil(AppManager.deviceFront.getRawPermissionsTable().then(json => {
let styleContent = "";
styleContent += "body {background:white; font-family: monospace}";
styleContent += "table {border-collapse: collapse}";
@ -713,8 +773,7 @@ let Cmds = {
},
showRuntimeDetails: function() {
UI.hidePanels();
UI.busyUntil(AppManager.deviceFront.getDescription().then(json => {
return UI.busyUntil(AppManager.deviceFront.getDescription().then(json => {
let styleContent = "";
styleContent += "body {background:white; font-family: monospace}";
styleContent += "table {border-collapse: collapse}";
@ -746,31 +805,34 @@ let Cmds = {
switch(AppManager.selectedProject.type) {
case "packaged":
case "hosted":
UI.busyUntil(AppManager.installAndRunProject(), "installing and running app");
return UI.busyUntil(AppManager.installAndRunProject(), "installing and running app");
break;
case "runtimeApp":
UI.busyUntil(AppManager.runRuntimeApp(), "running app");
return UI.busyUntil(AppManager.runRuntimeApp(), "running app");
break;
}
return promise.reject();
},
stop: function() {
UI.busyUntil(AppManager.stopRunningApp(), "stopping app");
return UI.busyUntil(AppManager.stopRunningApp(), "stopping app");
},
toggleToolbox: function() {
if (UI.toolboxIframe) {
UI.closeToolbox();
return promise.resolve();
} else {
UI.toolboxPromise = AppManager.getTarget().then((target) => {
return UI.showToolbox(target);
}, UI.console.error);
UI.busyUntil(UI.toolboxPromise, "opening toolbox");
return UI.toolboxPromise;
}
},
removeProject: function() {
AppManager.removeSelectedProject();
return AppManager.removeSelectedProject();
},
toggleEditors: function() {

View File

@ -34,7 +34,7 @@ exports.AppManager = AppManager = {
this.connection.on(Connection.Events.STATUS_CHANGED, this.onConnectionChanged);
this.webAppsStore = new WebappsStore(this.connection);
this.runtimeList = {usb:[], simulators:[]};
this.runtimeList = {usb: [], simulator: []};
this.trackUSBRuntimes();
this.trackSimulatorRuntimes();
},
@ -49,6 +49,7 @@ exports.AppManager = AppManager = {
this.runtimeList = null;
this.connection.off(Connection.Events.STATUS_CHANGED, this.onConnectionChanged);
this.webAppsStore.destroy();
this.webAppsStore = null;
this._listTabsResponse = null;
this.connection.disconnect();
this.connection = null;
@ -91,6 +92,9 @@ exports.AppManager = AppManager = {
_runningApps: new Set(),
_getRunningApps: function() {
let client = this.connection.client;
if (!this._listTabsResponse.webappsActor) {
return;
}
let request = {
to: this._listTabsResponse.webappsActor,
type: "listRunningApps"
@ -214,7 +218,7 @@ exports.AppManager = AppManager = {
removeSelectedProject: function() {
let location = this.selectedProject.location;
AppManager.selectedProject = null;
AppProjects.remove(location);
return AppProjects.remove(location);
},
_selectedRuntime: null,
@ -288,13 +292,16 @@ exports.AppManager = AppManager = {
installAndRunProject: function() {
let project = this.selectedProject;
if (!project ||
!this._listTabsResponse ||
(project.type != "packaged" && project.type != "hosted")) {
if (!project || (project.type != "packaged" && project.type != "hosted")) {
AppManager.console.error("Can't install project. Unknown type of project.");
return promise.reject("Can't install");
}
if (!this._listTabsResponse) {
AppManager.console.error("Can't install project. Not fully connected.");
return promise.reject("Can't install");
}
return this.validateProject(project).then(() => {
if (project.errorsCount > 0) {
@ -471,9 +478,9 @@ exports.AppManager = AppManager = {
Simulator.off("unregister", this._updateSimulatorRuntimes);
},
_updateSimulatorRuntimes: function() {
this.runtimeList.simulators = [];
this.runtimeList.simulator = [];
for (let version of Simulator.availableVersions()) {
this.runtimeList.simulators.push(new SimulatorRuntime(version));
this.runtimeList.simulator.push(new SimulatorRuntime(version));
}
this.update("runtimelist");
},
@ -517,6 +524,9 @@ USBRuntime.prototype = {
connection.connect();
});
},
getID: function() {
return this.id;
},
getName: function() {
return this.id;
},
@ -540,6 +550,9 @@ SimulatorRuntime.prototype = {
connection.connect();
});
},
getID: function() {
return this.version;
},
getName: function() {
return this.version;
},

View File

@ -9,3 +9,4 @@ PARALLEL_DIRS += [
'themes',
]
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']

Binary file not shown.

View File

@ -0,0 +1,6 @@
<!doctype html>
<html>
<head><title></title></head>
<body>
</body>
</html>

View File

@ -0,0 +1,5 @@
{
"name": "A name (in app directory)",
"description": "desc",
"launch_path": "/index.html"
}

View File

@ -0,0 +1,13 @@
[DEFAULT]
support-files =
app/index.html
app/manifest.webapp
app.zip
head.js
hosted_app.manifest
templates.json
[test_basic.html]
[test_newapp.html]
[test_import.html]
[test_runtime.html]

View File

@ -0,0 +1,81 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const {utils: Cu, classes: Cc, interfaces: Ci} = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
const {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const {AppProjects} = require("devtools/app-manager/app-projects");
const TEST_BASE = "chrome://mochitests/content/chrome/browser/devtools/webide/test/";
Services.prefs.setBoolPref("devtools.webide.enabled", true);
SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.webide.enabled");
});
function openWebIDE() {
info("opening WebIDE");
let deferred = promise.defer();
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
let win = ww.openWindow(null, "chrome://webide/content/", "webide", "chrome,centerscreen,resizable", null);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
info("WebIDE open");
SimpleTest.executeSoon(() => {
deferred.resolve(win);
});
});
return deferred.promise;
}
function closeWebIDE(win) {
info("Closing WebIDE");
let deferred = promise.defer();
win.addEventListener("unload", function onUnload() {
win.removeEventListener("unload", onUnload);
info("WebIDE closed");
SimpleTest.executeSoon(() => {
deferred.resolve();
});
});
win.close();
return deferred.promise;
}
function removeAllProjects() {
let deferred = promise.defer();
AppProjects.load().then(() => {
let projects = AppProjects.store.object.projects;
for (let i = 0; i < projects.length; i++) {
AppProjects.remove(projects[i].location);
}
deferred.resolve();
});
return deferred.promise;
}
function nextTick() {
let deferred = promise.defer();
SimpleTest.executeSoon(() => {
deferred.resolve();
});
return deferred.promise;
}

View File

@ -0,0 +1,3 @@
{
"name": "hosted manifest name property"
}

View File

@ -0,0 +1,14 @@
[
{
"file": "chrome://mochitests/content/chrome/browser/devtools/webide/test/app.zip?1",
"icon": "ximgx1",
"name": "app name 1",
"description": "app description 1"
},
{
"file": "chrome://mochitests/content/chrome/browser/devtools/webide/test/app.zip?2",
"icon": "ximgx2",
"name": "app name 2",
"description": "app description 2"
}
]

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript;version=1.8" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
openWebIDE().then((win) => {
ok(win, "Found a window");
ok(win.AppManager, "App Manager accessible");
let appmgr = win.AppManager;
ok(appmgr.connection, "App Manager connection ready");
ok(appmgr.runtimeList, "Runtime list ready");
ok(appmgr.webAppsStore, "WebApps store ready");
closeWebIDE(win).then(() => {
ok(!appmgr.connection, "App Manager connection destroyed");
ok(!appmgr.runtimeList, "Runtime list destroyed");
ok(!appmgr.webAppsStore, "WebApps store destroyed");
SimpleTest.finish();
});
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript;version=1.8" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
Task.spawn(function* () {
let win = yield openWebIDE();
let packagedAppLocation = getTestFilePath("app");
yield win.Cmds.importPackagedApp(packagedAppLocation);
let project = win.AppManager.selectedProject;
is(project.location, packagedAppLocation, "Location is valid");
is(project.name, "A name (in app directory)", "name field has been updated");
is(project.manifest.launch_path, "/index.html", "manifest found. launch_path valid.");
is(project.manifest.description, "desc", "manifest found. description valid");
yield nextTick();
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
yield win.Cmds.importHostedApp(hostedAppManifest);
project = win.AppManager.selectedProject;
is(project.location, hostedAppManifest, "Location is valid");
is(project.name, "hosted manifest name property", "name field has been updated");
info("opening panel");
yield win.Cmds.showProjectPanel();
info("panel open");
let panelNode = win.document.querySelector("#project-panel");
let items = panelNode.querySelectorAll(".panel-item");
// 3 controls, + 2 projects
is(items.length, 5, "5 projects in panel");
is(items[3].getAttribute("label"), "A name (in app directory)", "Panel label is correct");
is(items[4].getAttribute("label"), "hosted manifest name property", "Panel label is correct");
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript;version=1.8" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
Services.prefs.setCharPref("devtools.webide.templatesURL", TEST_BASE + "templates.json");
Task.spawn(function* () {
let win = yield openWebIDE();
let tmpDir = FileUtils.getDir("TmpD", []);
yield win.Cmds.newApp({
index: 0,
name: "webideTmpApp",
folder: tmpDir
});
let project = win.AppManager.selectedProject;
let tmpDir = FileUtils.getDir("TmpD", ["webidetmpapp"]);
ok(tmpDir.isDirectory(), "Directory created");
is(project.location, tmpDir.path, "Location is valid (and lowercase)");
is(project.name, "webideTmpApp", "name field has been updated");
// Clean up
tmpDir.remove(true);
Services.prefs.clearUserPref("devtools.webide.templatesURL");
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript;version=1.8" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
Task.spawn(function* () {
function isPlayActive() {
return !win.document.querySelector("#cmd_play").hasAttribute("disabled");
}
function isStopActive() {
return !win.document.querySelector("#cmd_stop").hasAttribute("disabled");
}
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
DebuggerServer.init(function () { return true; });
DebuggerServer.addBrowserActors();
let win = yield openWebIDE();
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
ok(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
},
getName: function() {
return "fakeRuntime";
}
});
win.AppManager.update("runtimelist");
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
yield win.Cmds.importHostedApp(hostedAppManifest);
yield win.Cmds.showRuntimePanel();
let panelNode = win.document.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-usbruntime");
is(items.length, 1, "Found one runtime button");
let deferred = promise.defer();
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
() => deferred.resolve());
items[0].click();
yield deferred.promise;
yield nextTick();
ok(!isPlayActive(), "play button is disabled 2");
ok(!isStopActive(), "stop button is disabled 2");
win.AppManager.selectedProject.errorsCount = 0;
win.UI.updateCommands();
yield nextTick();
ok(isPlayActive(), "play button is enabled 3");
ok(!isStopActive(), "stop button is disabled 3");
let oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = null;
yield nextTick();
ok(!isPlayActive(), "play button is disabled 4");
ok(!isStopActive(), "stop button is disabled 4");
win.AppManager._selectedProject = oldProject;
win.UI.updateCommands();
yield nextTick();
ok(isPlayActive(), "play button is enabled 5");
ok(!isStopActive(), "stop button is disabled 5");
yield win.Cmds.disconnectRuntime();
ok(win.AppManager.selectedProject, "A project is still selected");
ok(!isPlayActive(), "play button is disabled 6");
ok(!isStopActive(), "stop button is disabled 6");
yield closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View File

@ -61,7 +61,6 @@ header > div {
#icon {
height: 48px;
width: 48px;
text-align:top;
float: left;
margin: 0 20px;
}

View File

@ -43,10 +43,6 @@ richlistitem {
-moz-box-align: start;
}
richlistitem:nth-child(odd) {
background-color:
}
richlistitem > image {
height: 24px;
width: 24px;