use std::sync::Arc;
use xa11y::*;
pub fn app_tree() -> Element {
for attempt in 0..3 {
match App::from_name(xa11y::provider().unwrap(), "xa11y") {
Ok(app) => return app.elements().expect("Failed to snapshot app tree"),
Err(_) if attempt < 2 => {
std::thread::sleep(std::time::Duration::from_millis(200));
}
Err(e) => panic!("Could not find test app after retries: {}", e),
}
}
unreachable!()
}
pub fn query(root: &Element, selector: &str) -> Result<Vec<Element>> {
let indices = root.tree().query_indices(selector)?;
Ok(indices
.into_iter()
.map(|idx| Element::new(Arc::clone(root.tree()), idx))
.collect())
}
pub fn one(root: &Element, selector: &str) -> Element {
let results = query(root, selector)
.unwrap_or_else(|e| panic!("Selector '{}' failed: {}. Tree:\n{}", selector, e, root));
assert!(
results.len() == 1,
"Selector '{}' matched {} elements (expected 1). Tree:\n{}",
selector,
results.len(),
root
);
results[0].clone()
}
pub fn named(root: &Element, substring: &str) -> Element {
let selector = format!("[name*=\"{}\"]", substring);
let results = query(root, &selector)
.unwrap_or_else(|e| panic!("Selector '{}' failed: {}. Tree:\n{}", selector, e, root));
assert!(
!results.is_empty(),
"No element with name containing '{}'. Tree:\n{}",
substring,
root
);
results[0].clone()
}
pub fn try_act(element: &Element, action: Action) -> Result<()> {
try_act_with(element, action, None)
}
pub fn try_act_with(element: &Element, action: Action, data: Option<ActionData>) -> Result<()> {
xa11y::perform_action(element, action, data)
}
pub fn act(element: &Element, action: Action) -> Element {
act_with(element, action, None)
}
pub fn act_with(element: &Element, action: Action, data: Option<ActionData>) -> Element {
try_act_with(element, action, data)
.unwrap_or_else(|e| panic!("Action {:?} failed: {}", action, e));
std::thread::sleep(std::time::Duration::from_millis(100));
app_tree()
}