diff options
author | George Roman <george.roman.99@gmail.com> | 2019-06-20 17:53:02 +0300 |
---|---|---|
committer | George Roman <george.roman.99@gmail.com> | 2019-07-23 09:55:47 +0300 |
commit | 0ec852eb4131f39cab66f13321c18a425c66caad (patch) | |
tree | a6c72ddcf0b8b9609e678266c54e1ab46572e23e /components/script/webdriver_handlers.rs | |
parent | 75275965f08d7b34be73254b7b4df9135cc8fcf8 (diff) | |
download | servo-0ec852eb4131f39cab66f13321c18a425c66caad.tar.gz servo-0ec852eb4131f39cab66f13321c18a425c66caad.zip |
Implement link and partial link text selectors for FindElement and related WebDriver commands
Diffstat (limited to 'components/script/webdriver_handlers.rs')
-rw-r--r-- | components/script/webdriver_handlers.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index c960878f60d..03b61875b3b 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -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, |