mirror of
https://github.com/servo/servo.git
synced 2025-07-03 05:23:38 +01:00
script::webdriver_handlers: Replace find_node_by_unique_id
with get_known_element
(#37502)
Implement previously missing step 3 of [get a known element](https://w3c.github.io/webdriver/#dfn-get-a-known-element): "If node is not null and node does not implement Element, return error with error code no such element" Testing: All webdriver conformance test --------- Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
parent
6159a11905
commit
f22c273ea9
1 changed files with 86 additions and 91 deletions
|
@ -72,17 +72,24 @@ use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
|||
use crate::script_thread::ScriptThread;
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-get-a-known-element>
|
||||
fn find_node_by_unique_id(
|
||||
fn get_known_element(
|
||||
documents: &DocumentCollection,
|
||||
pipeline: PipelineId,
|
||||
node_id: String,
|
||||
) -> Result<DomRoot<Node>, ErrorStatus> {
|
||||
) -> Result<DomRoot<Element>, ErrorStatus> {
|
||||
let doc = documents
|
||||
.find_document(pipeline)
|
||||
.expect("webdriver_handlers::Document should exists");
|
||||
find_node_by_unique_id_in_document(&doc, node_id)
|
||||
// Step 3. If node is not null and node does not implement Element
|
||||
// return error with error code no such element.
|
||||
find_node_by_unique_id_in_document(&doc, node_id).and_then(|node| {
|
||||
node.downcast::<Element>()
|
||||
.map(DomRoot::from_ref)
|
||||
.ok_or(ErrorStatus::NoSuchElement)
|
||||
})
|
||||
}
|
||||
|
||||
// This is also used by `dom/window.rs`
|
||||
pub(crate) fn find_node_by_unique_id_in_document(
|
||||
document: &Document,
|
||||
node_id: String,
|
||||
|
@ -526,8 +533,9 @@ pub(crate) fn handle_get_browsing_context_id(
|
|||
Err(ErrorStatus::UnsupportedOperation)
|
||||
},
|
||||
WebDriverFrameId::Element(element_id) => {
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
node.downcast::<HTMLIFrameElement>()
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
element
|
||||
.downcast::<HTMLIFrameElement>()
|
||||
.and_then(|element| element.browsing_context_id())
|
||||
.ok_or(ErrorStatus::NoSuchFrame)
|
||||
})
|
||||
|
@ -588,9 +596,8 @@ pub(crate) fn handle_get_element_in_view_center_point(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).map(|node| {
|
||||
get_element_in_view_center_point(node.downcast::<Element>().unwrap(), can_gc)
|
||||
.map(|point| (point.x, point.y))
|
||||
get_known_element(documents, pipeline, element_id).map(|element| {
|
||||
get_element_in_view_center_point(&element, can_gc).map(|point| (point.x, point.y))
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -627,7 +634,7 @@ pub(crate) fn handle_find_element_css(
|
|||
document
|
||||
.QuerySelector(DOMString::from(selector))
|
||||
.map_err(|_| ErrorStatus::InvalidSelector)
|
||||
.map(|node| node.map(|x| x.upcast::<Node>().unique_id(pipeline))),
|
||||
.map(|element| element.map(|x| x.upcast::<Node>().unique_id(pipeline))),
|
||||
)
|
||||
.unwrap(),
|
||||
Err(error) => reply.send(Err(error)).unwrap(),
|
||||
|
@ -668,7 +675,7 @@ pub(crate) fn handle_find_element_tag_name(
|
|||
.GetElementsByTagName(DOMString::from(selector), can_gc)
|
||||
.elements_iter()
|
||||
.next()
|
||||
.map(|node| node.upcast::<Node>().unique_id(pipeline))))
|
||||
.map(|element| element.upcast::<Node>().unique_id(pipeline))))
|
||||
.unwrap(),
|
||||
Err(error) => reply.send(Err(error)).unwrap(),
|
||||
}
|
||||
|
@ -747,10 +754,12 @@ pub(crate) fn handle_find_element_element_css(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
node.query_selector(DOMString::from(selector))
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
element
|
||||
.upcast::<Node>()
|
||||
.query_selector(DOMString::from(selector))
|
||||
.map_err(|_| ErrorStatus::InvalidSelector)
|
||||
.map(|node| node.map(|x| x.upcast::<Node>().unique_id(pipeline)))
|
||||
.map(|element| element.map(|x| x.upcast::<Node>().unique_id(pipeline)))
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -767,8 +776,9 @@ pub(crate) fn handle_find_element_element_link_text(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id)
|
||||
.and_then(|node| first_matching_link(&node, selector.clone(), partial, can_gc)),
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
first_matching_link(element.upcast::<Node>(), selector.clone(), partial, can_gc)
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -783,15 +793,12 @@ pub(crate) fn handle_find_element_element_tag_name(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node
|
||||
.downcast::<Element>(
|
||||
) {
|
||||
Some(element) => Ok(element
|
||||
get_known_element(documents, pipeline, element_id).map(|element| {
|
||||
element
|
||||
.GetElementsByTagName(DOMString::from(selector), can_gc)
|
||||
.elements_iter()
|
||||
.next()
|
||||
.map(|x| x.upcast::<Node>().unique_id(pipeline))),
|
||||
None => Err(ErrorStatus::UnknownError),
|
||||
.map(|x| x.upcast::<Node>().unique_id(pipeline))
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -806,8 +813,10 @@ pub(crate) fn handle_find_element_elements_css(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
node.query_selector_all(DOMString::from(selector))
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
element
|
||||
.upcast::<Node>()
|
||||
.query_selector_all(DOMString::from(selector))
|
||||
.map_err(|_| ErrorStatus::InvalidSelector)
|
||||
.map(|nodes| {
|
||||
nodes
|
||||
|
@ -831,8 +840,9 @@ pub(crate) fn handle_find_element_elements_link_text(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id)
|
||||
.and_then(|node| all_matching_links(&node, selector.clone(), partial, can_gc)),
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
all_matching_links(element.upcast::<Node>(), selector.clone(), partial, can_gc)
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -847,15 +857,12 @@ pub(crate) fn handle_find_element_elements_tag_name(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node
|
||||
.downcast::<Element>(
|
||||
) {
|
||||
Some(element) => Ok(element
|
||||
get_known_element(documents, pipeline, element_id).map(|element| {
|
||||
element
|
||||
.GetElementsByTagName(DOMString::from(selector), can_gc)
|
||||
.elements_iter()
|
||||
.map(|x| x.upcast::<Node>().unique_id(pipeline))
|
||||
.collect::<Vec<String>>()),
|
||||
None => Err(ErrorStatus::UnknownError),
|
||||
.collect::<Vec<String>>()
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -870,13 +877,10 @@ pub(crate) fn handle_get_element_shadow_root(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node
|
||||
.downcast::<Element>(
|
||||
) {
|
||||
Some(element) => Ok(element
|
||||
get_known_element(documents, pipeline, element_id).map(|element| {
|
||||
element
|
||||
.GetShadowRoot()
|
||||
.map(|x| x.upcast::<Node>().unique_id(pipeline))),
|
||||
None => Err(ErrorStatus::NoSuchElement),
|
||||
.map(|x| x.upcast::<Node>().unique_id(pipeline))
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -893,16 +897,16 @@ pub(crate) fn handle_will_send_keys(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
// Step 6: Let file be true if element is input element
|
||||
// in the file upload state, or false otherwise
|
||||
let file_input = node
|
||||
let file_input = element
|
||||
.downcast::<HTMLInputElement>()
|
||||
.filter(|&input_element| input_element.input_type() == InputType::File);
|
||||
|
||||
// Step 7: If file is false or the session's strict file interactability
|
||||
if file_input.is_none() || strict_file_interactability {
|
||||
match node.downcast::<HTMLElement>() {
|
||||
match element.downcast::<HTMLElement>() {
|
||||
Some(element) => {
|
||||
// Need a way to find if this actually succeeded
|
||||
element.Focus(can_gc);
|
||||
|
@ -970,12 +974,8 @@ pub(crate) fn handle_get_computed_role(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, node_id).and_then(|node| {
|
||||
match node.downcast::<Element>() {
|
||||
Some(element) => Ok(element.GetRole().map(String::from)),
|
||||
None => Err(ErrorStatus::UnknownError),
|
||||
}
|
||||
}),
|
||||
get_known_element(documents, pipeline, node_id)
|
||||
.map(|element| element.GetRole().map(String::from)),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -1181,9 +1181,9 @@ pub(crate) fn handle_get_rect(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
// https://w3c.github.io/webdriver/webdriver-spec.html#dfn-calculate-the-absolute-position
|
||||
match node.downcast::<HTMLElement>() {
|
||||
match element.downcast::<HTMLElement>() {
|
||||
Some(html_element) => {
|
||||
// Step 1
|
||||
let mut x = 0;
|
||||
|
@ -1227,17 +1227,12 @@ pub(crate) fn handle_get_bounding_client_rect(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node
|
||||
.downcast::<Element>(
|
||||
) {
|
||||
Some(element) => {
|
||||
get_known_element(documents, pipeline, element_id).map(|element| {
|
||||
let rect = element.GetBoundingClientRect(can_gc);
|
||||
Ok(Rect::new(
|
||||
Rect::new(
|
||||
Point2D::new(rect.X() as f32, rect.Y() as f32),
|
||||
Size2D::new(rect.Width() as f32, rect.Height() as f32),
|
||||
))
|
||||
},
|
||||
None => Err(ErrorStatus::UnknownError),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -1253,10 +1248,16 @@ pub(crate) fn handle_get_text(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, node_id).map(|node| {
|
||||
node.downcast::<HTMLElement>()
|
||||
.map(|element| element.InnerText(can_gc).to_string())
|
||||
.unwrap_or_else(|| node.GetTextContent().map_or("".to_owned(), String::from))
|
||||
get_known_element(documents, pipeline, node_id).map(|element| {
|
||||
element
|
||||
.downcast::<HTMLElement>()
|
||||
.map(|htmlelement| htmlelement.InnerText(can_gc).to_string())
|
||||
.unwrap_or_else(|| {
|
||||
element
|
||||
.upcast::<Node>()
|
||||
.GetTextContent()
|
||||
.map_or("".to_owned(), String::from)
|
||||
})
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -1270,8 +1271,8 @@ pub(crate) fn handle_get_name(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, node_id)
|
||||
.map(|node| String::from(node.downcast::<Element>().unwrap().TagName())),
|
||||
get_known_element(documents, pipeline, node_id)
|
||||
.map(|element| String::from(element.TagName())),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -1285,9 +1286,8 @@ pub(crate) fn handle_get_attribute(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, node_id).map(|node| {
|
||||
node.downcast::<Element>()
|
||||
.unwrap()
|
||||
get_known_element(documents, pipeline, node_id).map(|element| {
|
||||
element
|
||||
.GetAttribute(DOMString::from(name))
|
||||
.map(String::from)
|
||||
}),
|
||||
|
@ -1306,7 +1306,7 @@ pub(crate) fn handle_get_property(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, node_id).map(|node| {
|
||||
get_known_element(documents, pipeline, node_id).map(|element| {
|
||||
let document = documents.find_document(pipeline).unwrap();
|
||||
let realm = enter_realm(&*document);
|
||||
let cx = document.window().get_cx();
|
||||
|
@ -1315,7 +1315,7 @@ pub(crate) fn handle_get_property(
|
|||
match unsafe {
|
||||
get_property_jsval(
|
||||
*cx,
|
||||
node.reflector().get_jsobject(),
|
||||
element.reflector().get_jsobject(),
|
||||
&name,
|
||||
property.handle_mut(),
|
||||
)
|
||||
|
@ -1323,7 +1323,7 @@ pub(crate) fn handle_get_property(
|
|||
Ok(_) => {
|
||||
match jsval_to_webdriver(
|
||||
cx,
|
||||
&node.global(),
|
||||
&element.global(),
|
||||
property.handle(),
|
||||
InRealm::entered(&realm),
|
||||
can_gc,
|
||||
|
@ -1333,7 +1333,7 @@ pub(crate) fn handle_get_property(
|
|||
}
|
||||
},
|
||||
Err(error) => {
|
||||
throw_dom_exception(cx, &node.global(), error, can_gc);
|
||||
throw_dom_exception(cx, &element.global(), error, can_gc);
|
||||
WebDriverJSValue::Undefined
|
||||
},
|
||||
}
|
||||
|
@ -1352,12 +1352,11 @@ pub(crate) fn handle_get_css(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, node_id).map(|node| {
|
||||
let window = node.owner_window();
|
||||
let element = node.downcast::<Element>().unwrap();
|
||||
get_known_element(documents, pipeline, node_id).map(|element| {
|
||||
let window = element.owner_window();
|
||||
String::from(
|
||||
window
|
||||
.GetComputedStyle(element, None)
|
||||
.GetComputedStyle(&element, None)
|
||||
.GetPropertyValue(DOMString::from(name), can_gc),
|
||||
)
|
||||
}),
|
||||
|
@ -1422,15 +1421,15 @@ pub(crate) fn handle_element_click(
|
|||
reply
|
||||
.send(
|
||||
// Step 3
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
// Step 4
|
||||
if let Some(input_element) = node.downcast::<HTMLInputElement>() {
|
||||
if let Some(input_element) = element.downcast::<HTMLInputElement>() {
|
||||
if input_element.input_type() == InputType::File {
|
||||
return Err(ErrorStatus::InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
let Some(container) = get_container(&node) else {
|
||||
let Some(container) = get_container(element.upcast::<Node>()) else {
|
||||
return Err(ErrorStatus::UnknownError);
|
||||
};
|
||||
|
||||
|
@ -1444,7 +1443,7 @@ pub(crate) fn handle_element_click(
|
|||
// TODO: return error if obscured
|
||||
|
||||
// Step 8
|
||||
match node.downcast::<HTMLOptionElement>() {
|
||||
match element.downcast::<HTMLOptionElement>() {
|
||||
Some(option_element) => {
|
||||
// Steps 8.2 - 8.4
|
||||
let event_target = container.upcast::<EventTarget>();
|
||||
|
@ -1488,7 +1487,7 @@ pub(crate) fn handle_element_click(
|
|||
|
||||
Ok(None)
|
||||
},
|
||||
None => Ok(Some(node.unique_id(pipeline))),
|
||||
None => Ok(Some(element.upcast::<Node>().unique_id(pipeline))),
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
@ -1503,12 +1502,8 @@ pub(crate) fn handle_is_enabled(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| match node
|
||||
.downcast::<Element>(
|
||||
) {
|
||||
Some(element) => Ok(element.enabled_state()),
|
||||
None => Err(ErrorStatus::UnknownError),
|
||||
}),
|
||||
get_known_element(documents, pipeline, element_id)
|
||||
.map(|element| element.enabled_state()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -1521,12 +1516,12 @@ pub(crate) fn handle_is_selected(
|
|||
) {
|
||||
reply
|
||||
.send(
|
||||
find_node_by_unique_id(documents, pipeline, element_id).and_then(|node| {
|
||||
if let Some(input_element) = node.downcast::<HTMLInputElement>() {
|
||||
get_known_element(documents, pipeline, element_id).and_then(|element| {
|
||||
if let Some(input_element) = element.downcast::<HTMLInputElement>() {
|
||||
Ok(input_element.Checked())
|
||||
} else if let Some(option_element) = node.downcast::<HTMLOptionElement>() {
|
||||
} else if let Some(option_element) = element.downcast::<HTMLOptionElement>() {
|
||||
Ok(option_element.Selected())
|
||||
} else if node.is::<HTMLElement>() {
|
||||
} else if element.is::<HTMLElement>() {
|
||||
Ok(false) // regular elements are not selectable
|
||||
} else {
|
||||
Err(ErrorStatus::UnknownError)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue