diff options
Diffstat (limited to 'devtools/client/webide/test')
75 files changed, 3363 insertions, 0 deletions
diff --git a/devtools/client/webide/test/.eslintrc.js b/devtools/client/webide/test/.eslintrc.js new file mode 100644 index 000000000..8d15a76d9 --- /dev/null +++ b/devtools/client/webide/test/.eslintrc.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = { + // Extend from the shared list of defined globals for mochitests. + "extends": "../../../.eslintrc.mochitests.js" +}; diff --git a/devtools/client/webide/test/addons/adbhelper-linux.xpi b/devtools/client/webide/test/addons/adbhelper-linux.xpi Binary files differnew file mode 100644 index 000000000..b56cc03e3 --- /dev/null +++ b/devtools/client/webide/test/addons/adbhelper-linux.xpi diff --git a/devtools/client/webide/test/addons/adbhelper-linux64.xpi b/devtools/client/webide/test/addons/adbhelper-linux64.xpi Binary files differnew file mode 100644 index 000000000..b56cc03e3 --- /dev/null +++ b/devtools/client/webide/test/addons/adbhelper-linux64.xpi diff --git a/devtools/client/webide/test/addons/adbhelper-mac64.xpi b/devtools/client/webide/test/addons/adbhelper-mac64.xpi Binary files differnew file mode 100644 index 000000000..b56cc03e3 --- /dev/null +++ b/devtools/client/webide/test/addons/adbhelper-mac64.xpi diff --git a/devtools/client/webide/test/addons/adbhelper-win32.xpi b/devtools/client/webide/test/addons/adbhelper-win32.xpi Binary files differnew file mode 100644 index 000000000..b56cc03e3 --- /dev/null +++ b/devtools/client/webide/test/addons/adbhelper-win32.xpi diff --git a/devtools/client/webide/test/addons/fxdt-adapters-linux32.xpi b/devtools/client/webide/test/addons/fxdt-adapters-linux32.xpi Binary files differnew file mode 100644 index 000000000..5a512ae3d --- /dev/null +++ b/devtools/client/webide/test/addons/fxdt-adapters-linux32.xpi diff --git a/devtools/client/webide/test/addons/fxdt-adapters-linux64.xpi b/devtools/client/webide/test/addons/fxdt-adapters-linux64.xpi Binary files differnew file mode 100644 index 000000000..5a512ae3d --- /dev/null +++ b/devtools/client/webide/test/addons/fxdt-adapters-linux64.xpi diff --git a/devtools/client/webide/test/addons/fxdt-adapters-mac64.xpi b/devtools/client/webide/test/addons/fxdt-adapters-mac64.xpi Binary files differnew file mode 100644 index 000000000..5a512ae3d --- /dev/null +++ b/devtools/client/webide/test/addons/fxdt-adapters-mac64.xpi diff --git a/devtools/client/webide/test/addons/fxdt-adapters-win32.xpi b/devtools/client/webide/test/addons/fxdt-adapters-win32.xpi Binary files differnew file mode 100644 index 000000000..5a512ae3d --- /dev/null +++ b/devtools/client/webide/test/addons/fxdt-adapters-win32.xpi diff --git a/devtools/client/webide/test/addons/fxos_1_0_simulator-linux.xpi b/devtools/client/webide/test/addons/fxos_1_0_simulator-linux.xpi Binary files differnew file mode 100644 index 000000000..238c97562 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_1_0_simulator-linux.xpi diff --git a/devtools/client/webide/test/addons/fxos_1_0_simulator-linux64.xpi b/devtools/client/webide/test/addons/fxos_1_0_simulator-linux64.xpi Binary files differnew file mode 100644 index 000000000..2f86c4d4d --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_1_0_simulator-linux64.xpi diff --git a/devtools/client/webide/test/addons/fxos_1_0_simulator-mac64.xpi b/devtools/client/webide/test/addons/fxos_1_0_simulator-mac64.xpi Binary files differnew file mode 100644 index 000000000..6da2fcbad --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_1_0_simulator-mac64.xpi diff --git a/devtools/client/webide/test/addons/fxos_1_0_simulator-win32.xpi b/devtools/client/webide/test/addons/fxos_1_0_simulator-win32.xpi Binary files differnew file mode 100644 index 000000000..546deacaf --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_1_0_simulator-win32.xpi diff --git a/devtools/client/webide/test/addons/fxos_2_0_simulator-linux.xpi b/devtools/client/webide/test/addons/fxos_2_0_simulator-linux.xpi Binary files differnew file mode 100644 index 000000000..e2335e3a0 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_2_0_simulator-linux.xpi diff --git a/devtools/client/webide/test/addons/fxos_2_0_simulator-linux64.xpi b/devtools/client/webide/test/addons/fxos_2_0_simulator-linux64.xpi Binary files differnew file mode 100644 index 000000000..75fe209ea --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_2_0_simulator-linux64.xpi diff --git a/devtools/client/webide/test/addons/fxos_2_0_simulator-mac64.xpi b/devtools/client/webide/test/addons/fxos_2_0_simulator-mac64.xpi Binary files differnew file mode 100644 index 000000000..58749f724 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_2_0_simulator-mac64.xpi diff --git a/devtools/client/webide/test/addons/fxos_2_0_simulator-win32.xpi b/devtools/client/webide/test/addons/fxos_2_0_simulator-win32.xpi Binary files differnew file mode 100644 index 000000000..60cffd46e --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_2_0_simulator-win32.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_simulator-linux.xpi b/devtools/client/webide/test/addons/fxos_3_0_simulator-linux.xpi Binary files differnew file mode 100644 index 000000000..c54cae3aa --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_simulator-linux.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_simulator-linux64.xpi b/devtools/client/webide/test/addons/fxos_3_0_simulator-linux64.xpi Binary files differnew file mode 100644 index 000000000..9a650a888 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_simulator-linux64.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_simulator-mac64.xpi b/devtools/client/webide/test/addons/fxos_3_0_simulator-mac64.xpi Binary files differnew file mode 100644 index 000000000..d13dd78de --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_simulator-mac64.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_simulator-win32.xpi b/devtools/client/webide/test/addons/fxos_3_0_simulator-win32.xpi Binary files differnew file mode 100644 index 000000000..92d5cc394 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_simulator-win32.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-linux.xpi b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-linux.xpi Binary files differnew file mode 100644 index 000000000..7a2a432ff --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-linux.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-linux64.xpi b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-linux64.xpi Binary files differnew file mode 100644 index 000000000..d38932195 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-linux64.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-mac64.xpi b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-mac64.xpi Binary files differnew file mode 100644 index 000000000..48e271d54 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-mac64.xpi diff --git a/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-win32.xpi b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-win32.xpi Binary files differnew file mode 100644 index 000000000..4c8bb2f10 --- /dev/null +++ b/devtools/client/webide/test/addons/fxos_3_0_tv_simulator-win32.xpi diff --git a/devtools/client/webide/test/addons/simulators.json b/devtools/client/webide/test/addons/simulators.json new file mode 100644 index 000000000..31d71b4da --- /dev/null +++ b/devtools/client/webide/test/addons/simulators.json @@ -0,0 +1,4 @@ +{ + "stable": ["1.0", "2.0"], + "unstable": ["3.0", "3.0_tv"] +} diff --git a/devtools/client/webide/test/app.zip b/devtools/client/webide/test/app.zip Binary files differnew file mode 100644 index 000000000..8a706a3c9 --- /dev/null +++ b/devtools/client/webide/test/app.zip diff --git a/devtools/client/webide/test/app/index.html b/devtools/client/webide/test/app/index.html new file mode 100644 index 000000000..3ef4a25e2 --- /dev/null +++ b/devtools/client/webide/test/app/index.html @@ -0,0 +1,6 @@ +<!doctype html> +<html> +<head><title></title></head> +<body> +</body> +</html> diff --git a/devtools/client/webide/test/app/manifest.webapp b/devtools/client/webide/test/app/manifest.webapp new file mode 100644 index 000000000..4a198b1ca --- /dev/null +++ b/devtools/client/webide/test/app/manifest.webapp @@ -0,0 +1,5 @@ +{ + "name": "A name (in app directory)", + "description": "desc", + "launch_path": "/index.html" +} diff --git a/devtools/client/webide/test/browser.ini b/devtools/client/webide/test/browser.ini new file mode 100644 index 000000000..7d6e2de72 --- /dev/null +++ b/devtools/client/webide/test/browser.ini @@ -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] diff --git a/devtools/client/webide/test/browser_tabs.js b/devtools/client/webide/test/browser_tabs.js new file mode 100644 index 000000000..541c6b363 --- /dev/null +++ b/devtools/client/webide/test/browser_tabs.js @@ -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; + }); +} diff --git a/devtools/client/webide/test/browser_widget.js b/devtools/client/webide/test/browser_widget.js new file mode 100644 index 000000000..7cfb2782b --- /dev/null +++ b/devtools/client/webide/test/browser_widget.js @@ -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); +} diff --git a/devtools/client/webide/test/build_app1/package.json b/devtools/client/webide/test/build_app1/package.json new file mode 100644 index 000000000..c6ae833e1 --- /dev/null +++ b/devtools/client/webide/test/build_app1/package.json @@ -0,0 +1,5 @@ +{ + "webide": { + "prepackage": "echo \"{\\\"name\\\":\\\"hello\\\"}\" > manifest.webapp" + } +} diff --git a/devtools/client/webide/test/build_app2/manifest.webapp b/devtools/client/webide/test/build_app2/manifest.webapp new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/devtools/client/webide/test/build_app2/manifest.webapp @@ -0,0 +1 @@ +{} diff --git a/devtools/client/webide/test/build_app2/package.json b/devtools/client/webide/test/build_app2/package.json new file mode 100644 index 000000000..5b7101620 --- /dev/null +++ b/devtools/client/webide/test/build_app2/package.json @@ -0,0 +1,10 @@ +{ + "webide": { + "prepackage": { + "command": "echo \"{\\\"name\\\":\\\"$NAME\\\"}\" > manifest.webapp", + "cwd": "./stage", + "env": ["NAME=world"] + }, + "packageDir": "./stage" + } +} diff --git a/devtools/client/webide/test/build_app2/stage/empty-directory b/devtools/client/webide/test/build_app2/stage/empty-directory new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/webide/test/build_app2/stage/empty-directory diff --git a/devtools/client/webide/test/build_app_windows1/package.json b/devtools/client/webide/test/build_app_windows1/package.json new file mode 100644 index 000000000..036d2d767 --- /dev/null +++ b/devtools/client/webide/test/build_app_windows1/package.json @@ -0,0 +1,5 @@ +{ + "webide": { + "prepackage": "echo {\"name\":\"hello\"} > manifest.webapp" + } +} diff --git a/devtools/client/webide/test/build_app_windows2/manifest.webapp b/devtools/client/webide/test/build_app_windows2/manifest.webapp new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/devtools/client/webide/test/build_app_windows2/manifest.webapp @@ -0,0 +1 @@ +{} diff --git a/devtools/client/webide/test/build_app_windows2/package.json b/devtools/client/webide/test/build_app_windows2/package.json new file mode 100644 index 000000000..83caf82ab --- /dev/null +++ b/devtools/client/webide/test/build_app_windows2/package.json @@ -0,0 +1,10 @@ +{ + "webide": { + "prepackage": { + "command": "echo {\"name\":\"%NAME%\"} > manifest.webapp", + "cwd": "./stage", + "env": ["NAME=world"] + }, + "packageDir": "./stage" + } +} diff --git a/devtools/client/webide/test/build_app_windows2/stage/empty-directory b/devtools/client/webide/test/build_app_windows2/stage/empty-directory new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/webide/test/build_app_windows2/stage/empty-directory diff --git a/devtools/client/webide/test/chrome.ini b/devtools/client/webide/test/chrome.ini new file mode 100644 index 000000000..b492ccd9b --- /dev/null +++ b/devtools/client/webide/test/chrome.ini @@ -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] diff --git a/devtools/client/webide/test/device_front_shared.js b/devtools/client/webide/test/device_front_shared.js new file mode 100644 index 000000000..0ddb5df21 --- /dev/null +++ b/devtools/client/webide/test/device_front_shared.js @@ -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"); +} diff --git a/devtools/client/webide/test/doc_tabs.html b/devtools/client/webide/test/doc_tabs.html new file mode 100644 index 000000000..4901289fc --- /dev/null +++ b/devtools/client/webide/test/doc_tabs.html @@ -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> diff --git a/devtools/client/webide/test/head.js b/devtools/client/webide/test/head.js new file mode 100644 index 000000000..c0171c730 --- /dev/null +++ b/devtools/client/webide/test/head.js @@ -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); + }); +} diff --git a/devtools/client/webide/test/hosted_app.manifest b/devtools/client/webide/test/hosted_app.manifest new file mode 100644 index 000000000..ab5069978 --- /dev/null +++ b/devtools/client/webide/test/hosted_app.manifest @@ -0,0 +1,3 @@ +{ + "name": "hosted manifest name property" +} diff --git a/devtools/client/webide/test/templates.json b/devtools/client/webide/test/templates.json new file mode 100644 index 000000000..e6ffa3efe --- /dev/null +++ b/devtools/client/webide/test/templates.json @@ -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" + } +] diff --git a/devtools/client/webide/test/test_addons.html b/devtools/client/webide/test/test_addons.html new file mode 100644 index 000000000..5a1bc7504 --- /dev/null +++ b/devtools/client/webide/test/test_addons.html @@ -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> diff --git a/devtools/client/webide/test/test_app_validator.html b/devtools/client/webide/test/test_app_validator.html new file mode 100644 index 000000000..60ed29aac --- /dev/null +++ b/devtools/client/webide/test/test_app_validator.html @@ -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> diff --git a/devtools/client/webide/test/test_autoconnect_runtime.html b/devtools/client/webide/test/test_autoconnect_runtime.html new file mode 100644 index 000000000..3de00473a --- /dev/null +++ b/devtools/client/webide/test/test_autoconnect_runtime.html @@ -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> diff --git a/devtools/client/webide/test/test_autoselect_project.html b/devtools/client/webide/test/test_autoselect_project.html new file mode 100644 index 000000000..cd5793559 --- /dev/null +++ b/devtools/client/webide/test/test_autoselect_project.html @@ -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> diff --git a/devtools/client/webide/test/test_basic.html b/devtools/client/webide/test/test_basic.html new file mode 100644 index 000000000..e619a0f06 --- /dev/null +++ b/devtools/client/webide/test/test_basic.html @@ -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> diff --git a/devtools/client/webide/test/test_build.html b/devtools/client/webide/test/test_build.html new file mode 100644 index 000000000..ffb01998c --- /dev/null +++ b/devtools/client/webide/test/test_build.html @@ -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> diff --git a/devtools/client/webide/test/test_device_permissions.html b/devtools/client/webide/test/test_device_permissions.html new file mode 100644 index 000000000..eadd9f595 --- /dev/null +++ b/devtools/client/webide/test/test_device_permissions.html @@ -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> diff --git a/devtools/client/webide/test/test_device_preferences.html b/devtools/client/webide/test/test_device_preferences.html new file mode 100644 index 000000000..c79db7f79 --- /dev/null +++ b/devtools/client/webide/test/test_device_preferences.html @@ -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> diff --git a/devtools/client/webide/test/test_device_runtime.html b/devtools/client/webide/test/test_device_runtime.html new file mode 100644 index 000000000..0ac42b472 --- /dev/null +++ b/devtools/client/webide/test/test_device_runtime.html @@ -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> diff --git a/devtools/client/webide/test/test_device_settings.html b/devtools/client/webide/test/test_device_settings.html new file mode 100644 index 000000000..ec8e7943b --- /dev/null +++ b/devtools/client/webide/test/test_device_settings.html @@ -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> diff --git a/devtools/client/webide/test/test_duplicate_import.html b/devtools/client/webide/test/test_duplicate_import.html new file mode 100644 index 000000000..ef01e23e4 --- /dev/null +++ b/devtools/client/webide/test/test_duplicate_import.html @@ -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> + diff --git a/devtools/client/webide/test/test_fullscreenToolbox.html b/devtools/client/webide/test/test_fullscreenToolbox.html new file mode 100644 index 000000000..6ae0c4446 --- /dev/null +++ b/devtools/client/webide/test/test_fullscreenToolbox.html @@ -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> diff --git a/devtools/client/webide/test/test_import.html b/devtools/client/webide/test/test_import.html new file mode 100644 index 000000000..830198cca --- /dev/null +++ b/devtools/client/webide/test/test_import.html @@ -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> diff --git a/devtools/client/webide/test/test_manifestUpdate.html b/devtools/client/webide/test/test_manifestUpdate.html new file mode 100644 index 000000000..66f9affd0 --- /dev/null +++ b/devtools/client/webide/test/test_manifestUpdate.html @@ -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> diff --git a/devtools/client/webide/test/test_newapp.html b/devtools/client/webide/test/test_newapp.html new file mode 100644 index 000000000..45374f268 --- /dev/null +++ b/devtools/client/webide/test/test_newapp.html @@ -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> diff --git a/devtools/client/webide/test/test_runtime.html b/devtools/client/webide/test/test_runtime.html new file mode 100644 index 000000000..9b16ef82d --- /dev/null +++ b/devtools/client/webide/test/test_runtime.html @@ -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> diff --git a/devtools/client/webide/test/test_simulators.html b/devtools/client/webide/test/test_simulators.html new file mode 100644 index 000000000..204881512 --- /dev/null +++ b/devtools/client/webide/test/test_simulators.html @@ -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> diff --git a/devtools/client/webide/test/test_telemetry.html b/devtools/client/webide/test/test_telemetry.html new file mode 100644 index 000000000..225ddb89b --- /dev/null +++ b/devtools/client/webide/test/test_telemetry.html @@ -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> diff --git a/devtools/client/webide/test/test_toolbox.html b/devtools/client/webide/test/test_toolbox.html new file mode 100644 index 000000000..71ac2706c --- /dev/null +++ b/devtools/client/webide/test/test_toolbox.html @@ -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> diff --git a/devtools/client/webide/test/test_zoom.html b/devtools/client/webide/test/test_zoom.html new file mode 100644 index 000000000..4ad3885d2 --- /dev/null +++ b/devtools/client/webide/test/test_zoom.html @@ -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> diff --git a/devtools/client/webide/test/validator/no-name-or-icon/home.html b/devtools/client/webide/test/validator/no-name-or-icon/home.html new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/webide/test/validator/no-name-or-icon/home.html diff --git a/devtools/client/webide/test/validator/no-name-or-icon/manifest.webapp b/devtools/client/webide/test/validator/no-name-or-icon/manifest.webapp new file mode 100644 index 000000000..149e3fb79 --- /dev/null +++ b/devtools/client/webide/test/validator/no-name-or-icon/manifest.webapp @@ -0,0 +1,3 @@ +{ + "launch_path": "/home.html" +} diff --git a/devtools/client/webide/test/validator/non-absolute-path/manifest.webapp b/devtools/client/webide/test/validator/non-absolute-path/manifest.webapp new file mode 100644 index 000000000..64744067f --- /dev/null +++ b/devtools/client/webide/test/validator/non-absolute-path/manifest.webapp @@ -0,0 +1,7 @@ +{ + "name": "non-absolute path", + "icons": { + "128": "/icon.png" + }, + "launch_path": "non-absolute.html" +} diff --git a/devtools/client/webide/test/validator/valid/alsoValid/manifest.webapp b/devtools/client/webide/test/validator/valid/alsoValid/manifest.webapp new file mode 100644 index 000000000..20bd97bba --- /dev/null +++ b/devtools/client/webide/test/validator/valid/alsoValid/manifest.webapp @@ -0,0 +1,7 @@ +{ + "name": "valid at subfolder", + "launch_path": "/home.html", + "icons": { + "128": "/icon.png" + } +} diff --git a/devtools/client/webide/test/validator/valid/home.html b/devtools/client/webide/test/validator/valid/home.html new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/webide/test/validator/valid/home.html diff --git a/devtools/client/webide/test/validator/valid/icon.png b/devtools/client/webide/test/validator/valid/icon.png new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/webide/test/validator/valid/icon.png diff --git a/devtools/client/webide/test/validator/valid/manifest.webapp b/devtools/client/webide/test/validator/valid/manifest.webapp new file mode 100644 index 000000000..2c22a1567 --- /dev/null +++ b/devtools/client/webide/test/validator/valid/manifest.webapp @@ -0,0 +1,7 @@ +{ + "name": "valid", + "launch_path": "/home.html", + "icons": { + "128": "/icon.png" + } +} diff --git a/devtools/client/webide/test/validator/wrong-launch-path/icon.png b/devtools/client/webide/test/validator/wrong-launch-path/icon.png new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/devtools/client/webide/test/validator/wrong-launch-path/icon.png diff --git a/devtools/client/webide/test/validator/wrong-launch-path/manifest.webapp b/devtools/client/webide/test/validator/wrong-launch-path/manifest.webapp new file mode 100644 index 000000000..08057bae1 --- /dev/null +++ b/devtools/client/webide/test/validator/wrong-launch-path/manifest.webapp @@ -0,0 +1,7 @@ +{ + "name": "valid", + "launch_path": "/wrong-path.html", + "icons": { + "128": "/icon.png" + } +} |