Crates.io | thirtyfour-querier-derive |
lib.rs | thirtyfour-querier-derive |
version | 0.1.4 |
source | src |
created_at | 2022-07-19 06:57:40.259212 |
updated_at | 2022-07-20 15:33:18.38057 |
description | #[derive(Querier)] macro for thirtyfour WebDriver library |
homepage | https://github.com/kotatsuyaki/thirtyfour-querier-derive |
repository | https://github.com/kotatsuyaki/thirtyfour-querier-derive |
max_upload_size | |
id | 628107 |
size | 16,571 |
A #[derive(Querier)]
derive macro for generating the boilerplate code needed to query a
collection of elements by CSS selectors using
thirtyfour.
This library is highly experimental, and is initially developed for internal use.
use thirtyfour::prelude::*;
use thirtyfour_querier_derive::Querier;
#[derive(Querier)]
struct PageElements {
#[querier(css = "#first")]
first: WebElement,
#[querier(css = "#second")]
second: WebElement,
#[querier(all, css = "div")]
all_divs: WebElement,
}
let page_elements = PageElements::query(&driver).await.unwrap();
The impl
blocks generated by the macro uses futures
and thirtyfour
libraries.
Since the a proc macro crate can't export items, these dependencies has to be added manually
by the user.
This may change in future versions.
The #[derive(Querier)]
macro generates an impl
block containing an async constructor for
the structure named query
, with the following signature.
pub async fn query<T: ElementQueryable>(driver: &T)
-> Result<Self, WebDriverError>;
Only structs with named fields are supported.
By default, the queries are performed without waiting.
Use #[querier(wait = num_seconds)]
to add an explicit wait.
Each field of the structure must have a #[querier(...)]
attribute.
The content of the attribute must match the type of the field in this way:
Attribute | Field Type |
---|---|
#[querier(css = "...")] |
WebElement |
#[querier(maybe, css = "...")] |
Option<WebElement> |
#[querier(all, css = "...")] |
Vec<WebElement> |
#[querier(nested, css = "...")] |
(WebElement, Q) |
#[querier(maybe, nested, css = "...")] |
Option<(WebElement, Q)> |
#[querier(all, nested, css = "...")] |
Vec<(WebElement, Q)> |
The type Q
in the table can be any type that also has #[derive(Querier)]
.
use thirtyfour_querier_derive::Querier;
use thirtyfour::prelude::*;
const HTML: &str = r#"
data:text/html;charset=utf-8,<html>
<body>
<div id="single-element"></div>
<div class="many-elements">
<div class="nested-element"></div>
<div class="nested-element"></div>
</div>
<div class="many-elements">
<div class="nested-element"></div>
<div class="nested-element"></div>
</div>
<div class="not-queried nested-element"></div>
</body>
</html>
"#;
#[derive(Debug, Querier)]
#[allow(dead_code)]
struct Page {
#[querier(css = "#single-element")]
single_elem: WebElement,
#[querier(wait = 5, css = "#single-element")]
single_elem_with_wait: WebElement,
#[querier(maybe, css = "#missing-element")]
missing_elem: Option<WebElement>,
#[querier(all, css = ".many-elements")]
many_elems: Vec<WebElement>,
#[querier(all, nested, css = ".many-elements")]
many_elems_nested: Vec<(WebElement, SubElement)>,
}
#[derive(Debug, Querier)]
struct SubElement {
#[querier(all, css = ".nested-element")]
nested_elems: Vec<WebElement>,
}
#[tokio::main]
async fn main() {
let driver = WebDriver::new("http://localhost:9100", DesiredCapabilities::chrome())
.await
.unwrap();
// Load the html string
driver.get(HTML).await.unwrap();
// Query the elements specified in `struct Page`
let page = Page::query(&driver).await.unwrap();
// Count number of `.nested-element` within `many-element`s (should be 4)
let mut nest_elem_count = 0;
for (_, elem) in page.many_elems_nested {
nest_elem_count += elem.nested_elems.len();
}
assert_eq!(
nest_elem_count, 4,
"Number of nested-element within many-element is 4"
);
}