Revert "Remove WebIDE devtools component."

This reverts commit 8c1500707f.

# Conflicts:
#	application/basilisk/components/customizableui/CustomizableUI.jsm
This commit is contained in:
Roy Tam 2019-10-18 09:09:39 +08:00
commit df89b48e30
163 changed files with 13812 additions and 0 deletions

View file

@ -0,0 +1,6 @@
"use strict";
module.exports = {
// Extend from the shared list of defined globals for mochitests.
"extends": "../../../.eslintrc.mochitests.js"
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,4 @@
{
"stable": ["1.0", "2.0"],
"unstable": ["3.0", "3.0_tv"]
}

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,12 @@
[DEFAULT]
tags = devtools
subsuite = devtools
support-files =
addons/simulators.json
doc_tabs.html
head.js
templates.json
[browser_tabs.js]
skip-if = e10s # Bug 1072167 - browser_tabs.js test fails under e10s
[browser_widget.js]

View file

@ -0,0 +1,84 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_URI = "http://example.com/browser/devtools/client/webide/test/doc_tabs.html";
function test() {
waitForExplicitFinish();
requestCompleteLog();
Task.spawn(function* () {
// Since we test the connections set below, destroy the server in case it
// was left open.
DebuggerServer.destroy();
DebuggerServer.init();
DebuggerServer.addBrowserActors();
let tab = yield addTab(TEST_URI);
let win = yield openWebIDE();
let docProject = getProjectDocument(win);
let docRuntime = getRuntimeDocument(win);
yield connectToLocal(win, docRuntime);
is(Object.keys(DebuggerServer._connections).length, 1, "Locally connected");
yield selectTabProject(win, docProject);
ok(win.UI.toolboxPromise, "Toolbox promise exists");
yield win.UI.toolboxPromise;
let project = win.AppManager.selectedProject;
is(project.location, TEST_URI, "Location is correct");
is(project.name, "example.com: Test Tab", "Name is correct");
// Ensure tab list changes are noticed
let tabsNode = docProject.querySelector("#project-panel-tabs");
is(tabsNode.querySelectorAll(".panel-item").length, 2, "2 tabs available");
yield removeTab(tab);
yield waitForUpdate(win, "project");
yield waitForUpdate(win, "runtime-targets");
is(tabsNode.querySelectorAll(".panel-item").length, 1, "1 tab available");
tab = yield addTab(TEST_URI);
is(tabsNode.querySelectorAll(".panel-item").length, 2, "2 tabs available");
yield removeTab(tab);
is(tabsNode.querySelectorAll(".panel-item").length, 2, "2 tabs available");
docProject.querySelector("#refresh-tabs").click();
yield waitForUpdate(win, "runtime-targets");
is(tabsNode.querySelectorAll(".panel-item").length, 1, "1 tab available");
yield win.Cmds.disconnectRuntime();
yield closeWebIDE(win);
DebuggerServer.destroy();
}).then(finish, handleError);
}
function connectToLocal(win, docRuntime) {
let deferred = promise.defer();
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
() => deferred.resolve());
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
return deferred.promise;
}
function selectTabProject(win, docProject) {
return Task.spawn(function* () {
yield waitForUpdate(win, "runtime-targets");
let tabsNode = docProject.querySelector("#project-panel-tabs");
let tabNode = tabsNode.querySelectorAll(".panel-item")[1];
let project = waitForUpdate(win, "project");
tabNode.click();
yield project;
});
}

View file

@ -0,0 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
waitForExplicitFinish();
Task.spawn(function* () {
let win = yield openWebIDE();
ok(document.querySelector("#webide-button"), "Found WebIDE button");
Services.prefs.setBoolPref("devtools.webide.widget.enabled", false);
ok(!document.querySelector("#webide-button"), "WebIDE button uninstalled");
yield closeWebIDE(win);
Services.prefs.clearUserPref("devtools.webide.widget.enabled");
}).then(finish, handleError);
}

View file

@ -0,0 +1,5 @@
{
"webide": {
"prepackage": "echo \"{\\\"name\\\":\\\"hello\\\"}\" > manifest.webapp"
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,10 @@
{
"webide": {
"prepackage": {
"command": "echo \"{\\\"name\\\":\\\"$NAME\\\"}\" > manifest.webapp",
"cwd": "./stage",
"env": ["NAME=world"]
},
"packageDir": "./stage"
}
}

View file

@ -0,0 +1,5 @@
{
"webide": {
"prepackage": "echo {\"name\":\"hello\"} > manifest.webapp"
}
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,10 @@
{
"webide": {
"prepackage": {
"command": "echo {\"name\":\"%NAME%\"} > manifest.webapp",
"cwd": "./stage",
"env": ["NAME=world"]
},
"packageDir": "./stage"
}
}

View file

@ -0,0 +1,71 @@
[DEFAULT]
tags = devtools
support-files =
app/index.html
app/manifest.webapp
app.zip
addons/simulators.json
addons/fxos_1_0_simulator-linux.xpi
addons/fxos_1_0_simulator-linux64.xpi
addons/fxos_1_0_simulator-win32.xpi
addons/fxos_1_0_simulator-mac64.xpi
addons/fxos_2_0_simulator-linux.xpi
addons/fxos_2_0_simulator-linux64.xpi
addons/fxos_2_0_simulator-win32.xpi
addons/fxos_2_0_simulator-mac64.xpi
addons/fxos_3_0_simulator-linux.xpi
addons/fxos_3_0_simulator-linux64.xpi
addons/fxos_3_0_simulator-win32.xpi
addons/fxos_3_0_simulator-mac64.xpi
addons/fxos_3_0_tv_simulator-linux.xpi
addons/fxos_3_0_tv_simulator-linux64.xpi
addons/fxos_3_0_tv_simulator-win32.xpi
addons/fxos_3_0_tv_simulator-mac64.xpi
addons/adbhelper-linux.xpi
addons/adbhelper-linux64.xpi
addons/adbhelper-win32.xpi
addons/adbhelper-mac64.xpi
addons/fxdt-adapters-linux32.xpi
addons/fxdt-adapters-linux64.xpi
addons/fxdt-adapters-win32.xpi
addons/fxdt-adapters-mac64.xpi
build_app1/package.json
build_app2/manifest.webapp
build_app2/package.json
build_app2/stage/empty-directory
build_app_windows1/package.json
build_app_windows2/manifest.webapp
build_app_windows2/package.json
build_app_windows2/stage/empty-directory
device_front_shared.js
head.js
hosted_app.manifest
templates.json
../../shared/test/browser_devices.json
validator/*
[test_basic.html]
[test_newapp.html]
skip-if = (os == "win" && os_version == "10.0") # Bug 1197053
[test_import.html]
skip-if = (os == "linux") # Bug 1024734
[test_duplicate_import.html]
[test_runtime.html]
[test_manifestUpdate.html]
[test_addons.html]
skip-if = true # Bug 1201392 - Update add-ons after migration
[test_device_runtime.html]
[test_device_permissions.html]
[test_autoconnect_runtime.html]
[test_autoselect_project.html]
[test_telemetry.html]
skip-if = true # Bug 1201392 - Update add-ons after migration
[test_device_preferences.html]
[test_device_settings.html]
[test_fullscreenToolbox.html]
[test_zoom.html]
[test_build.html]
[test_simulators.html]
skip-if = true # Bug 1281138 - intermittent failures
[test_toolbox.html]
[test_app_validator.html]

View file

@ -0,0 +1,219 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var customName;
var customValue;
var customValueType;
var customBtn;
var newField;
var change;
var doc;
var iframe;
var resetBtn;
var found = false;
function setDocument(frame) {
iframe = frame;
doc = iframe.contentWindow.document;
}
function fieldChange(fields, id) {
// Trigger existing field change
for (let field of fields) {
if (field.id == id) {
let button = doc.getElementById("btn-" + id);
found = true;
ok(button.classList.contains("hide"), "Default field detected");
field.value = "custom";
field.click();
ok(!button.classList.contains("hide"), "Custom field detected");
break;
}
}
ok(found, "Found " + id + " line");
}
function addNewField() {
found = false;
customName = doc.querySelector("#custom-value-name");
customValue = doc.querySelector("#custom-value-text");
customValueType = doc.querySelector("#custom-value-type");
customBtn = doc.querySelector("#custom-value");
change = doc.createEvent("HTMLEvents");
change.initEvent("change", false, true);
// Add a new custom string
customValueType.value = "string";
customValueType.dispatchEvent(change);
customName.value = "new-string-field!";
customValue.value = "test";
customBtn.click();
let newField = doc.querySelector("#new-string-field");
if (newField) {
found = true;
is(newField.type, "text", "Custom type is a string");
is(newField.value, "test", "Custom string new value is correct");
}
ok(found, "Found new string field line");
is(customName.value, "", "Custom string name reset");
is(customValue.value, "", "Custom string value reset");
}
function addNewFieldWithEnter() {
// Add a new custom value with the <enter> key
found = false;
customName.value = "new-string-field-two";
customValue.value = "test";
let newAddField = doc.querySelector("#add-custom-field");
let enter = doc.createEvent("KeyboardEvent");
enter.initKeyEvent(
"keyup", true, true, null, false, false, false, false, 13, 0);
newAddField.dispatchEvent(enter);
newField = doc.querySelector("#new-string-field-two");
if (newField) {
found = true;
is(newField.type, "text", "Custom type is a string");
is(newField.value, "test", "Custom string new value is correct");
}
ok(found, "Found new string field line");
is(customName.value, "", "Custom string name reset");
is(customValue.value, "", "Custom string value reset");
}
function editExistingField() {
// Edit existing custom string preference
newField.value = "test2";
newField.click();
is(newField.value, "test2", "Custom string existing value is correct");
}
function addNewFieldInteger() {
// Add a new custom integer preference with a valid integer
customValueType.value = "number";
customValueType.dispatchEvent(change);
customName.value = "new-integer-field";
customValue.value = 1;
found = false;
customBtn.click();
newField = doc.querySelector("#new-integer-field");
if (newField) {
found = true;
is(newField.type, "number", "Custom type is a number");
is(newField.value, "1", "Custom integer value is correct");
}
ok(found, "Found new integer field line");
is(customName.value, "", "Custom integer name reset");
is(customValue.value, "", "Custom integer value reset");
}
var editFieldInteger = Task.async(function* () {
// Edit existing custom integer preference
newField.value = 3;
newField.click();
is(newField.value, "3", "Custom integer existing value is correct");
// Reset a custom field
let resetBtn = doc.querySelector("#btn-new-integer-field");
resetBtn.click();
try {
yield iframe.contentWindow.configView._defaultField;
} catch (err) {
let fieldRow = doc.querySelector("#row-new-integer-field");
if (!fieldRow) {
found = false;
}
ok(!found, "Custom field removed");
}
});
var resetExistingField = Task.async(function* (id) {
let existing = doc.getElementById(id);
existing.click();
is(existing.checked, true, "Existing boolean value is correct");
resetBtn = doc.getElementById("btn-" + id);
resetBtn.click();
yield iframe.contentWindow.configView._defaultField;
ok(resetBtn.classList.contains("hide"), true, "Reset button hidden");
is(existing.checked, true, "Existing field reset");
});
var resetNewField = Task.async(function* (id) {
let custom = doc.getElementById(id);
custom.click();
is(custom.value, "test", "New string value is correct");
resetBtn = doc.getElementById("btn-" + id);
resetBtn.click();
yield iframe.contentWindow.configView._defaultField;
ok(resetBtn.classList.contains("hide"), true, "Reset button hidden");
});
function addNewFieldBoolean() {
customValueType.value = "boolean";
customValueType.dispatchEvent(change);
customName.value = "new-boolean-field";
customValue.checked = true;
found = false;
customBtn.click();
newField = doc.querySelector("#new-boolean-field");
if (newField) {
found = true;
is(newField.type, "checkbox", "Custom type is a checkbox");
is(newField.checked, true, "Custom boolean value is correctly true");
}
ok(found, "Found new boolean field line");
// Mouse event trigger
var mouseClick = new MouseEvent("click", {
canBubble: true,
cancelable: true,
view: doc.parent,
});
found = false;
customValueType.value = "boolean";
customValueType.dispatchEvent(change);
customName.value = "new-boolean-field2";
customValue.dispatchEvent(mouseClick);
customBtn.dispatchEvent(mouseClick);
newField = doc.querySelector("#new-boolean-field2");
if (newField) {
found = true;
is(newField.checked, true, "Custom boolean value is correctly false");
}
ok(found, "Found new second boolean field line");
is(customName.value, "", "Custom boolean name reset");
is(customValue.checked, false, "Custom boolean value reset");
newField.click();
is(newField.checked, false, "Custom boolean existing value is correct");
}
function searchFields(deck, keyword) {
// Search for a non-existent field
let searchField = doc.querySelector("#search-bar");
searchField.value = "![o_O]!";
searchField.click();
let fieldsTotal = doc.querySelectorAll("tr.edit-row").length;
let hiddenFields = doc.querySelectorAll("tr.hide");
is(hiddenFields.length, fieldsTotal, "Search keyword not found");
// Search for existing fields
searchField.value = keyword;
searchField.click();
hiddenFields = doc.querySelectorAll("tr.hide");
isnot(hiddenFields.length, fieldsTotal, "Search keyword found");
doc.querySelector("#close").click();
ok(!deck.selectedPanel, "No panel selected");
}

View file

@ -0,0 +1,15 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Test Tab</title>
</head>
<body>
Test Tab
</body>
</html>

View file

@ -0,0 +1,248 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
var {utils: Cu, classes: Cc, interfaces: Ci} = Components;
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
const { gDevTools } = require("devtools/client/framework/devtools");
const promise = require("promise");
const Services = require("Services");
const { Task } = require("devtools/shared/task");
const { AppProjects } = require("devtools/client/webide/modules/app-projects");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const { DebuggerServer } = require("devtools/server/main");
const flags = require("devtools/shared/flags");
flags.testing = true;
var TEST_BASE;
if (window.location === "chrome://browser/content/browser.xul") {
TEST_BASE = "chrome://mochitests/content/browser/devtools/client/webide/test/";
} else {
TEST_BASE = "chrome://mochitests/content/chrome/devtools/client/webide/test/";
}
Services.prefs.setBoolPref("devtools.webide.enabled", true);
Services.prefs.setBoolPref("devtools.webide.enableLocalRuntime", true);
Services.prefs.setCharPref("devtools.webide.addonsURL", TEST_BASE + "addons/simulators.json");
Services.prefs.setCharPref("devtools.webide.simulatorAddonsURL", TEST_BASE + "addons/fxos_#SLASHED_VERSION#_simulator-#OS#.xpi");
Services.prefs.setCharPref("devtools.webide.adbAddonURL", TEST_BASE + "addons/adbhelper-#OS#.xpi");
Services.prefs.setCharPref("devtools.webide.adaptersAddonURL", TEST_BASE + "addons/fxdt-adapters-#OS#.xpi");
Services.prefs.setCharPref("devtools.webide.templatesURL", TEST_BASE + "templates.json");
Services.prefs.setCharPref("devtools.devices.url", TEST_BASE + "browser_devices.json");
var registerCleanupFunction = registerCleanupFunction ||
SimpleTest.registerCleanupFunction;
registerCleanupFunction(() => {
flags.testing = false;
Services.prefs.clearUserPref("devtools.webide.enabled");
Services.prefs.clearUserPref("devtools.webide.enableLocalRuntime");
Services.prefs.clearUserPref("devtools.webide.autoinstallADBHelper");
Services.prefs.clearUserPref("devtools.webide.autoinstallFxdtAdapters");
Services.prefs.clearUserPref("devtools.webide.busyTimeout");
Services.prefs.clearUserPref("devtools.webide.lastSelectedProject");
Services.prefs.clearUserPref("devtools.webide.lastConnectedRuntime");
});
var openWebIDE = Task.async(function* (autoInstallAddons) {
info("opening WebIDE");
Services.prefs.setBoolPref("devtools.webide.autoinstallADBHelper", !!autoInstallAddons);
Services.prefs.setBoolPref("devtools.webide.autoinstallFxdtAdapters", !!autoInstallAddons);
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);
yield new Promise(resolve => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
SimpleTest.requestCompleteLog();
SimpleTest.executeSoon(resolve);
});
});
info("WebIDE open");
return win;
});
function closeWebIDE(win) {
info("Closing WebIDE");
let deferred = promise.defer();
Services.prefs.clearUserPref("devtools.webide.widget.enabled");
win.addEventListener("unload", function onUnload() {
win.removeEventListener("unload", onUnload);
info("WebIDE closed");
SimpleTest.executeSoon(() => {
deferred.resolve();
});
});
win.close();
return deferred.promise;
}
function removeAllProjects() {
return Task.spawn(function* () {
yield AppProjects.load();
// use a new array so we're not iterating over the same
// underlying array that's being modified by AppProjects
let projects = AppProjects.projects.map(p => p.location);
for (let i = 0; i < projects.length; i++) {
yield AppProjects.remove(projects[i]);
}
});
}
function nextTick() {
let deferred = promise.defer();
SimpleTest.executeSoon(() => {
deferred.resolve();
});
return deferred.promise;
}
function waitForUpdate(win, update) {
info("Wait: " + update);
let deferred = promise.defer();
win.AppManager.on("app-manager-update", function onUpdate(e, what) {
info("Got: " + what);
if (what !== update) {
return;
}
win.AppManager.off("app-manager-update", onUpdate);
deferred.resolve(win.UI._updatePromise);
});
return deferred.promise;
}
function waitForTime(time) {
let deferred = promise.defer();
setTimeout(() => {
deferred.resolve();
}, time);
return deferred.promise;
}
function documentIsLoaded(doc) {
let deferred = promise.defer();
if (doc.readyState == "complete") {
deferred.resolve();
} else {
doc.addEventListener("readystatechange", function onChange() {
if (doc.readyState == "complete") {
doc.removeEventListener("readystatechange", onChange);
deferred.resolve();
}
});
}
return deferred.promise;
}
function lazyIframeIsLoaded(iframe) {
let deferred = promise.defer();
iframe.addEventListener("load", function onLoad() {
iframe.removeEventListener("load", onLoad, true);
deferred.resolve(nextTick());
}, true);
return deferred.promise;
}
function addTab(aUrl, aWindow) {
info("Adding tab: " + aUrl);
let deferred = promise.defer();
let targetWindow = aWindow || window;
let targetBrowser = targetWindow.gBrowser;
targetWindow.focus();
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
let linkedBrowser = tab.linkedBrowser;
BrowserTestUtils.browserLoaded(linkedBrowser).then(function () {
info("Tab added and finished loading: " + aUrl);
deferred.resolve(tab);
});
return deferred.promise;
}
function removeTab(aTab, aWindow) {
info("Removing tab.");
let deferred = promise.defer();
let targetWindow = aWindow || window;
let targetBrowser = targetWindow.gBrowser;
let tabContainer = targetBrowser.tabContainer;
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
tabContainer.removeEventListener("TabClose", onClose, false);
info("Tab removed and finished closing.");
deferred.resolve();
}, false);
targetBrowser.removeTab(aTab);
return deferred.promise;
}
function getRuntimeDocument(win) {
return win.document.querySelector("#runtime-listing-panel-details").contentDocument;
}
function getProjectDocument(win) {
return win.document.querySelector("#project-listing-panel-details").contentDocument;
}
function getRuntimeWindow(win) {
return win.document.querySelector("#runtime-listing-panel-details").contentWindow;
}
function getProjectWindow(win) {
return win.document.querySelector("#project-listing-panel-details").contentWindow;
}
function connectToLocalRuntime(win) {
info("Loading local runtime.");
let panelNode;
let runtimePanel;
runtimePanel = getRuntimeDocument(win);
panelNode = runtimePanel.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-other");
is(items.length, 2, "Found 2 custom runtime buttons");
let updated = waitForUpdate(win, "runtime-global-actors");
items[1].click();
return updated;
}
function handleError(aError) {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
finish();
}
function waitForConnectionChange(expectedState, count = 1) {
return new Promise(resolve => {
let onConnectionChange = (_, state) => {
if (state != expectedState) {
return;
}
if (--count != 0) {
return;
}
DebuggerServer.off("connectionchange", onConnectionChange);
resolve();
};
DebuggerServer.on("connectionchange", onConnectionChange);
});
}

View file

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

View file

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

View file

@ -0,0 +1,176 @@
<!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();
const {GetAvailableAddons} = require("devtools/client/webide/modules/addons");
const {Devices} = Cu.import("resource://devtools/shared/apps/Devices.jsm");
const {Simulators} = require("devtools/client/webide/modules/simulators");
let adbAddonsInstalled = promise.defer();
Devices.on("addon-status-updated", function onUpdate1() {
Devices.off("addon-status-updated", onUpdate1);
adbAddonsInstalled.resolve();
});
function getVersion(name) {
return name.match(/(\d+\.\d+)/)[0];
}
function onSimulatorInstalled(name) {
let deferred = promise.defer();
Simulators.on("updated", function onUpdate() {
Simulators.findSimulatorAddons().then(addons => {
for (let addon of addons) {
if (name == addon.name.replace(" Simulator", "")) {
Simulators.off("updated", onUpdate);
nextTick().then(deferred.resolve);
return;
}
}
});
});
return deferred.promise;
}
function installSimulatorFromUI(doc, name) {
let li = doc.querySelector('[addon="simulator-' + getVersion(name) + '"]');
li.querySelector(".install-button").click();
return onSimulatorInstalled(name);
}
function uninstallSimulatorFromUI(doc, name) {
let deferred = promise.defer();
Simulators.on("updated", function onUpdate() {
nextTick().then(() => {
let li = doc.querySelector('[status="uninstalled"][addon="simulator-' + getVersion(name) + '"]');
if (li) {
Simulators.off("updated", onUpdate);
deferred.resolve();
} else {
deferred.reject("Can't find item");
}
});
});
let li = doc.querySelector('[status="installed"][addon="simulator-' + getVersion(name) + '"]');
li.querySelector(".uninstall-button").click();
return deferred.promise;
}
function uninstallADBFromUI(doc) {
let deferred = promise.defer();
Devices.on("addon-status-updated", function onUpdate() {
nextTick().then(() => {
let li = doc.querySelector('[status="uninstalled"][addon="adb"]');
if (li) {
Devices.off("addon-status-updated", onUpdate);
deferred.resolve();
} else {
deferred.reject("Can't find item");
}
})
});
let li = doc.querySelector('[status="installed"][addon="adb"]');
li.querySelector(".uninstall-button").click();
return deferred.promise;
}
Task.spawn(function*() {
ok(!Devices.helperAddonInstalled, "Helper not installed");
let win = yield openWebIDE(true);
let docRuntime = getRuntimeDocument(win);
yield adbAddonsInstalled.promise;
ok(Devices.helperAddonInstalled, "Helper has been auto-installed");
yield nextTick();
let addons = yield GetAvailableAddons();
is(addons.simulators.length, 3, "3 simulator addons to install");
let sim10 = addons.simulators.filter(a => a.version == "1.0")[0];
sim10.install();
yield onSimulatorInstalled("Firefox OS 1.0");
win.Cmds.showAddons();
let frame = win.document.querySelector("#deck-panel-addons");
let addonDoc = frame.contentWindow.document;
let lis;
lis = addonDoc.querySelectorAll("li");
is(lis.length, 5, "5 addons listed");
lis = addonDoc.querySelectorAll('li[status="installed"]');
is(lis.length, 3, "3 addons installed");
lis = addonDoc.querySelectorAll('li[status="uninstalled"]');
is(lis.length, 2, "2 addons uninstalled");
info("Uninstalling Simulator 2.0");
yield installSimulatorFromUI(addonDoc, "Firefox OS 2.0");
info("Uninstalling Simulator 3.0");
yield installSimulatorFromUI(addonDoc, "Firefox OS 3.0");
yield nextTick();
let panelNode = docRuntime.querySelector("#runtime-panel");
let items;
items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 1, "Found one runtime button");
items = panelNode.querySelectorAll(".runtime-panel-item-simulator");
is(items.length, 3, "Found 3 simulators button");
yield uninstallSimulatorFromUI(addonDoc, "Firefox OS 1.0");
yield uninstallSimulatorFromUI(addonDoc, "Firefox OS 2.0");
yield uninstallSimulatorFromUI(addonDoc, "Firefox OS 3.0");
items = panelNode.querySelectorAll(".runtime-panel-item-simulator");
is(items.length, 0, "No simulator listed");
let w = addonDoc.querySelector(".warning");
let display = addonDoc.defaultView.getComputedStyle(w).display
is(display, "none", "Warning about missing ADB hidden");
yield uninstallADBFromUI(addonDoc, "adb");
items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 0, "No usb runtime listed");
display = addonDoc.defaultView.getComputedStyle(w).display
is(display, "block", "Warning about missing ADB present");
yield closeWebIDE(win);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,205 @@
<!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>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript;version=1.8">
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://testing-common/httpd.js");
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
const {AppValidator} = require("devtools/client/webide/modules/app-validator");
const Services = require("Services");
const nsFile = Components.Constructor("@mozilla.org/file/local;1",
"nsILocalFile", "initWithPath");
const cr = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry);
const strings = Services.strings.createBundle("chrome://devtools/locale/app-manager.properties");
let httpserver, origin;
window.onload = function() {
SimpleTest.waitForExplicitFinish();
httpserver = new HttpServer();
httpserver.start(-1);
origin = "http://localhost:" + httpserver.identity.primaryPort + "/";
next();
}
function createHosted(path, manifestFile="/manifest.webapp") {
let dirPath = getTestFilePath("validator/" + path);
httpserver.registerDirectory("/", nsFile(dirPath));
return new AppValidator({
type: "hosted",
location: origin + manifestFile
});
}
function createPackaged(path) {
let dirPath = getTestFilePath("validator/" + path);
return new AppValidator({
type: "packaged",
location: dirPath
});
}
function next() {
let test = tests.shift();
if (test) {
try {
test();
} catch(e) {
console.error("exception", String(e), e, e.stack);
}
} else {
httpserver.stop(function() {
SimpleTest.finish();
});
}
}
let tests = [
// Test a 100% valid example
function () {
let validator = createHosted("valid");
validator.validate().then(() => {
is(validator.errors.length, 0, "valid app got no error");
is(validator.warnings.length, 0, "valid app got no warning");
next();
});
},
function () {
let validator = createPackaged("valid");
validator.validate().then(() => {
is(validator.errors.length, 0, "valid packaged app got no error");
is(validator.warnings.length, 0, "valid packaged app got no warning");
next();
});
},
// Test a launch path that returns a 404
function () {
let validator = createHosted("wrong-launch-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non-existant launch path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [origin + "wrong-path.html", 404], 2),
"with the right error message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
function () {
let validator = createPackaged("wrong-launch-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with wrong path got an error");
let file = nsFile(validator.location);
file.append("wrong-path.html");
let url = Services.io.newFileURI(file);
is(validator.errors[0], strings.formatStringFromName("validator.accessFailedLaunchPath", [url.spec], 1),
"with the expected message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
// Test when using a non-absolute path for launch_path
function () {
let validator = createHosted("non-absolute-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non absolute path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.nonAbsoluteLaunchPath", ["non-absolute.html"], 1),
"with expected message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
function () {
let validator = createPackaged("non-absolute-path");
validator.validate().then(() => {
is(validator.errors.length, 1, "app with non absolute path got an error");
is(validator.errors[0], strings.formatStringFromName("validator.nonAbsoluteLaunchPath", ["non-absolute.html"], 1),
"with expected message");
is(validator.warnings.length, 0, "but no warning");
next();
});
},
// Test multiple failures (missing name [error] and icon [warning])
function () {
let validator = createHosted("no-name-or-icon");
validator.validate().then(() => {
checkNoNameOrIcon(validator);
});
},
function () {
let validator = createPackaged("no-name-or-icon");
validator.validate().then(() => {
checkNoNameOrIcon(validator);
});
},
// Test a regular URL instead of a direct link to the manifest
function () {
let validator = createHosted("valid", "/");
validator.validate().then(() => {
is(validator.warnings.length, 0, "manifest found got no warning");
is(validator.errors.length, 0, "manifest found got no error");
next();
});
},
// Test finding a manifest at origin's root
function () {
let validator = createHosted("valid", "/unexisting-dir");
validator.validate().then(() => {
is(validator.warnings.length, 0, "manifest found at origin root got no warning");
is(validator.errors.length, 0, "manifest found at origin root got no error");
next();
});
},
// Test priorization of manifest.webapp at provided location instead of a manifest located at origin's root
function() {
let validator = createHosted("valid", "/alsoValid");
validator.validate().then(() => {
is(validator.manifest.name, "valid at subfolder", "manifest at subfolder was used");
next();
});
}
];
function checkNoNameOrIcon(validator) {
is(validator.errors.length, 1, "app with no name has an error");
is(validator.errors[0],
strings.GetStringFromName("validator.missNameManifestProperty"),
"with expected message");
is(validator.warnings.length, 1, "app with no icon has a warning");
is(validator.warnings[0],
strings.GetStringFromName("validator.missIconsManifestProperty"),
"with expected message");
next();
}
</script>
</body>
</html>

View file

@ -0,0 +1,94 @@
<!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*() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let docRuntime = getRuntimeDocument(win);
let fakeRuntime = {
type: "USB",
connect: function(connection) {
is(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
},
get id() {
return "fakeRuntime";
},
get name() {
return "fakeRuntime";
}
};
win.AppManager.runtimeList.usb.push(fakeRuntime);
win.AppManager.update("runtime-list");
let panelNode = docRuntime.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 1, "Found one runtime button");
let connectionsChanged = waitForConnectionChange("opened", 2);
items[0].click();
ok(win.document.querySelector("window").className, "busy", "UI is busy");
yield win.UI._busyPromise;
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 2, "Connected");
connectionsChanged = waitForConnectionChange("closed", 2);
yield nextTick();
yield closeWebIDE(win);
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
connectionsChanged = waitForConnectionChange("opened", 2);
win = yield openWebIDE();
win.AppManager.runtimeList.usb.push(fakeRuntime);
win.AppManager.update("runtime-list");
yield waitForUpdate(win, "runtime-targets");
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 2, "Automatically reconnected");
yield win.Cmds.disconnectRuntime();
yield closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,110 @@
<!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* () {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let docRuntime = getRuntimeDocument(win);
let docProject = getProjectDocument(win);
let panelNode = docRuntime.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-other");
is(items.length, 2, "Found 2 runtime buttons");
// Connect to local runtime
let connectionsChanged = waitForConnectionChange("opened", 2);
items[1].click();
yield waitForUpdate(win, "runtime-targets");
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 2, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
// Select main process
yield win.Cmds.showProjectPanel();
yield waitForUpdate(win, "runtime-targets");
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
yield waitForUpdate(win, "project");
let lastProject = Services.prefs.getCharPref("devtools.webide.lastSelectedProject");
is(lastProject, "mainProcess:", "Last project is main process");
connectionsChanged = waitForConnectionChange("closed", 2);
yield nextTick();
yield closeWebIDE(win);
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
connectionsChanged = waitForConnectionChange("opened", 2);
// Re-open, should reselect main process after connection
win = yield openWebIDE();
docRuntime = getRuntimeDocument(win);
panelNode = docRuntime.querySelector("#runtime-panel");
items = panelNode.querySelectorAll(".runtime-panel-item-other");
is(items.length, 2, "Found 2 runtime buttons");
// Connect to local runtime
items[1].click();
yield waitForUpdate(win, "runtime-targets");
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 2, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
is(win.AppManager.selectedProject.type, "mainProcess", "Main process reselected");
// Wait for the toolbox to be fully loaded
yield win.UI.toolboxPromise;
// If we happen to pass a project object targeting the same context,
// here, the main process, the `selectedProject` attribute shouldn't be updated
// so that no `project` event would fire.
let oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = {
type: "mainProcess"
};
is(win.AppManager.selectedProject, oldProject, "AppManager.selectedProject shouldn't be updated if we selected the same project");
yield win.Cmds.disconnectRuntime();
yield closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,55 @@
<!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();
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
yield gDevToolsBrowser.isWebIDEInitialized.promise;
ok(true, "WebIDE was initialized");
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");
// test error reporting
let nbox = win.document.querySelector("#notificationbox");
let notification = nbox.getNotificationWithValue("webide:errornotification");
ok(!notification, "No notification yet");
let deferred = promise.defer();
nextTick().then(() => {
deferred.reject("BOOM!");
});
try {
yield win.UI.busyUntil(deferred.promise, "xx");
} catch(e) {/* This *will* fail */}
notification = nbox.getNotificationWithValue("webide:errornotification");
ok(notification, "Error has been reported");
yield closeWebIDE(win);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,128 @@
<!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();
let {TextDecoder, OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
let {ProjectBuilding} = require("devtools/client/webide/modules/build");
Task.spawn(function* () {
let win = yield openWebIDE();
let winProject = getProjectWindow(win);
let AppManager = win.AppManager;
function isProjectMarkedAsValid() {
let details = win.frames[0];
return !details.document.body.classList.contains("error");
}
// # Test first package.json like this: `{webide: {prepackage: "command line string"}}`
let platform = Services.appShell.hiddenDOMWindow.navigator.platform;
let testSuffix = "";
if (platform.indexOf("Win") != -1) {
testSuffix = "_windows";
}
let packagedAppLocation = getTestFilePath("build_app" + testSuffix + "1");
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
let project = win.AppManager.selectedProject;
ok(!project.manifest, "manifest includes name");
is(project.name, "--", "Display name uses manifest name");
let loggedMessages = [];
let logger = function (msg) {
loggedMessages.push(msg);
}
yield ProjectBuilding.build({
project,
logger
});
let packageDir = yield ProjectBuilding.getPackageDir(project);
is(packageDir, packagedAppLocation, "no custom packagedir");
is(loggedMessages[0], "start", "log messages are correct");
ok(loggedMessages[1].indexOf("Running pre-package hook") != -1, "log messages are correct");
is(loggedMessages[2], "Terminated with error code: 0", "log messages are correct");
is(loggedMessages[3], "succeed", "log messages are correct");
// Trigger validation
yield AppManager.validateAndUpdateProject(AppManager.selectedProject);
yield nextTick();
ok("name" in project.manifest, "manifest includes name");
is(project.name, "hello", "Display name uses manifest name");
is(project.manifest.name, project.name, "Display name uses manifest name");
yield OS.File.remove(OS.Path.join(packagedAppLocation, "manifest.webapp"));
// # Now test a full featured package.json
packagedAppLocation = getTestFilePath("build_app" + testSuffix + "2");
onValidated = waitForUpdate(win, "project-validated");
onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
project = win.AppManager.selectedProject;
loggedMessages = [];
yield ProjectBuilding.build({
project,
logger
});
packageDir = yield ProjectBuilding.getPackageDir(project);
is(OS.Path.normalize(packageDir),
OS.Path.join(packagedAppLocation, "stage"), "custom packagedir");
is(loggedMessages[0], "start", "log messages are correct");
ok(loggedMessages[1].indexOf("Running pre-package hook") != -1, "log messages are correct");
is(loggedMessages[2], "Terminated with error code: 0", "log messages are correct");
is(loggedMessages[3], "succeed", "log messages are correct");
// Switch to the package dir in order to verify the generated webapp.manifest
onValidated = waitForUpdate(win, "project-validated");
onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packageDir);
yield onValidated;
yield onDetails;
project = win.AppManager.selectedProject;
ok("name" in project.manifest, "manifest includes name");
is(project.name, "world", "Display name uses manifest name");
is(project.manifest.name, project.name, "Display name uses manifest name");
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,81 @@
<!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* () {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let permIframe = win.document.querySelector("#deck-panel-permissionstable");
let docRuntime = getRuntimeDocument(win);
let winRuntime = getRuntimeWindow(win);
yield connectToLocalRuntime(win);
let perm = docRuntime.querySelector("#runtime-permissions");
ok(!perm.hasAttribute("disabled"), "perm cmd enabled");
let deck = win.document.querySelector("#deck");
winRuntime.runtimeList.showPermissionsTable();
is(deck.selectedPanel, permIframe, "permission iframe selected");
yield nextTick();
yield lazyIframeIsLoaded(permIframe);
yield permIframe.contentWindow.getRawPermissionsTablePromise;
doc = permIframe.contentWindow.document;
trs = doc.querySelectorAll(".line");
found = false;
for (let tr of trs) {
let [name,v1,v2,v3] = tr.querySelectorAll("td");
if (name.textContent == "geolocation") {
found = true;
is(v1.className, "permprompt", "geolocation perm is valid");
is(v2.className, "permprompt", "geolocation perm is valid");
is(v3.className, "permprompt", "geolocation perm is valid");
break;
}
}
ok(found, "Found geolocation line");
doc.querySelector("#close").click();
ok(!deck.selectedPanel, "No panel selected");
DebuggerServer.destroy();
yield closeWebIDE(win);
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,87 @@
<!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>
<script type="application/javascript;version=1.8" src="device_front_shared.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* () {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let prefIframe = win.document.querySelector("#deck-panel-devicepreferences");
let docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
yield connectToLocalRuntime(win);
let prefs = docRuntime.querySelector("#runtime-preferences");
ok(!prefs.hasAttribute("disabled"), "device prefs cmd enabled");
let deck = win.document.querySelector("#deck");
win.Cmds.showDevicePrefs();
is(deck.selectedPanel, prefIframe, "device preferences iframe selected");
yield nextTick();
yield lazyIframeIsLoaded(prefIframe);
yield prefIframe.contentWindow.getAllPrefs;
setDocument(prefIframe);
let fields = doc.querySelectorAll(".editable");
addNewField();
let preference = "accessibility.accesskeycausesactivation";
fieldChange(fields, preference);
addNewFieldWithEnter();
editExistingField();
addNewFieldInteger();
yield editFieldInteger();
yield resetExistingField("accessibility.accesskeycausesactivation");
addNewFieldBoolean();
searchFields(deck, "debugger");
DebuggerServer.destroy();
yield closeWebIDE(win);
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,81 @@
<!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* () {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let detailsIframe = win.document.querySelector("#deck-panel-runtimedetails");
yield connectToLocalRuntime(win);
let details = win.document.querySelector("#cmd_showRuntimeDetails");
ok(!details.hasAttribute("disabled"), "info cmd enabled");
let deck = win.document.querySelector("#deck");
win.Cmds.showRuntimeDetails();
is(deck.selectedPanel, detailsIframe, "info iframe selected");
yield nextTick();
yield lazyIframeIsLoaded(detailsIframe);
yield detailsIframe.contentWindow.getDescriptionPromise;
// device info and permissions content is checked in other tests
// We just test one value to make sure we get something
let doc = detailsIframe.contentWindow.document;
let trs = doc.querySelectorAll("tr");
let found = false;
for (let tr of trs) {
let [name,val] = tr.querySelectorAll("td");
if (name.textContent == "appid") {
found = true;
is(val.textContent, Services.appinfo.ID, "appid has the right value");
break;
}
}
ok(found, "Found appid line");
doc.querySelector("#close").click();
ok(!deck.selectedPanel, "No panel selected");
DebuggerServer.destroy();
yield closeWebIDE(win);
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,87 @@
<!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>
<script type="application/javascript;version=1.8" src="device_front_shared.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*() {
if (SpecialPowers.isMainProcess()) {
Cu.import("resource://gre/modules/SettingsRequestManager.jsm");
}
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let win = yield openWebIDE();
let settingIframe = win.document.querySelector("#deck-panel-devicesettings");
let docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
yield connectToLocalRuntime(win);
let settings = docRuntime.querySelector("#runtime-settings");
ok(!settings.hasAttribute("disabled"), "device settings cmd enabled");
let deck = win.document.querySelector("#deck");
win.Cmds.showSettings();
is(deck.selectedPanel, settingIframe, "device settings iframe selected");
yield nextTick();
yield lazyIframeIsLoaded(settingIframe);
yield settingIframe.contentWindow.getAllSettings;
setDocument(settingIframe);
let fields = doc.querySelectorAll(".editable");
addNewField();
addNewFieldWithEnter();
editExistingField();
addNewFieldInteger();
yield editFieldInteger();
yield resetNewField("new-string-field");
addNewFieldBoolean();
searchFields(deck, "new-boolean-field2");
DebuggerServer.destroy();
yield closeWebIDE(win);
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,77 @@
<!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 docProject = getProjectDocument(win);
let winProject = getProjectWindow(win);
let packagedAppLocation = getTestFilePath("app");
let hostedAppManifest = TEST_BASE + "hosted_app.manifest";
yield win.AppProjects.load();
is(win.AppProjects.projects.length, 0, "IDB is empty");
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
yield winProject.projectList.importHostedApp(hostedAppManifest);
yield waitForUpdate(win, "project-validated");
yield nextTick();
onValidated = waitForUpdate(win, "project-validated");
onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
let project = win.AppManager.selectedProject;
is(project.location, packagedAppLocation, "Correctly reselected existing packaged app.");
yield nextTick();
info("to call importHostedApp(" + hostedAppManifest + ") again");
yield winProject.projectList.importHostedApp(hostedAppManifest);
yield waitForUpdate(win, "project-validated");
project = win.AppManager.selectedProject;
is(project.location, hostedAppManifest, "Correctly reselected existing hosted app.");
yield nextTick();
let panelNode = docProject.querySelector("#project-panel");
let items = panelNode.querySelectorAll(".panel-item");
// 3 controls, + 2 projects
is(items.length, 5, "5 projects in panel");
is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,67 @@
<!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">
function connectToLocal(win, docRuntime) {
let deferred = promise.defer();
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
() => deferred.resolve());
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
return deferred.promise;
}
window.onload = function() {
SimpleTest.waitForExplicitFinish();
Task.spawn(function* () {
let win = yield openWebIDE();
let docProject = getProjectDocument(win);
let docRuntime = getRuntimeDocument(win);
win.AppManager.update("runtime-list");
yield connectToLocal(win, docRuntime);
// Select main process
yield waitForUpdate(win, "runtime-targets");
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
yield waitForUpdate(win, "project");
ok(win.UI.toolboxPromise, "Toolbox promise exists");
yield win.UI.toolboxPromise;
let nbox = win.document.querySelector("#notificationbox");
ok(!nbox.hasAttribute("toolboxfullscreen"), "Toolbox is not fullscreen");
win.Cmds.showRuntimeDetails();
ok(!nbox.hasAttribute("toolboxfullscreen"), "Toolbox is not fullscreen");
yield win.Cmds.disconnectRuntime();
yield closeWebIDE(win);
DebuggerServer.destroy();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,82 @@
<!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 docProject = getProjectDocument(win);
let winProject = getProjectWindow(win);
let packagedAppLocation = getTestFilePath("app");
yield win.AppProjects.load();
is(win.AppProjects.projects.length, 0, "IDB is empty");
info("to call importPackagedApp(" + packagedAppLocation + ")");
ok(!win.UI._busyPromise, "UI is not busy");
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
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 winProject.projectList.importHostedApp(hostedAppManifest);
yield waitForUpdate(win, "project-validated");
project = win.AppManager.selectedProject;
is(project.location, hostedAppManifest, "Location is valid");
is(project.name, "hosted manifest name property", "name field has been updated");
yield nextTick();
hostedAppManifest = TEST_BASE + "/app";
yield winProject.projectList.importHostedApp(hostedAppManifest);
yield waitForUpdate(win, "project-validated");
project = win.AppManager.selectedProject;
ok(project.location.endsWith('manifest.webapp'), "The manifest was found and the project was updated");
let panelNode = docProject.querySelector("#project-panel");
let items = panelNode.querySelectorAll(".panel-item");
// 4 controls, + 2 projects
is(items.length, 6, "6 projects in panel");
is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
}).then(null, e => {
ok(false, "Exception: " + e);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,98 @@
<!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();
let {TextDecoder, OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
Task.spawn(function* () {
let win = yield openWebIDE();
let winProject = getProjectWindow(win);
let AppManager = win.AppManager;
function isProjectMarkedAsValid() {
let details = win.frames[1];
return !details.document.body.classList.contains("error");
}
let packagedAppLocation = getTestFilePath("app");
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
let project = win.AppManager.selectedProject;
ok("name" in project.manifest, "manifest includes name");
is(project.name, project.manifest.name, "Display name uses manifest name");
ok(isProjectMarkedAsValid(), "project is marked as valid");
// Change the name
let originalName = project.manifest.name;
project.manifest.name = "xxx";
// Write to disk
yield AppManager.writeManifest(project);
// Read file
let manifestPath = OS.Path.join(packagedAppLocation, "manifest.webapp");
let Decoder = new TextDecoder();
let data = yield OS.File.read(manifestPath);
data = new TextDecoder().decode(data);
let json = JSON.parse(data);
is(json.name, "xxx", "manifest written on disc");
// Make the manifest invalid on disk
delete json.name;
let Encoder = new TextEncoder();
data = Encoder.encode(JSON.stringify(json));
yield OS.File.writeAtomic(manifestPath, data , {tmpPath: manifestPath + ".tmp"});
// Trigger validation
yield AppManager.validateAndUpdateProject(AppManager.selectedProject);
yield nextTick();
ok(!("name" in project.manifest), "manifest has been updated");
is(project.name, "--", "Placeholder is used for display name");
ok(!isProjectMarkedAsValid(), "project is marked as invalid");
// Make the manifest valid on disk
project.manifest.name = originalName;
yield AppManager.writeManifest(project);
// Trigger validation
yield AppManager.validateAndUpdateProject(AppManager.selectedProject);
yield nextTick();
ok("name" in project.manifest, "manifest includes name");
is(project.name, originalName, "Display name uses original manifest name");
ok(isProjectMarkedAsValid(), "project is marked as valid");
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,46 @@
<!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 winProject = getProjectWindow(win);
let tmpDir = FileUtils.getDir("TmpD", []);
yield winProject.projectList.newApp({
index: 0,
name: "webideTmpApp",
folder: tmpDir
});
let project = win.AppManager.selectedProject;
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);
yield closeWebIDE(win);
yield removeAllProjects();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,203 @@
<!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();
let win;
SimpleTest.registerCleanupFunction(() => {
Task.spawn(function*() {
if (win) {
yield closeWebIDE(win);
}
DebuggerServer.destroy();
yield removeAllProjects();
});
});
Task.spawn(function*() {
function isPlayActive() {
return !win.document.querySelector("#cmd_play").hasAttribute("disabled");
}
function isStopActive() {
return !win.document.querySelector("#cmd_stop").hasAttribute("disabled");
}
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
win = yield openWebIDE();
let docRuntime = getRuntimeDocument(win);
let docProject = getProjectDocument(win);
let winProject = getProjectWindow(win);
let packagedAppLocation = getTestFilePath("app");
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
is(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
},
get name() {
return "fakeRuntime";
}
});
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
let deferred = promise.defer();
return deferred.promise;
},
get name() {
return "infiniteRuntime";
}
});
win.AppManager.runtimeList.usb.push({
connect: function(connection) {
let deferred = promise.defer();
return deferred.promise;
},
prolongedConnection: true,
get name() {
return "prolongedRuntime";
}
});
win.AppManager.update("runtime-list");
let panelNode = docRuntime.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
is(items.length, 3, "Found 3 runtime buttons");
let connectionsChanged = waitForConnectionChange("opened", 2);
items[0].click();
ok(win.document.querySelector("window").className, "busy", "UI is busy");
yield win.UI._busyPromise;
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 2, "Connected");
yield waitForUpdate(win, "runtime-global-actors");
// Play button always disabled now, webapps actor removed
ok(!isPlayActive(), "play button is disabled");
ok(!isStopActive(), "stop button is disabled");
let oldProject = win.AppManager.selectedProject;
win.AppManager.selectedProject = null;
yield nextTick();
ok(!isPlayActive(), "play button is disabled");
ok(!isStopActive(), "stop button is disabled");
win.AppManager._selectedProject = oldProject;
win.UI.updateCommands();
yield nextTick();
ok(!isPlayActive(), "play button is enabled");
ok(!isStopActive(), "stop button is disabled");
connectionsChanged = waitForConnectionChange("closed", 2);
yield win.Cmds.disconnectRuntime();
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");
ok(win.AppManager.selectedProject, "A project is still selected");
ok(!isPlayActive(), "play button is disabled");
ok(!isStopActive(), "stop button is disabled");
connectionsChanged = waitForConnectionChange("opened", 2);
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
yield waitForUpdate(win, "runtime-targets");
yield connectionsChanged;
is(Object.keys(DebuggerServer._connections).length, 2, "Locally connected");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
// Select main process
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
yield waitForUpdate(win, "project");
// Toolbox opens automatically for main process / runtime apps
ok(win.UI.toolboxPromise, "Toolbox promise exists");
yield win.UI.toolboxPromise;
yield win.Cmds.disconnectRuntime();
Services.prefs.setIntPref("devtools.webide.busyTimeout", 100);
// Wait for error message since connection never completes
let errorDeferred = promise.defer();
win.UI.reportError = errorName => {
if (errorName === "error_operationTimeout") {
errorDeferred.resolve();
}
};
// Click the infinite runtime
items[1].click();
ok(win.document.querySelector("window").className, "busy", "UI is busy");
yield errorDeferred.promise;
// Check for unexpected error message since this is prolonged
let noErrorDeferred = promise.defer();
win.UI.reportError = errorName => {
if (errorName === "error_operationTimeout") {
noErrorDeferred.reject();
}
};
// Click the prolonged runtime
items[2].click();
ok(win.document.querySelector("window").className, "busy", "UI is busy");
setTimeout(() => {
noErrorDeferred.resolve();
}, 1000);
yield noErrorDeferred.promise;
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,426 @@
<!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();
const asyncStorage = require("devtools/shared/async-storage");
const EventEmitter = require("devtools/shared/event-emitter");
const { GetAvailableAddons } = require("devtools/client/webide/modules/addons");
const { getDevices } = require("devtools/client/shared/devices");
const { Simulator, Simulators } = require("devtools/client/webide/modules/simulators");
const { AddonSimulatorProcess,
OldAddonSimulatorProcess,
CustomSimulatorProcess } = require("devtools/client/webide/modules/simulator-process");
function addonStatus(addon, status) {
if (addon.status == status) {
return promise.resolve();
}
let deferred = promise.defer();
addon.on("update", function onUpdate() {
if (addon.status == status) {
addon.off("update", onUpdate);
nextTick().then(() => deferred.resolve());
}
});
return deferred.promise;
}
function waitForUpdate(length) {
info(`Wait for update with length ${length}`);
let deferred = promise.defer();
let handler = (_, data) => {
if (data.length != length) {
return;
}
info(`Got update with length ${length}`);
Simulators.off("updated", handler);
deferred.resolve();
};
Simulators.on("updated", handler);
return deferred.promise;
}
Task.spawn(function* () {
let win = yield openWebIDE(false);
yield Simulators._load();
let docRuntime = getRuntimeDocument(win);
let find = win.document.querySelector.bind(docRuntime);
let findAll = win.document.querySelectorAll.bind(docRuntime);
let simulatorList = find("#runtime-panel-simulator");
let simulatorPanel = win.document.querySelector("#deck-panel-simulator");
// Hack SimulatorProcesses to spy on simulation parameters.
let runPromise;
function fakeRun() {
runPromise.resolve({
path: this.b2gBinary.path,
args: this.args
});
// Don't actually try to connect to the fake simulator.
throw new Error("Aborting on purpose before connection.");
}
AddonSimulatorProcess.prototype.run = fakeRun;
OldAddonSimulatorProcess.prototype.run = fakeRun;
CustomSimulatorProcess.prototype.run = fakeRun;
function runSimulator(i) {
runPromise = promise.defer();
findAll(".runtime-panel-item-simulator")[i].click();
return runPromise.promise;
}
// Install fake "Firefox OS 1.0" simulator addon.
let addons = yield GetAvailableAddons();
let sim10 = addons.simulators.filter(a => a.version == "1.0")[0];
sim10.install();
let updated = waitForUpdate(1);
yield addonStatus(sim10, "installed");
yield updated;
// Wait for next tick to ensure UI elements are updated
yield nextTick();
is(findAll(".runtime-panel-item-simulator").length, 1, "One simulator in runtime panel");
// Install fake "Firefox OS 2.0" simulator addon.
let sim20 = addons.simulators.filter(a => a.version == "2.0")[0];
sim20.install();
updated = waitForUpdate(2);
yield addonStatus(sim20, "installed");
yield updated;
// Wait for next tick to ensure UI elements are updated
yield nextTick();
is(findAll(".runtime-panel-item-simulator").length, 2, "Two simulators in runtime panel");
// Dry run a simulator to verify that its parameters look right.
let params = yield runSimulator(0);
ok(params.path.includes(sim10.addonID) && params.path.includes("b2g-bin"), "Simulator binary path looks right");
let pid = params.args.indexOf("-profile");
ok(pid > -1, "Simulator process arguments have --profile");
let profilePath = params.args[pid + 1];
ok(profilePath.includes(sim10.addonID) && profilePath.includes("profile"), "Simulator profile path looks right");
ok(params.args.indexOf("-dbgport") > -1 || params.args.indexOf("-start-debugger-server") > -1, "Simulator process arguments have a debugger port");
ok(params.args.indexOf("-no-remote") > -1, "Simulator process arguments have --no-remote");
// Wait for next tick to ensure UI elements are updated
yield nextTick();
// Configure the fake 1.0 simulator.
simulatorList.querySelectorAll(".configure-button")[0].click();
is(win.document.querySelector("#deck").selectedPanel, simulatorPanel, "Simulator deck panel is selected");
yield lazyIframeIsLoaded(simulatorPanel);
let doc = simulatorPanel.contentWindow.document;
let form = doc.querySelector("#simulator-editor");
let formReady = new Promise((resolve, reject) => {
form.addEventListener("change", () => {
resolve();
});
});
let change = doc.createEvent("HTMLEvents");
change.initEvent("change", true, true);
function set(input, value) {
input.value = value;
input.dispatchEvent(change);
return nextTick();
}
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(simulatorPanel.contentWindow);
yield formReady;
// Test `name`.
is(form.name.value, find(".runtime-panel-item-simulator").textContent, "Original simulator name");
let customName = "CustomFox ";
yield set(form.name, customName + "1.0");
is(find(".runtime-panel-item-simulator").textContent, form.name.value, "Updated simulator name");
// Test `version`.
is(form.version.value, sim10.addonID, "Original simulator version");
ok(!form.version.classList.contains("custom"), "Version selector is not customized");
yield set(form.version, sim20.addonID);
ok(!form.version.classList.contains("custom"), "Version selector is not customized after addon change");
is(form.name.value, customName + "2.0", "Simulator name was updated to new version");
// Pick custom binary, but act like the user aborted the file picker.
MockFilePicker.returnFiles = [];
yield set(form.version, "pick");
is(form.version.value, sim20.addonID, "Version selector reverted to last valid choice after customization abort");
ok(!form.version.classList.contains("custom"), "Version selector is not customized after customization abort");
// Pick custom binary, and actually follow through. (success, verify value = "custom" and textContent = custom path)
MockFilePicker.useAnyFile();
yield set(form.version, "pick");
let fakeBinary = MockFilePicker.returnFiles[0];
ok(form.version.value == "custom", "Version selector was set to a new custom binary");
ok(form.version.classList.contains("custom"), "Version selector is now customized");
is(form.version.selectedOptions[0].textContent, fakeBinary.path, "Custom option textContent is correct");
yield set(form.version, sim10.addonID);
ok(form.version.classList.contains("custom"), "Version selector remains customized after change back to addon");
is(form.name.value, customName + "1.0", "Simulator name was updated to new version");
yield set(form.version, "custom");
ok(form.version.value == "custom", "Version selector is back to custom");
// Test `profile`.
is(form.profile.value, "default", "Default simulator profile");
ok(!form.profile.classList.contains("custom"), "Profile selector is not customized");
MockFilePicker.returnFiles = [];
yield set(form.profile, "pick");
is(form.profile.value, "default", "Profile selector reverted to last valid choice after customization abort");
ok(!form.profile.classList.contains("custom"), "Profile selector is not customized after customization abort");
let fakeProfile = FileUtils.getDir("TmpD", []);
MockFilePicker.returnFiles = [ fakeProfile ];
yield set(form.profile, "pick");
ok(form.profile.value == "custom", "Profile selector was set to a new custom directory");
ok(form.profile.classList.contains("custom"), "Profile selector is now customized");
is(form.profile.selectedOptions[0].textContent, fakeProfile.path, "Custom option textContent is correct");
yield set(form.profile, "default");
is(form.profile.value, "default", "Profile selector back to default");
ok(form.profile.classList.contains("custom"), "Profile selector remains customized after change back to default");
yield set(form.profile, "custom");
is(form.profile.value, "custom", "Profile selector back to custom");
params = yield runSimulator(0);
is(params.path, fakeBinary.path, "Simulator process uses custom binary path");
pid = params.args.indexOf("-profile");
is(params.args[pid + 1], fakeProfile.path, "Simulator process uses custom profile directory");
yield set(form.version, sim10.addonID);
is(form.name.value, customName + "1.0", "Simulator restored to 1.0");
params = yield runSimulator(0);
pid = params.args.indexOf("-profile");
is(params.args[pid + 1], fakeProfile.path, "Simulator process still uses custom profile directory");
yield set(form.version, "custom");
// Test `device`.
let defaults = Simulator.prototype._defaults;
for (let param in defaults.phone) {
is(form[param].value, String(defaults.phone[param]), "Default phone value for device " + param);
}
let width = 5000, height = 4000;
yield set(form.width, width);
yield set(form.height, height);
is(form.device.value, "custom", "Device selector is custom");
params = yield runSimulator(0);
let sid = params.args.indexOf("-screen");
ok(sid > -1, "Simulator process arguments have --screen");
ok(params.args[sid + 1].includes(width + "x" + height), "Simulator screen resolution looks right");
yield set(form.version, sim10.addonID);
// Configure the fake 2.0 simulator.
simulatorList.querySelectorAll(".configure-button")[1].click();
// Wait for next tick to ensure UI elements are updated
yield nextTick();
// Test `name`.
is(form.name.value, findAll(".runtime-panel-item-simulator")[1].textContent, "Original simulator name");
yield set(form.name, customName + "2.0");
is(findAll(".runtime-panel-item-simulator")[1].textContent, form.name.value, "Updated simulator name");
yield set(form.version, sim10.addonID);
ok(form.name.value !== customName + "1.0", "Conflicting simulator name was deduplicated");
is(form.name.value, findAll(".runtime-panel-item-simulator")[1].textContent, "Deduplicated simulator name stayed consistent");
yield set(form.version, sim20.addonID);
is(form.name.value, customName + "2.0", "Name deduplication was undone when possible");
// Test `device`.
for (let param in defaults.phone) {
is(form[param].value, String(defaults.phone[param]), "Default phone value for device " + param);
}
let devices = yield getDevices();
devices = devices[devices.TYPES[0]];
let device = devices[devices.length - 1];
yield set(form.device, device.name);
is(form.device.value, device.name, "Device selector was changed");
is(form.width.value, String(device.width), "New device width is correct");
is(form.height.value, String(device.height), "New device height is correct");
params = yield runSimulator(1);
sid = params.args.indexOf("-screen");
ok(params.args[sid + 1].includes(device.width + "x" + device.height), "Simulator screen resolution looks right");
// Test Simulator Menu.
is(doc.querySelector("#tv_simulator_menu").style.visibility, "hidden", "OpenTVDummyDirectory Button is not hidden");
// Restore default simulator options.
doc.querySelector("#reset").click();
// Wait for next tick to ensure UI elements are updated
yield nextTick();
for (let param in defaults.phone) {
is(form[param].value, String(defaults.phone[param]), "Default phone value for device " + param);
}
// Install and configure the fake "Firefox OS 3.0 TV" simulator addon.
let sim30tv = addons.simulators.filter(a => a.version == "3.0_tv")[0];
sim30tv.install();
updated = waitForUpdate(3);
yield addonStatus(sim30tv, "installed");
yield updated;
// Wait for next tick to ensure UI elements are updated
yield nextTick();
is(findAll(".runtime-panel-item-simulator").length, 3, "Three simulators in runtime panel");
simulatorList.querySelectorAll(".configure-button")[2].click();
// Wait for next tick to ensure UI elements are updated
yield nextTick();
for (let param in defaults.television) {
is(form[param].value, String(defaults.television[param]), "Default TV value for device " + param);
}
// Test Simulator Menu
is(doc.querySelector("#tv_simulator_menu").style.visibility, "visible", "OpenTVDummyDirectory Button is not visible");
// Force reload the list of simulators.
Simulators._loadingPromise = null;
Simulators._simulators = [];
yield Simulators._load();
// Wait for next tick to ensure UI elements are updated
yield nextTick();
is(findAll(".runtime-panel-item-simulator").length, 3, "Three simulators saved and reloaded " + Simulators._simulators.map(s => s.name).join(','));
// Uninstall the 3.0 TV and 2.0 addons, and watch their Simulator objects disappear.
sim30tv.uninstall();
yield addonStatus(sim30tv, "uninstalled");
is(findAll(".runtime-panel-item-simulator").length, 2, "Two simulators left in runtime panel");
sim20.uninstall();
yield addonStatus(sim20, "uninstalled");
is(findAll(".runtime-panel-item-simulator").length, 1, "One simulator left in runtime panel");
// Remove 1.0 simulator.
simulatorList.querySelectorAll(".configure-button")[0].click();
// Wait for next tick to ensure UI elements are updated
yield nextTick();
doc.querySelector("#remove").click();
// Wait for next tick to ensure UI elements are updated
yield nextTick();
is(findAll(".runtime-panel-item-simulator").length, 0, "Last simulator was removed");
yield asyncStorage.removeItem("simulators");
sim10.uninstall();
MockFilePicker.cleanup();
doc.querySelector("#close").click();
ok(!win.document.querySelector("#deck").selectedPanel, "No panel selected");
yield closeWebIDE(win);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,325 @@
<!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">
const Telemetry = require("devtools/client/shared/telemetry");
const { _DeprecatedUSBRuntime, _WiFiRuntime, _SimulatorRuntime,
_gRemoteRuntime, _gLocalRuntime, RuntimeTypes }
= require("devtools/client/webide/modules/runtimes");
// Because we need to gather stats for the period of time that a tool has
// been opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
function patchTelemetry() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
}
Telemetry.prototype._oldlogKeyed = Telemetry.prototype.logKeyed;
Telemetry.prototype.logKeyed = function(histogramId, key, value) {
// This simple reduction is enough to test WebIDE's usage
this.log(`${histogramId}|${key}`, value);
}
}
function resetTelemetry() {
Telemetry.prototype.log = Telemetry.prototype._oldlog;
Telemetry.prototype.logKeyed = Telemetry.prototype._oldlogKeyed;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlogKeyed;
delete Telemetry.prototype.telemetryInfo;
}
function cycleWebIDE() {
return Task.spawn(function*() {
let win = yield openWebIDE();
// Wait a bit, so we're open for a non-zero time
yield waitForTime(TOOL_DELAY);
yield closeWebIDE(win);
});
}
function addFakeRuntimes(win) {
// We use the real runtimes here (and switch out some functionality)
// so we can ensure that logging happens as it would in real use.
let usb = new _DeprecatedUSBRuntime("fakeUSB");
// Use local pipe instead
usb.connect = function(connection) {
ok(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
};
win.AppManager.runtimeList.usb.push(usb);
let wifi = new _WiFiRuntime("fakeWiFi");
// Use local pipe instead
wifi.connect = function(connection) {
ok(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
};
win.AppManager.runtimeList.wifi.push(wifi);
let sim = new _SimulatorRuntime({ id: "fakeSimulator" });
// Use local pipe instead
sim.connect = function(connection) {
ok(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
};
Object.defineProperty(sim, "name", {
get() {
return this.version;
}
});
win.AppManager.runtimeList.simulator.push(sim);
let remote = _gRemoteRuntime;
// Use local pipe instead
remote.connect = function(connection) {
ok(connection, win.AppManager.connection, "connection is valid");
connection.host = null; // force connectPipe
connection.connect();
return promise.resolve();
};
let local = _gLocalRuntime;
let other = Object.create(_gLocalRuntime);
other.type = RuntimeTypes.OTHER;
win.AppManager.runtimeList.other = [remote, local, other];
win.AppManager.update("runtime-list");
}
function addTestApp(win) {
return Task.spawn(function*() {
let packagedAppLocation = getTestFilePath("../app");
let winProject = getProjectWindow(win);
let onValidated = waitForUpdate(win, "project-validated");
let onDetails = waitForUpdate(win, "details");
yield winProject.projectList.importPackagedApp(packagedAppLocation);
yield onValidated;
yield onDetails;
});
}
function startConnection(win, docRuntime, type, index) {
let panelNode = docRuntime.querySelector("#runtime-panel");
let items = panelNode.querySelectorAll(".runtime-panel-item-" + type);
if (index === undefined) {
is(items.length, 1, "Found one runtime button");
}
let deferred = promise.defer();
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
() => deferred.resolve());
items[index || 0].click();
return deferred.promise;
}
function waitUntilConnected(win) {
return Task.spawn(function*() {
ok(win.document.querySelector("window").className, "busy", "UI is busy");
yield win.UI._busyPromise;
is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
// Logging runtime info needs to use the device actor
yield waitForUpdate(win, "runtime-global-actors");
// Ensure detailed telemetry is recorded
yield waitForUpdate(win, "runtime-telemetry");
});
}
function connectToRuntime(win, docRuntime, type, index) {
return Task.spawn(function*() {
startConnection(win, docRuntime, type, index);
yield waitUntilConnected(win);
});
}
function checkResults() {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId === "DEVTOOLS_WEBIDE_IMPORT_PROJECT_BOOLEAN") {
ok(value.length === 1 && !!value[0],
histId + " has 1 successful entry");
} else if (histId ===
"DEVTOOLS_WEBIDE_PROJECT_EDITOR_OPENED_COUNT") {
ok(value.length === 1 && !!value[0],
histId + " has 1 successful entry");
} else if (histId === "DEVTOOLS_WEBIDE_OPENED_COUNT") {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return !!element;
});
ok(okay, "All " + histId + " entries are true");
} else if (histId.endsWith("WEBIDE_TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
} else if (histId.endsWith("EDITOR_TIME_ACTIVE_SECONDS")) {
ok(value.length === 1 && value[0] > 0,
histId + " has 1 entry with time > 0");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTION_RESULT") {
ok(value.length === 6, histId + " has 6 connection results");
let okay = value.every(function(element) {
return !!element;
});
ok(okay, "All " + histId + " connections succeeded");
} else if (histId.endsWith("CONNECTION_RESULT")) {
ok(value.length === 1 && !!value[0],
histId + " has 1 successful connection");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTION_TIME_SECONDS") {
ok(value.length === 6, histId + " has 6 connection results");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " connections have time > 0");
} else if (histId.endsWith("USED")) {
ok(value.length === 6, histId + " has 6 connection actions");
let okay = value.every(function(element) {
return !element;
});
ok(okay, "All " + histId + " actions were skipped");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|USB") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|WIFI") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|SIMULATOR") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|REMOTE") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|LOCAL") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|OTHER") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|fakeUSB") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|fakeWiFi") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|fakeSimulator") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|unknown") {
is(value.length, 1, histId + " has 1 connection results");
} else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|local") {
is(value.length, 2, histId + " has 2 connection results");
} else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_PROCESSOR")) {
let processor = histId.split("|")[1];
is(processor, Services.appinfo.XPCOMABI.split("-")[0], "Found runtime processor");
is(value.length, 6, histId + " has 6 connection results");
} else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_OS")) {
let os = histId.split("|")[1];
is(os, Services.appinfo.OS, "Found runtime OS");
is(value.length, 6, histId + " has 6 connection results");
} else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_PLATFORM_VERSION")) {
let platformversion = histId.split("|")[1];
is(platformversion, Services.appinfo.platformVersion, "Found runtime platform version");
is(value.length, 6, histId + " has 6 connection results");
} else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_APP_TYPE")) {
let apptype = histId.split("|")[1];
is(apptype, "firefox", "Found runtime app type");
is(value.length, 6, histId + " has 6 connection results");
} else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_VERSION")) {
let version = histId.split("|")[1];
is(version, Services.appinfo.version, "Found runtime version");
is(value.length, 6, histId + " has 6 connection results");
} else {
ok(false, "Unexpected " + histId + " was logged");
}
}
}
window.onload = function() {
SimpleTest.testInChaosMode();
SimpleTest.waitForExplicitFinish();
let win;
SimpleTest.registerCleanupFunction(() => {
return Task.spawn(function*() {
if (win) {
yield closeWebIDE(win);
}
DebuggerServer.destroy();
yield removeAllProjects();
resetTelemetry();
});
});
Task.spawn(function*() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
patchTelemetry();
// Cycle once, so we can test for multiple opens
yield cycleWebIDE();
win = yield openWebIDE();
let docRuntime = getRuntimeDocument(win);
// Wait a bit, so we're open for a non-zero time
yield waitForTime(TOOL_DELAY);
addFakeRuntimes(win);
yield addTestApp(win);
// Each one should log a connection result and non-zero connection
// time
yield connectToRuntime(win, docRuntime, "usb");
yield connectToRuntime(win, docRuntime, "wifi");
yield connectToRuntime(win, docRuntime, "simulator");
yield connectToRuntime(win, docRuntime, "other", 0 /* remote */);
yield connectToRuntime(win, docRuntime, "other", 1 /* local */);
yield connectToRuntime(win, docRuntime, "other", 2 /* other */);
yield closeWebIDE(win);
win = null;
checkResults();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,93 @@
<!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();
let win;
SimpleTest.registerCleanupFunction(() => {
Task.spawn(function*() {
if (win) {
yield closeWebIDE(win);
}
DebuggerServer.destroy();
yield removeAllProjects();
});
});
Task.spawn(function*() {
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
win = yield openWebIDE();
let docRuntime = getRuntimeDocument(win);
let docProject = getProjectDocument(win);
win.AppManager.update("runtime-list");
let deferred = promise.defer();
win.AppManager.connection.once(
win.Connection.Events.CONNECTED,
() => deferred.resolve());
docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();
ok(win.document.querySelector("window").className, "busy", "UI is busy");
yield win.UI._busyPromise;
is(Object.keys(DebuggerServer._connections).length, 1, "Connected");
yield waitForUpdate(win, "runtime-global-actors");
ok(win.AppManager.isMainProcessDebuggable(), "Main process available");
// Select main process
SimpleTest.executeSoon(() => {
docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
});
yield waitForUpdate(win, "project");
// Toolbox opens automatically for main process / runtime apps
ok(win.UI.toolboxPromise, "Toolbox promise exists");
let toolbox = yield win.UI.toolboxPromise;
yield toolbox.destroy();
ok(!win.UI.toolboxPromise, "Toolbox promise should be unset once toolbox.destroy()'s promise resolves");
// Reopen the toolbox right after to check races and also
// opening a toolbox more than just once against the same target
yield win.Cmds.toggleToolbox();
ok(win.UI.toolboxPromise, "Toolbox promise exists");
yield win.UI.destroyToolbox();
ok(!win.UI.toolboxPromise, "Toolbox promise is also nullified the second times");
yield win.Cmds.disconnectRuntime();
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,77 @@
<!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 viewer = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.contentViewer;
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
win.Cmds.zoomOut();
let roundZoom = Math.round(10 * viewer.fullZoom) / 10;
is(roundZoom, 0.6, "Reach min zoom");
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
win.Cmds.zoomIn();
roundZoom = Math.round(10 * viewer.fullZoom) / 10;
is(roundZoom, 1.4, "Reach max zoom");
yield closeWebIDE(win);
win = yield openWebIDE();
viewer = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.contentViewer;
roundZoom = Math.round(10 * viewer.fullZoom) / 10;
is(roundZoom, 1.4, "Zoom restored");
win.Cmds.resetZoom();
is(viewer.fullZoom, 1, "Zoom reset");
yield closeWebIDE(win);
SimpleTest.finish();
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,3 @@
{
"launch_path": "/home.html"
}

View file

@ -0,0 +1,7 @@
{
"name": "non-absolute path",
"icons": {
"128": "/icon.png"
},
"launch_path": "non-absolute.html"
}

View file

@ -0,0 +1,7 @@
{
"name": "valid at subfolder",
"launch_path": "/home.html",
"icons": {
"128": "/icon.png"
}
}

View file

@ -0,0 +1,7 @@
{
"name": "valid",
"launch_path": "/home.html",
"icons": {
"128": "/icon.png"
}
}

View file

@ -0,0 +1,7 @@
{
"name": "valid",
"launch_path": "/wrong-path.html",
"icons": {
"128": "/icon.png"
}
}