mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 1280947 - Dispatch DOM change event on appending file to input; r=automatedtester
MozReview-Commit-ID: 6SC01AEkuTs --HG-- extra : rebase_source : ee4ed323e024bf6fdcf9a28ab7f44763c7475c8c
This commit is contained in:
parent
e213d0d9c5
commit
0f34b42611
93
testing/marionette/addon.js
Normal file
93
testing/marionette/addon.js
Normal file
@ -0,0 +1,93 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
Cu.import("chrome://marionette/content/error.js");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["addon"];
|
||||
|
||||
this.addon = {};
|
||||
|
||||
/**
|
||||
* Installs Firefox addon.
|
||||
*
|
||||
* If the addon is restartless, it can be used right away. Otherwise a
|
||||
* restart is needed.
|
||||
*
|
||||
* Temporary addons will automatically be unisntalled on shutdown and
|
||||
* do not need to be signed, though they must be restartless.
|
||||
*
|
||||
* @param {string} path
|
||||
* Full path to the extension package archive to be installed.
|
||||
* @param {boolean=} temporary
|
||||
* Install the add-on temporarily if true.
|
||||
*
|
||||
* @return {Promise.<string>}
|
||||
* Addon ID string of the newly installed addon.
|
||||
*
|
||||
* @throws {AddonError}
|
||||
* if installation fails
|
||||
*/
|
||||
addon.install = function(path, temporary = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let listener = {
|
||||
onInstallEnded: function(install, addon) {
|
||||
resolve(addon.id);
|
||||
},
|
||||
|
||||
onInstallFailed: function(install) {
|
||||
reject(new AddonError(install.error));
|
||||
},
|
||||
|
||||
onInstalled: function(addon) {
|
||||
AddonManager.removeAddonListener(listener);
|
||||
resolve(addon.id);
|
||||
}
|
||||
};
|
||||
|
||||
let file = new FileUtils.File(path);
|
||||
|
||||
// temporary addons
|
||||
if (temp) {
|
||||
AddonManager.addAddonListener(listener);
|
||||
AddonManager.installTemporaryAddon(file);
|
||||
}
|
||||
|
||||
// addons that require restart
|
||||
else {
|
||||
AddonManager.getInstallForFile(file, function(aInstall) {
|
||||
if (aInstall.error != 0) {
|
||||
reject(new AddonError(aInstall.error));
|
||||
}
|
||||
aInstall.addListener(listener);
|
||||
aInstall.install();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Uninstall a Firefox addon.
|
||||
*
|
||||
* If the addon is restartless, it will be uninstalled right
|
||||
* away. Otherwise a restart is necessary.
|
||||
*
|
||||
* @param {string} id
|
||||
* Addon ID to uninstall.
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
addon.uninstall = function(id) {
|
||||
return new Promise(resolve => {
|
||||
AddonManager.getAddonByID(arguments[0], function(addon) {
|
||||
addon.uninstall();
|
||||
});
|
||||
});
|
||||
};
|
@ -0,0 +1,31 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from marionette import MarionetteTestCase
|
||||
from marionette_driver.errors import UnknownException
|
||||
|
||||
|
||||
class TestCertificates(MarionetteTestCase):
|
||||
def test_block_insecure_sites(self):
|
||||
self.marionette.delete_session()
|
||||
self.marionette.start_session()
|
||||
|
||||
self.marionette.navigate(self.fixtures.where_is("test.html", on="http"))
|
||||
self.assertIn("http://", self.marionette.get_url())
|
||||
with self.assertRaises(UnknownException):
|
||||
self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
|
||||
|
||||
def test_accept_all_insecure(self):
|
||||
self.marionette.delete_session()
|
||||
self.marionette.start_session({"desiredCapability": {"acceptSslCerts": ["*"]}})
|
||||
self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
|
||||
self.assertIn("https://", self.marionette.url)
|
||||
|
||||
"""
|
||||
def test_accept_some_insecure(self):
|
||||
self.marionette.delete_session()
|
||||
self.marionette.start_session({"requiredCapabilities": {"acceptSslCerts": ["127.0.0.1"]}})
|
||||
self.marionette.navigate(self.fixtures.where_is("test.html", on="https"))
|
||||
self.assertIn("https://", self.marionette.url)
|
||||
"""
|
@ -105,6 +105,22 @@ class TestFileUpload(MarionetteTestCase):
|
||||
Wait(self.marionette).until(lambda m: m.get_url() != url)
|
||||
self.assertIn("multipart/form-data", self.body.text)
|
||||
|
||||
def test_change_event(self):
|
||||
self.marionette.navigate(single)
|
||||
self.marionette.execute_script("""
|
||||
window.changeEvs = [];
|
||||
let el = arguments[arguments.length - 1];
|
||||
el.addEventListener("change", ev => window.changeEvs.push(ev));
|
||||
console.log(window.changeEvs.length);
|
||||
""", script_args=(self.input,), sandbox=None)
|
||||
|
||||
with tempfile() as f:
|
||||
self.input.send_keys(f.name)
|
||||
|
||||
nevs = self.marionette.execute_script(
|
||||
"return window.changeEvs.length", sandbox=None)
|
||||
self.assertEqual(1, nevs)
|
||||
|
||||
def find_inputs(self):
|
||||
return self.marionette.find_elements(By.TAG_NAME, "input")
|
||||
|
||||
|
@ -221,6 +221,33 @@ interaction.selectOption = function(el) {
|
||||
event.click(parent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends |path| to an <input type=file>'s file list.
|
||||
*
|
||||
* @param {HTMLInputElement} el
|
||||
* An <input type=file> element.
|
||||
* @param {File} file
|
||||
* File object to assign to |el|.
|
||||
*/
|
||||
interaction.uploadFile = function(el, file) {
|
||||
let fs = Array.prototype.slice.call(el.files);
|
||||
fs.push(file);
|
||||
|
||||
// <input type=file> opens OS widget dialogue
|
||||
// which means the mousedown/focus/mouseup/click events
|
||||
// occur before the change event
|
||||
event.mouseover(el);
|
||||
event.mousemove(el);
|
||||
event.mousedown(el);
|
||||
event.focus(el);
|
||||
event.mouseup(el);
|
||||
event.click(el);
|
||||
|
||||
el.mozSetFileArray(fs);
|
||||
|
||||
event.change(el);
|
||||
};
|
||||
|
||||
/**
|
||||
* Locate the <select> element that encapsulate an <option> element.
|
||||
*
|
||||
|
@ -595,20 +595,21 @@ function setTestName(msg) {
|
||||
* sendKeysToElement action on a file input element.
|
||||
*/
|
||||
function receiveFiles(msg) {
|
||||
if ('error' in msg.json) {
|
||||
if ("error" in msg.json) {
|
||||
let err = new InvalidArgumentError(msg.json.error);
|
||||
sendError(err, msg.json.command_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fileInputElement) {
|
||||
let err = new InvalidElementStateError("receiveFiles called with no valid fileInputElement");
|
||||
sendError(err, msg.json.command_id);
|
||||
return;
|
||||
}
|
||||
let fs = Array.prototype.slice.call(fileInputElement.files);
|
||||
fs.push(msg.json.file);
|
||||
fileInputElement.mozSetFileArray(fs);
|
||||
|
||||
interaction.uploadFile(fileInputElement, msg.json.file);
|
||||
fileInputElement = null;
|
||||
|
||||
sendOk(msg.json.command_id);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user