aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/webdriver_handlers.rs
diff options
context:
space:
mode:
authorGeorge Roman <george.roman.99@gmail.com>2019-06-20 17:53:02 +0300
committerGeorge Roman <george.roman.99@gmail.com>2019-07-23 09:55:47 +0300
commit0ec852eb4131f39cab66f13321c18a425c66caad (patch)
treea6c72ddcf0b8b9609e678266c54e1ab46572e23e /components/script/webdriver_handlers.rs
parent75275965f08d7b34be73254b7b4df9135cc8fcf8 (diff)
downloadservo-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.rs101
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,