Skip to content

Commit

Permalink
Implement link and partial link text selectors for FindElement and re…
Browse files Browse the repository at this point in the history
…lated WebDriver commands
  • Loading branch information
georgeroman committed Jul 23, 2019
1 parent 7527596 commit 0ec852e
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 102 deletions.
44 changes: 44 additions & 0 deletions components/script/script_thread.rs
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
101 changes: 101 additions & 0 deletions components/script/webdriver_handlers.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions components/script_traits/webdriver_msg.rs
Expand Up @@ -25,12 +25,16 @@ pub enum WebDriverScriptCommand {
ExecuteScript(String, IpcSender<WebDriverJSResult>),
ExecuteAsyncScript(String, IpcSender<WebDriverJSResult>),
FindElementCSS(String, IpcSender<Result<Option<String>, ()>>),
FindElementLinkText(String, bool, IpcSender<Result<Option<String>, ()>>),
FindElementTagName(String, IpcSender<Result<Option<String>, ()>>),
FindElementsCSS(String, IpcSender<Result<Vec<String>, ()>>),
FindElementsLinkText(String, bool, IpcSender<Result<Vec<String>, ()>>),
FindElementsTagName(String, IpcSender<Result<Vec<String>, ()>>),
FindElementElementCSS(String, String, IpcSender<Result<Option<String>, ()>>),
FindElementElementLinkText(String, String, bool, IpcSender<Result<Option<String>, ()>>),
FindElementElementTagName(String, String, IpcSender<Result<Option<String>, ()>>),
FindElementElementsCSS(String, String, IpcSender<Result<Vec<String>, ()>>),
FindElementElementsLinkText(String, String, bool, IpcSender<Result<Vec<String>, ()>>),
FindElementElementsTagName(String, String, IpcSender<Result<Vec<String>, ()>>),
FocusElement(String, IpcSender<Result<(), ()>>),
GetActiveElement(IpcSender<Option<String>>),
Expand Down
34 changes: 34 additions & 0 deletions components/webdriver_server/lib.rs
Expand Up @@ -811,6 +811,14 @@ impl Handler {
let cmd = WebDriverScriptCommand::FindElementCSS(parameters.value.clone(), sender);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementLinkText(
parameters.value.clone(),
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::TagName => {
let cmd =
WebDriverScriptCommand::FindElementTagName(parameters.value.clone(), sender);
Expand Down Expand Up @@ -914,6 +922,14 @@ impl Handler {
let cmd = WebDriverScriptCommand::FindElementsCSS(parameters.value.clone(), sender);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementsLinkText(
parameters.value.clone(),
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::TagName => {
let cmd =
WebDriverScriptCommand::FindElementsTagName(parameters.value.clone(), sender);
Expand Down Expand Up @@ -961,6 +977,15 @@ impl Handler {
);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementElementLinkText(
parameters.value.clone(),
element.id.clone(),
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::TagName => {
let cmd = WebDriverScriptCommand::FindElementElementTagName(
parameters.value.clone(),
Expand Down Expand Up @@ -1008,6 +1033,15 @@ impl Handler {
);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::LinkText | LocatorStrategy::PartialLinkText => {
let cmd = WebDriverScriptCommand::FindElementElementsLinkText(
parameters.value.clone(),
element.id.clone(),
parameters.using == LocatorStrategy::PartialLinkText,
sender,
);
self.browsing_context_script_command(cmd)?;
},
LocatorStrategy::TagName => {
let cmd = WebDriverScriptCommand::FindElementElementsTagName(
parameters.value.clone(),
Expand Down
45 changes: 0 additions & 45 deletions tests/wpt/metadata/webdriver/tests/find_element/find.py.ini
Expand Up @@ -2,72 +2,27 @@
[test_xhtml_namespace[css selector-#linkText\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=#>partial link&amp;text</a>-k&t\]]
expected: FAIL

[test_htmldocument[xpath-/html\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=#>&nbsp;partial link text&nbsp;</a>-link\]]
expected: FAIL

[test_find_element_link_text[<a href=#>link<br>text</a>-link\ntext\]]
expected: FAIL

[test_xhtml_namespace[xpath-//*[name()='a'\]\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=# style='text-transform: uppercase'>partial link text</a>-LINK\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=#>partial link text</a>-link\]]
expected: FAIL

[test_xhtml_namespace[tag name-a\]]
expected: FAIL

[test_find_element_link_text[<a href=#>link&amp;text</a>-link&text\]]
expected: FAIL

[test_find_element[partial link text-link text\]]
expected: FAIL

[test_find_element_link_text[<a href=#>LINK TEXT</a>-LINK TEXT\]]
expected: FAIL

[test_xhtml_namespace[link text-full link text\]]
expected: FAIL

[test_find_element[link text-full link text\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=#>partial link<br>text</a>-k\nt\]]
expected: FAIL

[test_find_element_link_text[<a href=#>&nbsp;link text&nbsp;</a>-link text\]]
expected: FAIL

[test_find_element_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT\]]
expected: FAIL

[test_no_element[css selector-#wontExist\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=#>PARTIAL LINK TEXT</a>-LINK\]]
expected: FAIL

[test_find_element_partial_link_text[<a href=#>partial link text</a>-k t\]]
expected: FAIL

[test_xhtml_namespace[partial link text-link text\]]
expected: FAIL

[test_find_element[xpath-//a\]]
expected: FAIL

[test_find_element_link_text[<a href=#>link text</a>-link text\]]
expected: FAIL

[test_no_browsing_context]
expected: ERROR

0 comments on commit 0ec852e

Please sign in to comment.