use crate::DominatorTestingError;
use std::fmt::{Debug, Formatter};
use std::time::Duration;
use web_sys::NodeList;
pub enum Condition {
AtLeastCount(u32),
AtMostCount(u32),
Fn(Box<dyn Fn(NodeList) -> bool>),
}
impl Debug for Condition {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Condition::AtLeastCount(count) => write!(f, "AtLeastCount({})", count),
Condition::AtMostCount(count) => write!(f, "AtMostCount({})", count),
Condition::Fn(_) => write!(f, "Fn"),
}
}
}
pub async fn wait_for_query_selector_all_condition(
query: &str,
condition: Condition,
timeout: Duration,
) -> Result<(), DominatorTestingError> {
barrier(
move || {
let elements = web_sys::window()
.unwrap()
.document()
.unwrap()
.query_selector_all(query)
.unwrap();
match &condition {
Condition::AtLeastCount(count) => elements.length() >= *count,
Condition::AtMostCount(count) => elements.length() <= *count,
Condition::Fn(fn_) => fn_(elements),
}
},
timeout,
format!("query: {query}"),
)
.await
}
pub async fn barrier(
mut expr: impl FnMut() -> bool,
timeout: Duration,
label: impl ToString,
) -> Result<(), DominatorTestingError> {
let started_at = web_time::Instant::now();
loop {
crate::async_yield().await;
if expr() {
break Ok(());
}
if started_at.elapsed() > timeout {
break Err(DominatorTestingError::BarrierTimeOut(label.to_string()));
}
}
}