mirror of
https://github.com/servo/servo.git
synced 2025-08-15 10:25:32 +01:00
Implement webdriver extract script arguments (#38357)
Fix script parsing step. Implement webdriver `extract script arguments`. Implement `deserialize_web_element` and `deserialize_shadow_root` from script command argument. Testing: `/tests/wpt/tests/webdriver/tests/classic/execute_script/` `/tests/wpt/tests/webdriver/tests/classic/execute_async_script/` cc: @xiaochengh --------- Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
This commit is contained in:
parent
c0d884ddb2
commit
9effdce5a1
9 changed files with 228 additions and 169 deletions
|
@ -1524,9 +1524,22 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
.map(Root::upcast::<Element>)
|
||||
}
|
||||
|
||||
fn WebdriverWindow(&self, _id: DOMString) -> Option<DomRoot<Window>> {
|
||||
warn!("Window references are not supported in webdriver yet");
|
||||
None
|
||||
fn WebdriverWindow(&self, id: DOMString) -> Option<DomRoot<WindowProxy>> {
|
||||
let window_proxy = self.window_proxy.get()?;
|
||||
|
||||
// Window must be top level browsing context.
|
||||
if window_proxy.browsing_context_id() != window_proxy.webview_id() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let pipeline_id = window_proxy.currently_active()?;
|
||||
let document = ScriptThread::find_document(pipeline_id)?;
|
||||
|
||||
if document.upcast::<Node>().unique_id(pipeline_id) == id.str() {
|
||||
Some(DomRoot::from_ref(&window_proxy))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn WebdriverShadowRoot(&self, id: DOMString) -> Option<DomRoot<ShadowRoot>> {
|
||||
|
|
|
@ -2396,6 +2396,22 @@ impl ScriptThread {
|
|||
can_gc,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::GetKnownElement(element_id, reply) => {
|
||||
webdriver_handlers::handle_get_known_element(
|
||||
&documents,
|
||||
pipeline_id,
|
||||
element_id,
|
||||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::GetKnownShadowRoot(element_id, reply) => {
|
||||
webdriver_handlers::handle_get_known_shadow_root(
|
||||
&documents,
|
||||
pipeline_id,
|
||||
element_id,
|
||||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::GetActiveElement(reply) => {
|
||||
webdriver_handlers::handle_get_active_element(&documents, pipeline_id, reply)
|
||||
},
|
||||
|
|
|
@ -122,6 +122,18 @@ fn is_disabled(element: &Element) -> bool {
|
|||
element.is_actually_disabled()
|
||||
}
|
||||
|
||||
pub(crate) fn handle_get_known_shadow_root(
|
||||
documents: &DocumentCollection,
|
||||
pipeline: PipelineId,
|
||||
shadow_root_id: String,
|
||||
reply: IpcSender<Result<(), ErrorStatus>>,
|
||||
) {
|
||||
let result = get_known_shadow_root(documents, pipeline, shadow_root_id).map(|_| ());
|
||||
if reply.send(result).is_err() {
|
||||
error!("Webdriver get known shadow root reply failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-get-a-known-shadow-root>
|
||||
fn get_known_shadow_root(
|
||||
documents: &DocumentCollection,
|
||||
|
@ -170,6 +182,18 @@ fn get_known_shadow_root(
|
|||
Ok(shadow_root)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_get_known_element(
|
||||
documents: &DocumentCollection,
|
||||
pipeline: PipelineId,
|
||||
element_id: String,
|
||||
reply: IpcSender<Result<(), ErrorStatus>>,
|
||||
) {
|
||||
let result = get_known_element(documents, pipeline, element_id).map(|_| ());
|
||||
if reply.send(result).is_err() {
|
||||
error!("Webdriver get known element reply failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-get-a-known-element>
|
||||
fn get_known_element(
|
||||
documents: &DocumentCollection,
|
||||
|
|
|
@ -152,7 +152,7 @@ partial interface Window {
|
|||
undefined webdriverTimeout();
|
||||
Element? webdriverElement(DOMString id);
|
||||
Element? webdriverFrame(DOMString id);
|
||||
Window? webdriverWindow(DOMString id);
|
||||
WindowProxy? webdriverWindow(DOMString id);
|
||||
ShadowRoot? webdriverShadowRoot(DOMString id);
|
||||
};
|
||||
|
||||
|
|
|
@ -210,6 +210,8 @@ pub enum WebDriverScriptCommand {
|
|||
FindShadowElementsXPathSelector(String, String, IpcSender<Result<Vec<String>, ErrorStatus>>),
|
||||
GetElementShadowRoot(String, IpcSender<Result<Option<String>, ErrorStatus>>),
|
||||
ElementClick(String, IpcSender<Result<Option<String>, ErrorStatus>>),
|
||||
GetKnownElement(String, IpcSender<Result<(), ErrorStatus>>),
|
||||
GetKnownShadowRoot(String, IpcSender<Result<(), ErrorStatus>>),
|
||||
GetActiveElement(IpcSender<Option<String>>),
|
||||
GetComputedRole(String, IpcSender<Result<Option<String>, ErrorStatus>>),
|
||||
GetCookie(
|
||||
|
|
144
components/webdriver_server/elements.rs
Normal file
144
components/webdriver_server/elements.rs
Normal file
|
@ -0,0 +1,144 @@
|
|||
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use embedder_traits::WebDriverScriptCommand;
|
||||
use ipc_channel::ipc;
|
||||
use serde_json::Value;
|
||||
use webdriver::command::JavascriptCommandParameters;
|
||||
use webdriver::error::{WebDriverError, WebDriverResult};
|
||||
|
||||
use crate::{Handler, VerifyBrowsingContextIsOpen, wait_for_ipc_response};
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-web-element-identifier>
|
||||
const ELEMENT_IDENTIFIER: &str = "element-6066-11e4-a52e-4f735466cecf";
|
||||
/// <https://w3c.github.io/webdriver/#dfn-web-frame-identifier>
|
||||
const FRAME_IDENTIFIER: &str = "frame-075b-4da1-b6ba-e579c2d3230a";
|
||||
/// <https://w3c.github.io/webdriver/#dfn-web-window-identifier>
|
||||
const WINDOW_IDENTIFIER: &str = "window-fcc6-11e5-b4f8-330a88ab9d7f";
|
||||
/// <https://w3c.github.io/webdriver/#dfn-shadow-root-identifier>
|
||||
const SHADOW_ROOT_IDENTIFIER: &str = "shadow-6066-11e4-a52e-4f735466cecf";
|
||||
|
||||
impl Handler {
|
||||
/// <https://w3c.github.io/webdriver/#dfn-extract-the-script-arguments-from-a-request>
|
||||
pub(crate) fn extract_script_arguments(
|
||||
&self,
|
||||
parameters: JavascriptCommandParameters,
|
||||
) -> WebDriverResult<(String, Vec<String>)> {
|
||||
// Step 1. Let script be the result of getting a property named "script" from parameters
|
||||
// Step 2. (Skip) If script is not a String, return error with error code invalid argument.
|
||||
let script = parameters.script;
|
||||
|
||||
// Step 3. Let args be the result of getting a property named "args" from parameters.
|
||||
// Step 4. (Skip) If args is not an Array return error with error code invalid argument.
|
||||
let args: Vec<String> = parameters
|
||||
.args
|
||||
.as_deref()
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.map(|value| self.json_deserialize(value))
|
||||
.collect::<WebDriverResult<Vec<_>>>()?;
|
||||
|
||||
Ok((script, args))
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-deserialize-a-web-element>
|
||||
pub(crate) fn deserialize_web_element(&self, element: &Value) -> WebDriverResult<String> {
|
||||
// Step 2. Let reference be the result of getting the web element identifier property from object.
|
||||
let element_ref: String = match element {
|
||||
Value::String(s) => s.clone(),
|
||||
_ => element.to_string(),
|
||||
};
|
||||
|
||||
// Step 3. Let element be the result of trying to get a known element with session and reference.
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.browsing_context_script_command(
|
||||
WebDriverScriptCommand::GetKnownElement(element_ref.clone(), sender),
|
||||
VerifyBrowsingContextIsOpen::No,
|
||||
)?;
|
||||
|
||||
match wait_for_ipc_response(receiver)? {
|
||||
// Step 4. Return success with data element.
|
||||
Ok(_) => Ok(format!("window.webdriverElement(\"{}\")", element_ref)),
|
||||
Err(err) => Err(WebDriverError::new(err, "No such element")),
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-deserialize-a-shadow-root>
|
||||
pub(crate) fn deserialize_shadow_root(&self, shadow_root: &Value) -> WebDriverResult<String> {
|
||||
// Step 2. Let reference be the result of getting the shadow root identifier property from object.
|
||||
let shadow_root_ref = match shadow_root {
|
||||
Value::String(s) => s.clone(),
|
||||
_ => shadow_root.to_string(),
|
||||
};
|
||||
|
||||
// Step 3. Let element be the result of trying to get a known element with session and reference.
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.browsing_context_script_command(
|
||||
WebDriverScriptCommand::GetKnownShadowRoot(shadow_root_ref.clone(), sender),
|
||||
VerifyBrowsingContextIsOpen::No,
|
||||
)?;
|
||||
|
||||
match wait_for_ipc_response(receiver)? {
|
||||
// Step 4. Return success with data element.
|
||||
Ok(_) => Ok(format!(
|
||||
"window.webdriverShadowRoot(\"{}\")",
|
||||
shadow_root_ref
|
||||
)),
|
||||
Err(err) => Err(WebDriverError::new(err, "No such shadowroot")),
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-json-deserialize>
|
||||
fn json_deserialize(&self, v: &Value) -> WebDriverResult<String> {
|
||||
let res = match v {
|
||||
Value::Null => "null".to_string(),
|
||||
Value::String(s) => format!("\"{}\"", s),
|
||||
Value::Bool(b) => b.to_string(),
|
||||
Value::Number(n) => n.to_string(),
|
||||
Value::Array(list) => {
|
||||
let elems = list
|
||||
.iter()
|
||||
.map(|v| self.json_deserialize(v))
|
||||
.collect::<WebDriverResult<Vec<_>>>()?;
|
||||
format!("[{}]", elems.join(", "))
|
||||
},
|
||||
Value::Object(map) => {
|
||||
let key = map.keys().next().map(String::as_str);
|
||||
match (key, map.values().next()) {
|
||||
(Some(ELEMENT_IDENTIFIER), Some(id)) => {
|
||||
return self.deserialize_web_element(id);
|
||||
},
|
||||
(Some(FRAME_IDENTIFIER), Some(id)) => {
|
||||
let frame_ref = match id {
|
||||
Value::String(s) => s.clone(),
|
||||
_ => id.to_string(),
|
||||
};
|
||||
return Ok(format!("window.webdriverFrame(\"{}\")", frame_ref));
|
||||
},
|
||||
(Some(WINDOW_IDENTIFIER), Some(id)) => {
|
||||
let window_ref = match id {
|
||||
Value::String(s) => s.clone(),
|
||||
_ => id.to_string(),
|
||||
};
|
||||
return Ok(format!("window.webdriverWindow(\"{}\")", window_ref));
|
||||
},
|
||||
(Some(SHADOW_ROOT_IDENTIFIER), Some(id)) => {
|
||||
return self.deserialize_shadow_root(id);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
let elems = map
|
||||
.iter()
|
||||
.map(|(k, v)| {
|
||||
let arg = self.json_deserialize(v)?;
|
||||
Ok(format!("{}: {}", k, arg))
|
||||
})
|
||||
.collect::<WebDriverResult<Vec<String>>>()?;
|
||||
format!("{{{}}}", elems.join(", "))
|
||||
},
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
mod actions;
|
||||
mod capabilities;
|
||||
mod elements;
|
||||
mod session;
|
||||
mod timeout;
|
||||
mod user_prompt;
|
||||
|
@ -1955,23 +1956,11 @@ impl Handler {
|
|||
/// <https://w3c.github.io/webdriver/#dfn-execute-script>
|
||||
fn handle_execute_script(
|
||||
&self,
|
||||
parameters: &JavascriptCommandParameters,
|
||||
parameters: JavascriptCommandParameters,
|
||||
) -> WebDriverResult<WebDriverResponse> {
|
||||
// Step 2. If session's current browsing context is no longer open,
|
||||
// return error with error code no such window.
|
||||
self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?;
|
||||
// Step 3. Handle any user prompt.
|
||||
self.handle_any_user_prompts(self.session()?.webview_id)?;
|
||||
|
||||
let func_body = ¶meters.script;
|
||||
let args_string: Vec<_> = parameters
|
||||
.args
|
||||
.as_deref()
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.map(webdriver_value_to_js_argument)
|
||||
.collect();
|
||||
|
||||
// Step 1. Let body and arguments be the result of trying to extract the script arguments
|
||||
// from a request with argument parameters.
|
||||
let (func_body, args_string) = self.extract_script_arguments(parameters)?;
|
||||
// This is pretty ugly; we really want something that acts like
|
||||
// new Function() and then takes the resulting function and executes
|
||||
// it with a vec of arguments.
|
||||
|
@ -1982,6 +1971,13 @@ impl Handler {
|
|||
);
|
||||
debug!("{}", script);
|
||||
|
||||
// Step 2. If session's current browsing context is no longer open,
|
||||
// return error with error code no such window.
|
||||
self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?;
|
||||
|
||||
// Step 3. Handle any user prompt.
|
||||
self.handle_any_user_prompts(self.session()?.webview_id)?;
|
||||
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
let cmd = WebDriverScriptCommand::ExecuteScript(script, sender);
|
||||
self.browsing_context_script_command(cmd, VerifyBrowsingContextIsOpen::No)?;
|
||||
|
@ -1991,22 +1987,11 @@ impl Handler {
|
|||
|
||||
fn handle_execute_async_script(
|
||||
&self,
|
||||
parameters: &JavascriptCommandParameters,
|
||||
parameters: JavascriptCommandParameters,
|
||||
) -> WebDriverResult<WebDriverResponse> {
|
||||
// Step 2. If session's current browsing context is no longer open,
|
||||
// return error with error code no such window.
|
||||
self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?;
|
||||
// Step 3. Handle any user prompt.
|
||||
self.handle_any_user_prompts(self.session()?.webview_id)?;
|
||||
|
||||
let func_body = ¶meters.script;
|
||||
let mut args_string: Vec<_> = parameters
|
||||
.args
|
||||
.as_deref()
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.map(webdriver_value_to_js_argument)
|
||||
.collect();
|
||||
// Step 1. Let body and arguments be the result of trying to extract the script arguments
|
||||
// from a request with argument parameters.
|
||||
let (func_body, mut args_string) = self.extract_script_arguments(parameters)?;
|
||||
args_string.push("resolve".to_string());
|
||||
|
||||
let timeout_script = if let Some(script_timeout) = self.session()?.timeouts.script {
|
||||
|
@ -2032,6 +2017,13 @@ impl Handler {
|
|||
);
|
||||
debug!("{}", script);
|
||||
|
||||
// Step 2. If session's current browsing context is no longer open,
|
||||
// return error with error code no such window.
|
||||
self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?;
|
||||
|
||||
// Step 3. Handle any user prompt.
|
||||
self.handle_any_user_prompts(self.session()?.webview_id)?;
|
||||
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
let cmd = WebDriverScriptCommand::ExecuteAsyncScript(script, sender);
|
||||
self.browsing_context_script_command(cmd, VerifyBrowsingContextIsOpen::No)?;
|
||||
|
@ -2524,8 +2516,8 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
|
|||
self.handle_perform_actions(actions_parameters)
|
||||
},
|
||||
WebDriverCommand::ReleaseActions => self.handle_release_actions(),
|
||||
WebDriverCommand::ExecuteScript(ref x) => self.handle_execute_script(x),
|
||||
WebDriverCommand::ExecuteAsyncScript(ref x) => self.handle_execute_async_script(x),
|
||||
WebDriverCommand::ExecuteScript(x) => self.handle_execute_script(x),
|
||||
WebDriverCommand::ExecuteAsyncScript(x) => self.handle_execute_async_script(x),
|
||||
WebDriverCommand::ElementSendKeys(ref element, ref keys) => {
|
||||
self.handle_element_send_keys(element, keys)
|
||||
},
|
||||
|
@ -2560,54 +2552,6 @@ impl WebDriverHandler<ServoExtensionRoute> for Handler {
|
|||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-web-element-identifier>
|
||||
const ELEMENT_IDENTIFIER: &str = "element-6066-11e4-a52e-4f735466cecf";
|
||||
/// <https://w3c.github.io/webdriver/#dfn-web-frame-identifier>
|
||||
const FRAME_IDENTIFIER: &str = "frame-075b-4da1-b6ba-e579c2d3230a";
|
||||
/// <https://w3c.github.io/webdriver/#dfn-web-window-identifier>
|
||||
const WINDOW_IDENTIFIER: &str = "window-fcc6-11e5-b4f8-330a88ab9d7f";
|
||||
/// <https://w3c.github.io/webdriver/#dfn-shadow-root-identifier>
|
||||
const SHADOW_ROOT_IDENTIFIER: &str = "shadow-6066-11e4-a52e-4f735466cecf";
|
||||
|
||||
fn webdriver_value_to_js_argument(v: &Value) -> String {
|
||||
match v {
|
||||
Value::String(s) => format!("\"{}\"", s),
|
||||
Value::Null => "null".to_string(),
|
||||
Value::Bool(b) => b.to_string(),
|
||||
Value::Number(n) => n.to_string(),
|
||||
Value::Array(list) => {
|
||||
let elems = list
|
||||
.iter()
|
||||
.map(|v| webdriver_value_to_js_argument(v).to_string())
|
||||
.collect::<Vec<_>>();
|
||||
format!("[{}]", elems.join(", "))
|
||||
},
|
||||
Value::Object(map) => {
|
||||
let key = map.keys().next().map(String::as_str);
|
||||
match (key, map.values().next()) {
|
||||
(Some(ELEMENT_IDENTIFIER), Some(id)) => {
|
||||
return format!("window.webdriverElement({})", id);
|
||||
},
|
||||
(Some(FRAME_IDENTIFIER), Some(id)) => {
|
||||
return format!("window.webdriverFrame({})", id);
|
||||
},
|
||||
(Some(WINDOW_IDENTIFIER), Some(id)) => {
|
||||
return format!("window.webdriverWindow({})", id);
|
||||
},
|
||||
(Some(SHADOW_ROOT_IDENTIFIER), Some(id)) => {
|
||||
return format!("window.webdriverShadowRoot({})", id);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
let elems = map
|
||||
.iter()
|
||||
.map(|(k, v)| format!("{}: {}", k, webdriver_value_to_js_argument(v)))
|
||||
.collect::<Vec<_>>();
|
||||
format!("{{{}}}", elems.join(", "))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn wait_for_ipc_response<T>(receiver: IpcReceiver<T>) -> Result<T, WebDriverError>
|
||||
where
|
||||
T: for<'de> Deserialize<'de> + Serialize,
|
||||
|
|
|
@ -1,40 +1,4 @@
|
|||
[arguments.py]
|
||||
[test_no_such_element_with_unknown_id]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_window_handle[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_window_handle[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_frame[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_frame[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_with_unknown_id]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_window_handle[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_window_handle[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_frame[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_frame[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_stale_element_reference[top_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_stale_element_reference[child_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_invalid_argument_for_window_with_invalid_type[None-frame\]]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -73,6 +37,3 @@
|
|||
|
||||
[test_element_reference[shadow-root\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[window\]]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,46 +1,4 @@
|
|||
[arguments.py]
|
||||
[test_no_such_element_with_unknown_id]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_window_handle[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_window_handle[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_frame[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_element_from_other_frame[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_with_unknown_id]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_window_handle[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_window_handle[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_frame[open\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_no_such_shadow_root_from_other_frame[closed\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_detached_shadow_root_reference[top_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_detached_shadow_root_reference[child_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_stale_element_reference[top_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_stale_element_reference[child_context\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_invalid_argument_for_window_with_invalid_type[None-frame\]]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -79,6 +37,3 @@
|
|||
|
||||
[test_element_reference[shadow-root\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_element_reference[window\]]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue