mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-02 22:37:50 +00:00
Backed out 8 changesets (bug 1502864) for failing test_capabilities.py CLOSED TREE
Backed out changeset 6e4454a6f3ee (bug 1502864) Backed out changeset 3f7ca511af8c (bug 1502864) Backed out changeset 9382a6630231 (bug 1502864) Backed out changeset 1eb51f6b4ba0 (bug 1502864) Backed out changeset 2fda41394085 (bug 1502864) Backed out changeset 0b421dd8a7d5 (bug 1502864) Backed out changeset 9caa2f0e2e38 (bug 1502864) Backed out changeset 7616e25a07b3 (bug 1502864)
This commit is contained in:
parent
ec4136b39b
commit
ea4e67046a
@ -9,29 +9,9 @@ Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Introduces `strictFileInteractability` capability
|
||||
|
||||
The new capabilitiy indicates if strict interactability checks
|
||||
should be applied to `<input type=file>` elements. As strict
|
||||
interactability checks are off by default, there is a change
|
||||
in behaviour when using [Element Send Keys] with hidden file
|
||||
upload controls.
|
||||
|
||||
- Added new endpoint `GET /session/{session id}/moz/screenshot/full`
|
||||
for taking full document screenshots, thanks to Greg Fraley.
|
||||
|
||||
# Changed
|
||||
|
||||
- Allow file uploads to hidden `<input type=file>` elements
|
||||
|
||||
Through a series of changes to the WebDriver specification,
|
||||
geckodriver is now aligned with chromedriver’s behaviour that
|
||||
allows interaction with hidden `<input type=file>` elements.
|
||||
|
||||
This allows WebDriver to be used with various popular web frameworks
|
||||
that—through indirection—hides the file upload control and
|
||||
invokes it through other means.
|
||||
|
||||
|
||||
0.23.0 (2018-10-03)
|
||||
-------------------
|
||||
|
@ -156,10 +156,6 @@ impl<'a> BrowserCapabilities for FirefoxCapabilities<'a> {
|
||||
.or_else(|x| Err(convert_version_error(x)))
|
||||
}
|
||||
|
||||
fn strict_file_interactability(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn accept_proxy(&mut self, _: &Capabilities, _: &Capabilities) -> WebDriverResult<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
@ -397,7 +397,6 @@ class Capabilities extends Map {
|
||||
["proxy", new Proxy()],
|
||||
["setWindowRect", appinfo.name == "firefox"],
|
||||
["timeouts", new Timeouts()],
|
||||
["strictFileInteractability", false],
|
||||
["unhandledPromptBehavior", UnhandledPromptBehavior.DismissAndNotify],
|
||||
|
||||
// features
|
||||
@ -494,10 +493,6 @@ class Capabilities extends Map {
|
||||
v = Timeouts.fromJSON(v);
|
||||
break;
|
||||
|
||||
case "strictFileInteractability":
|
||||
v = assert.boolean(v);
|
||||
break;
|
||||
|
||||
case "unhandledPromptBehavior":
|
||||
assert.string(v, pprint`Expected ${k} to be a string, got ${v}`);
|
||||
if (!Object.values(UnhandledPromptBehavior).includes(v)) {
|
||||
|
@ -1256,9 +1256,6 @@ class Marionette(object):
|
||||
if capabilities is None:
|
||||
capabilities = {}
|
||||
|
||||
if capabilities is None:
|
||||
capabilities = {"strictFileInteractability": True}
|
||||
|
||||
if timeout is None:
|
||||
timeout = self.startup_timeout
|
||||
|
||||
|
@ -2533,9 +2533,9 @@ GeckoDriver.prototype.getElementRect = async function(cmd) {
|
||||
* Value to send to the element.
|
||||
*
|
||||
* @throws {InvalidArgumentError}
|
||||
* If `id` or `text` are not strings.
|
||||
* If <var>id</var> or <var>text</var> are not strings.
|
||||
* @throws {NoSuchElementError}
|
||||
* If element represented by reference `id` is unknown.
|
||||
* If element represented by reference <var>id</var> is unknown.
|
||||
* @throws {NoSuchWindowError}
|
||||
* Top-level browsing context has been discarded.
|
||||
* @throws {UnexpectedAlertOpenError}
|
||||
@ -2552,8 +2552,7 @@ GeckoDriver.prototype.sendKeysToElement = async function(cmd) {
|
||||
switch (this.context) {
|
||||
case Context.Chrome:
|
||||
let el = this.curBrowser.seenEls.get(webEl);
|
||||
await interaction.sendKeysToElement(el, text,
|
||||
{accessibilityChecks: this.a11yChecks});
|
||||
await interaction.sendKeysToElement(el, text, this.a11yChecks);
|
||||
break;
|
||||
|
||||
case Context.Content:
|
||||
|
@ -62,7 +62,6 @@ class TestCapabilities(MarionetteTestCase):
|
||||
self.assertIn("acceptInsecureCerts", self.caps)
|
||||
self.assertIn("setWindowRect", self.caps)
|
||||
self.assertIn("timeouts", self.caps)
|
||||
self.assertIn("strictFileInteractability", self.caps)
|
||||
|
||||
self.assertEqual(self.caps["browserName"], self.appinfo["name"].lower())
|
||||
self.assertEqual(self.caps["browserVersion"], self.appinfo["version"])
|
||||
@ -77,7 +76,6 @@ class TestCapabilities(MarionetteTestCase):
|
||||
{"implicit": 0,
|
||||
"pageLoad": 300000,
|
||||
"script": 30000})
|
||||
self.assertTrue(self.caps["strictFileInteractability"])
|
||||
|
||||
def test_supported_features(self):
|
||||
self.assertIn("rotatable", self.caps)
|
||||
@ -182,23 +180,6 @@ class TestCapabilityMatching(MarionetteTestCase):
|
||||
self.assertDictEqual(self.marionette.session_capabilities["timeouts"], timeouts)
|
||||
self.assertDictEqual(self.marionette._send_message("WebDriver:GetTimeouts"), timeouts)
|
||||
|
||||
def test_strict_file_interactability(self):
|
||||
for value in ["", 2.5, {}, []]:
|
||||
with self.assertRaises(SessionNotCreatedException):
|
||||
self.marionette.start_session({"strictFileInteractability": value})
|
||||
|
||||
self.delete_session()
|
||||
|
||||
self.marionette.start_session({"strictFileInteractability": True})
|
||||
self.assertIn("strictFileInteractability", self.marionette.session_capabilities)
|
||||
self.assertTrue(self.marionette.session_capabilities["strictFileInteractability"])
|
||||
|
||||
self.delete_session()
|
||||
|
||||
self.marionette.start_session({"strictFileInteractability": False})
|
||||
self.assertIn("strictFileInteractability", self.marionette.session_capabilities)
|
||||
self.assertFalse(self.marionette.session_capabilities["strictFileInteractability"])
|
||||
|
||||
def test_unhandled_prompt_behavior(self):
|
||||
behaviors = [
|
||||
"accept",
|
||||
|
@ -540,41 +540,31 @@ interaction.setFormControlValue = function(el, value) {
|
||||
* Element to send key events to.
|
||||
* @param {Array.<string>} value
|
||||
* Sequence of keystrokes to send to the element.
|
||||
* @param {boolean=} strictFileInteractability
|
||||
* Run interactability checks on `<input type=file>` elements.
|
||||
* @param {boolean=} accessibilityChecks
|
||||
* @param {boolean=} [strict=false] strict
|
||||
* Enforce strict accessibility tests.
|
||||
* @param {boolean=} webdriverClick
|
||||
* @param {boolean=} [specCompat=false] specCompat
|
||||
* Use WebDriver specification compatible interactability definition.
|
||||
*/
|
||||
interaction.sendKeysToElement = async function(el, value,
|
||||
{
|
||||
strictFileInteractability = false,
|
||||
accessibilityChecks = false,
|
||||
webdriverClick = false,
|
||||
} = {}) {
|
||||
const a11y = accessibility.get(accessibilityChecks);
|
||||
interaction.sendKeysToElement = async function(
|
||||
el, value, strict = false, specCompat = false) {
|
||||
const a11y = accessibility.get(strict);
|
||||
|
||||
if (webdriverClick) {
|
||||
await webdriverSendKeysToElement(
|
||||
el, value, a11y, strictFileInteractability);
|
||||
if (specCompat) {
|
||||
await webdriverSendKeysToElement(el, value, a11y);
|
||||
} else {
|
||||
await legacySendKeysToElement(el, value, a11y);
|
||||
}
|
||||
};
|
||||
|
||||
async function webdriverSendKeysToElement(el, value,
|
||||
a11y, strictFileInteractability) {
|
||||
async function webdriverSendKeysToElement(el, value, a11y) {
|
||||
const win = getWindow(el);
|
||||
|
||||
if (el.type != "file" || strictFileInteractability) {
|
||||
let containerEl = element.getContainer(el);
|
||||
let containerEl = element.getContainer(el);
|
||||
|
||||
// TODO: Wait for element to be keyboard-interactible
|
||||
if (!interaction.isKeyboardInteractable(containerEl)) {
|
||||
throw new ElementNotInteractableError(
|
||||
pprint`Element ${el} is not reachable by keyboard`);
|
||||
}
|
||||
// TODO: Wait for element to be keyboard-interactible
|
||||
if (!interaction.isKeyboardInteractable(containerEl)) {
|
||||
throw new ElementNotInteractableError(
|
||||
pprint`Element ${el} is not reachable by keyboard`);
|
||||
}
|
||||
|
||||
let acc = await a11y.getAccessible(el, true);
|
||||
|
@ -1304,12 +1304,11 @@ function isElementSelected(el) {
|
||||
}
|
||||
|
||||
async function sendKeysToElement(el, val) {
|
||||
let opts = {
|
||||
strictFileInteractability: capabilities.get("strictFileInteractability"),
|
||||
accessibilityChecks: capabilities.get("moz:accessibilityChecks"),
|
||||
webdriverClick: capabilities.get("moz:webdriverClick"),
|
||||
};
|
||||
await interaction.sendKeysToElement(el, val, opts);
|
||||
await interaction.sendKeysToElement(
|
||||
el, val,
|
||||
capabilities.get("moz:accessibilityChecks"),
|
||||
capabilities.get("moz:webdriverClick"),
|
||||
);
|
||||
}
|
||||
|
||||
/** Clear the text of an element. */
|
||||
|
@ -382,7 +382,6 @@ add_test(function test_Capabilities_ctor() {
|
||||
ok(caps.get("timeouts") instanceof Timeouts);
|
||||
ok(caps.get("proxy") instanceof Proxy);
|
||||
equal(caps.get("setWindowRect"), false); // xpcshell does not populate appinfo
|
||||
equal(caps.get("strictFileInteractability"), false);
|
||||
|
||||
ok(caps.has("rotatable"));
|
||||
|
||||
@ -414,7 +413,6 @@ add_test(function test_Capabilities_toJSON() {
|
||||
deepEqual(caps.get("timeouts").toJSON(), json.timeouts);
|
||||
equal(undefined, json.proxy);
|
||||
equal(caps.get("setWindowRect"), json.setWindowRect);
|
||||
equal(caps.get("strictFileInteractability"), json.strictFileInteractability);
|
||||
|
||||
equal(caps.get("rotatable"), json.rotatable);
|
||||
|
||||
@ -467,11 +465,6 @@ add_test(function test_Capabilities_fromJSON() {
|
||||
equal(false, caps.get("setWindowRect"));
|
||||
Assert.throws(() => fromJSON({setWindowRect: true}), InvalidArgumentError);
|
||||
|
||||
caps = fromJSON({strictFileInteractability: false});
|
||||
equal(false, caps.get("strictFileInteractability"));
|
||||
caps = fromJSON({strictFileInteractability: true});
|
||||
equal(true, caps.get("strictFileInteractability"));
|
||||
|
||||
caps = fromJSON({"moz:accessibilityChecks": true});
|
||||
equal(true, caps.get("moz:accessibilityChecks"));
|
||||
caps = fromJSON({"moz:accessibilityChecks": false});
|
||||
|
@ -1,5 +1,3 @@
|
||||
import pytest
|
||||
|
||||
from tests.support.asserts import assert_error, assert_files_uploaded, assert_success
|
||||
from tests.support.inline import inline
|
||||
|
||||
@ -142,87 +140,3 @@ def test_single_file_appends_with_multiple_attribute(session, create_files):
|
||||
assert_success(response)
|
||||
|
||||
assert_files_uploaded(session, element, files)
|
||||
|
||||
|
||||
def test_transparent(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("""<input type=file style="opacity: 0">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_success(response)
|
||||
assert_files_uploaded(session, element, files)
|
||||
|
||||
|
||||
def test_obscured(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("""
|
||||
<style>
|
||||
div {
|
||||
position: absolute;
|
||||
width: 100vh;
|
||||
height: 100vh;
|
||||
background: blue;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<input type=file>
|
||||
<div></div>
|
||||
""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_success(response)
|
||||
assert_files_uploaded(session, element, files)
|
||||
|
||||
|
||||
def test_outside_viewport(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("""<input type=file style="margin-left: -100vh">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_success(response)
|
||||
assert_files_uploaded(session, element, files)
|
||||
|
||||
|
||||
def test_hidden(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("<input type=file hidden>")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_success(response)
|
||||
assert_files_uploaded(session, element, files)
|
||||
|
||||
|
||||
def test_display_none(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("""<input type=file style="display: none">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_success(response)
|
||||
assert_files_uploaded(session, element, files)
|
||||
|
||||
|
||||
@pytest.mark.capabilities({"strictFileInteractability": True})
|
||||
def test_strict_hidden(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("<input type=file hidden>")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_error(response, "element not interactable")
|
||||
|
||||
|
||||
@pytest.mark.capabilities({"strictFileInteractability": True})
|
||||
def test_strict_display_none(session, create_files):
|
||||
files = create_files(["foo"])
|
||||
session.url = inline("""<input type=file style="display: none">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = element_send_keys(session, element, str(files[0]))
|
||||
assert_error(response, "element not interactable")
|
||||
|
@ -21,7 +21,6 @@ def test_sessionid(new_session, add_browser_capabilities):
|
||||
("proxy", dict),
|
||||
("setWindowRect", bool),
|
||||
("timeouts", dict),
|
||||
("strictFileInteractability", bool),
|
||||
("unhandledPromptBehavior", basestring),
|
||||
])
|
||||
def test_capability_type(session, capability, type):
|
||||
@ -36,7 +35,6 @@ def test_capability_type(session, capability, type):
|
||||
("proxy", {}),
|
||||
("setWindowRect", True),
|
||||
("timeouts", {"implicit": 0, "pageLoad": 300000, "script": 30000}),
|
||||
("strictFileInteractability", False),
|
||||
("unhandledPromptBehavior", "dismiss and notify"),
|
||||
])
|
||||
def test_capability_default_value(session, capability, default_value):
|
||||
|
@ -27,9 +27,6 @@ valid_data = [
|
||||
{"script": 50, "pageLoad": 25},
|
||||
{"script": 500},
|
||||
]),
|
||||
("strictFileInteractability", [
|
||||
True, False, None,
|
||||
]),
|
||||
("unhandledPromptBehavior", [
|
||||
"dismiss",
|
||||
"accept",
|
||||
@ -98,9 +95,6 @@ invalid_data = [
|
||||
{"pageLoad": {"value": 10}},
|
||||
{"pageLoad": 10, "invalid": 10},
|
||||
]),
|
||||
("strictFileInteractability", [
|
||||
1, [], {}, "false",
|
||||
]),
|
||||
("unhandledPromptBehavior", [
|
||||
1, [], {}, False,
|
||||
"DISMISS",
|
||||
@ -112,25 +106,25 @@ invalid_data = [
|
||||
]
|
||||
|
||||
invalid_extensions = [
|
||||
"automaticInspection",
|
||||
"automaticProfiling",
|
||||
"browser",
|
||||
"chromeOptions",
|
||||
"ensureCleanSession",
|
||||
"firefox",
|
||||
"firefox_binary",
|
||||
"firefoxOptions",
|
||||
"initialBrowserUrl",
|
||||
"chromeOptions",
|
||||
"automaticInspection",
|
||||
"automaticProfiling",
|
||||
"platform",
|
||||
"version",
|
||||
"browser",
|
||||
"platformVersion",
|
||||
"javascriptEnabled",
|
||||
"nativeEvents",
|
||||
"seleniumProtocol",
|
||||
"profile",
|
||||
"trustAllSSLCertificates",
|
||||
"initialBrowserUrl",
|
||||
"requireWindowFocus",
|
||||
"logFile",
|
||||
"logLevel",
|
||||
"nativeEvents",
|
||||
"platform",
|
||||
"platformVersion",
|
||||
"profile",
|
||||
"requireWindowFocus",
|
||||
"safari.options",
|
||||
"seleniumProtocol",
|
||||
"trustAllSSLCertificates",
|
||||
"version",
|
||||
"ensureCleanSession",
|
||||
]
|
||||
|
@ -43,9 +43,6 @@ pub trait BrowserCapabilities {
|
||||
/// repositioning commands.
|
||||
fn set_window_rect(&mut self, &Capabilities) -> WebDriverResult<bool>;
|
||||
|
||||
/// Indicates that interactability checks will be applied to `<input type=file>`.
|
||||
fn strict_file_interactability(&mut self, &Capabilities) -> WebDriverResult<bool>;
|
||||
|
||||
fn accept_proxy(
|
||||
&mut self,
|
||||
proxy_settings: &Map<String, Value>,
|
||||
@ -126,7 +123,7 @@ impl SpecNewSessionParameters {
|
||||
|
||||
for (key, value) in &capabilities {
|
||||
match &**key {
|
||||
x @ "acceptInsecureCerts" | x @ "setWindowRect" | x @ "strictFileInteractability" => if !value.is_boolean() {
|
||||
x @ "acceptInsecureCerts" | x @ "setWindowRect" => if !value.is_boolean() {
|
||||
return Err(WebDriverError::new(
|
||||
ErrorStatus::InvalidArgument,
|
||||
format!("{} is not boolean: {}", x, value),
|
||||
@ -485,15 +482,6 @@ impl CapabilitiesMatching for SpecNewSessionParameters {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
"strictFileInteractability" => {
|
||||
if value.as_bool().unwrap_or(false)
|
||||
&& !browser_capabilities
|
||||
.strict_file_interactability(merged)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
"proxy" => {
|
||||
let default = Map::new();
|
||||
let proxy = value.as_object().unwrap_or(&default);
|
||||
|
Loading…
x
Reference in New Issue
Block a user