mirror of
https://github.com/servo/servo.git
synced 2025-06-13 10:54:29 +00:00
Implement link and partial link text selectors for FindElement and related WebDriver commands
This commit is contained in:
parent
75275965f0
commit
0ec852eb41
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,
|
||||
|
|
|
@ -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>>),
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
|
|
@ -2,72 +2,27 @@
|
|||
[test_xhtml_namespace[css selector-#linkText\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_element_partial_link_text[<a href=#>partial link&text</a>-k&t\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_htmldocument[xpath-/html\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_element_partial_link_text[<a href=#> partial link text </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&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=#> link text </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
|
||||
|
||||
|
|
|
@ -2,75 +2,30 @@
|
|||
[test_xhtml_namespace[css selector-#linkText\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_element_partial_link_text[<a href=#>partial link&text</a>-k&t\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_element_partial_link_text[<a href=#> partial link text </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_parent_htmldocument]
|
||||
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&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_parent_of_document_node_errors]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_element_link_text[<a href=#> link text </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
|
||||
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
[test_xhtml_namespace[xpath-//*[name()='a'\]\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements[link text-full link text\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT\]]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -35,9 +32,6 @@
|
|||
[test_xhtml_namespace[link text-full link text\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements[partial link text-link text\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements_partial_link_text[<a href=#>partial link text</a>-k t\]]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
[test_xhtml_namespace[css selector-#linkText\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements[link text-full link text\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements_link_text[<a href=# style='text-transform: uppercase'>link text</a>-LINK TEXT\]]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -35,9 +32,6 @@
|
|||
[test_xhtml_namespace[link text-full link text\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements[partial link text-link text\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_find_elements_partial_link_text[<a href=#>partial link text</a>-k t\]]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue