mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #23820 - georgeroman:link_text_selectors_for_find_element_wd_commands, r=jdm
Implement Link and PartialLink text selectors for FindElement and related WebDriver commands <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> - [X] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23820) <!-- Reviewable:end -->
This commit is contained in:
commit
dcce668d3a
8 changed files with 183 additions and 102 deletions
|
@ -2019,6 +2019,15 @@ impl ScriptThread {
|
|||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::FindElementLinkText(selector, partial, reply) => {
|
||||
webdriver_handlers::handle_find_element_link_text(
|
||||
&*documents,
|
||||
pipeline_id,
|
||||
selector,
|
||||
partial,
|
||||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::FindElementTagName(selector, reply) => {
|
||||
webdriver_handlers::handle_find_element_tag_name(
|
||||
&*documents,
|
||||
|
@ -2035,6 +2044,15 @@ impl ScriptThread {
|
|||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::FindElementsLinkText(selector, partial, reply) => {
|
||||
webdriver_handlers::handle_find_elements_link_text(
|
||||
&*documents,
|
||||
pipeline_id,
|
||||
selector,
|
||||
partial,
|
||||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::FindElementsTagName(selector, reply) => {
|
||||
webdriver_handlers::handle_find_elements_tag_name(
|
||||
&*documents,
|
||||
|
@ -2052,6 +2070,19 @@ impl ScriptThread {
|
|||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::FindElementElementLinkText(
|
||||
selector,
|
||||
element_id,
|
||||
partial,
|
||||
reply,
|
||||
) => webdriver_handlers::handle_find_element_element_link_text(
|
||||
&*documents,
|
||||
pipeline_id,
|
||||
element_id,
|
||||
selector,
|
||||
partial,
|
||||
reply,
|
||||
),
|
||||
WebDriverScriptCommand::FindElementElementTagName(selector, element_id, reply) => {
|
||||
webdriver_handlers::handle_find_element_element_tag_name(
|
||||
&*documents,
|
||||
|
@ -2070,6 +2101,19 @@ impl ScriptThread {
|
|||
reply,
|
||||
)
|
||||
},
|
||||
WebDriverScriptCommand::FindElementElementsLinkText(
|
||||
selector,
|
||||
element_id,
|
||||
partial,
|
||||
reply,
|
||||
) => webdriver_handlers::handle_find_element_elements_link_text(
|
||||
&*documents,
|
||||
pipeline_id,
|
||||
element_id,
|
||||
selector,
|
||||
partial,
|
||||
reply,
|
||||
),
|
||||
WebDriverScriptCommand::FindElementElementsTagName(selector, element_id, reply) => {
|
||||
webdriver_handlers::handle_find_element_elements_tag_name(
|
||||
&*documents,
|
||||
|
|
|
@ -24,6 +24,7 @@ use crate::dom::htmliframeelement::HTMLIFrameElement;
|
|||
use crate::dom::htmlinputelement::HTMLInputElement;
|
||||
use crate::dom::htmloptionelement::HTMLOptionElement;
|
||||
use crate::dom::node::{window_from_node, Node, ShadowIncluding};
|
||||
use crate::dom::nodelist::NodeList;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::xmlserializer::XMLSerializer;
|
||||
use crate::script_thread::Documents;
|
||||
|
@ -58,6 +59,50 @@ fn find_node_by_unique_id(
|
|||
})
|
||||
}
|
||||
|
||||
fn matching_links<'a>(
|
||||
links: &'a NodeList,
|
||||
link_text: String,
|
||||
partial: bool,
|
||||
) -> impl Iterator<Item = String> + 'a {
|
||||
links
|
||||
.iter()
|
||||
.filter(move |node| {
|
||||
let content = node
|
||||
.GetTextContent()
|
||||
.map_or("".to_owned(), String::from)
|
||||
.trim()
|
||||
.to_owned();
|
||||
if partial {
|
||||
content.contains(&link_text)
|
||||
} else {
|
||||
content == link_text
|
||||
}
|
||||
})
|
||||
.map(|node| node.upcast::<Node>().unique_id())
|
||||
}
|
||||
|
||||
fn all_matching_links(
|
||||
root_node: &Node,
|
||||
link_text: String,
|
||||
partial: bool,
|
||||
) -> Result<Vec<String>, ()> {
|
||||
root_node
|
||||
.query_selector_all(DOMString::from("a"))
|
||||
.map_err(|_| ())
|
||||
.map(|nodes| matching_links(&nodes, link_text, partial).collect())
|
||||
}
|
||||
|
||||
fn first_matching_link(
|
||||
root_node: &Node,
|
||||
link_text: String,
|
||||
partial: bool,
|
||||
) -> Result<Option<String>, ()> {
|
||||
root_node
|
||||
.query_selector_all(DOMString::from("a"))
|
||||
.map_err(|_| ())
|
||||
.map(|nodes| matching_links(&nodes, link_text, partial).take(1).next())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub unsafe fn jsval_to_webdriver(cx: *mut JSContext, val: HandleValue) -> WebDriverJSResult {
|
||||
if val.get().is_undefined() {
|
||||
|
@ -182,6 +227,20 @@ pub fn handle_find_element_css(
|
|||
reply.send(node_id).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_element_link_text(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
selector: String,
|
||||
partial: bool,
|
||||
reply: IpcSender<Result<Option<String>, ()>>,
|
||||
) {
|
||||
let node_id = documents
|
||||
.find_document(pipeline)
|
||||
.ok_or(())
|
||||
.and_then(|doc| first_matching_link(&doc.upcast::<Node>(), selector.clone(), partial));
|
||||
reply.send(node_id).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_element_tag_name(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
|
@ -223,6 +282,20 @@ pub fn handle_find_elements_css(
|
|||
reply.send(node_ids).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_elements_link_text(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
selector: String,
|
||||
partial: bool,
|
||||
reply: IpcSender<Result<Vec<String>, ()>>,
|
||||
) {
|
||||
let node_ids = documents
|
||||
.find_document(pipeline)
|
||||
.ok_or(())
|
||||
.and_then(|doc| all_matching_links(&doc.upcast::<Node>(), selector.clone(), partial));
|
||||
reply.send(node_ids).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_elements_tag_name(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
|
@ -259,6 +332,20 @@ pub fn handle_find_element_element_css(
|
|||
reply.send(node_id).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_element_element_link_text(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
element_id: String,
|
||||
selector: String,
|
||||
partial: bool,
|
||||
reply: IpcSender<Result<Option<String>, ()>>,
|
||||
) {
|
||||
let node_id = find_node_by_unique_id(documents, pipeline, element_id)
|
||||
.ok_or(())
|
||||
.and_then(|node| first_matching_link(&node, selector.clone(), partial));
|
||||
reply.send(node_id).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_element_element_tag_name(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
|
@ -301,6 +388,20 @@ pub fn handle_find_element_elements_css(
|
|||
reply.send(node_ids).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_element_elements_link_text(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
element_id: String,
|
||||
selector: String,
|
||||
partial: bool,
|
||||
reply: IpcSender<Result<Vec<String>, ()>>,
|
||||
) {
|
||||
let node_ids = find_node_by_unique_id(documents, pipeline, element_id)
|
||||
.ok_or(())
|
||||
.and_then(|node| all_matching_links(&node, selector.clone(), partial));
|
||||
reply.send(node_ids).unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_find_element_elements_tag_name(
|
||||
documents: &Documents,
|
||||
pipeline: PipelineId,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue