#![cfg(feature = "integration-tests")]
#![allow(clippy::panic, clippy::unwrap_used)]
use std::time::Duration;
use serial_test::serial;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
use zendriver::Browser;
async fn fixture_with_html(html: &str) -> MockServer {
let mock = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/"))
.respond_with(
ResponseTemplate::new(200).set_body_raw(html.as_bytes().to_vec(), "text/html"),
)
.mount(&mock)
.await;
mock
}
#[tokio::test]
#[serial]
#[ignore] async fn include_frames_finds_element_two_iframes_deep() {
let mock = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/inner"))
.respond_with(ResponseTemplate::new(200).set_body_raw(
br#"<!doctype html><html><body><div id="deep">found</div></body></html>"#.to_vec(),
"text/html",
))
.mount(&mock)
.await;
Mock::given(method("GET"))
.and(path("/mid"))
.respond_with(ResponseTemplate::new(200).set_body_raw(
br#"<!doctype html><html><body><iframe src="/inner"></iframe></body></html>"#.to_vec(),
"text/html",
))
.mount(&mock)
.await;
Mock::given(method("GET"))
.and(path("/"))
.respond_with(ResponseTemplate::new(200).set_body_raw(
br#"<!doctype html><html><body><iframe id="mid" src="/mid"></iframe></body></html>"#
.to_vec(),
"text/html",
))
.mount(&mock)
.await;
let browser = Browser::builder().headless(true).launch().await.unwrap();
let tab = browser.main_tab();
tab.goto(&mock.uri()).await.unwrap();
tab.wait_for_load().await.unwrap();
let deadline = std::time::Instant::now() + Duration::from_secs(10);
loop {
let frames = tab.frames().await.unwrap();
let child_count = frames.iter().filter(|f| !f.is_main()).count();
if child_count >= 2 {
break;
}
if std::time::Instant::now() >= deadline {
panic!(
"expected at least 2 child frames within 10s; saw {} (total {})",
child_count,
frames.len()
);
}
tokio::time::sleep(Duration::from_millis(50)).await;
}
let el = tab
.find()
.css("#deep")
.include_frames()
.one()
.await
.expect("element nested two iframes deep must be found with include_frames()");
assert_eq!(
el.inner_text().await.unwrap(),
"found",
"#deep should contain 'found'"
);
let all = tab
.find_all()
.css("#deep")
.include_frames()
.many()
.await
.unwrap();
assert_eq!(all.len(), 1, "exactly one #deep element across all frames");
browser.close().await.unwrap();
}
#[tokio::test]
#[serial]
#[ignore]
async fn predicate_finds_by_tag_attr_text() {
let mock = fixture_with_html(
r#"<!doctype html><html><body>
<button class="primary active" data-id="4821">Buy now</button>
</body></html>"#,
)
.await;
let browser = Browser::builder().headless(true).launch().await.unwrap();
let tab = browser.main_tab();
tab.goto(&mock.uri()).await.unwrap();
tab.wait_for_load().await.unwrap();
let el = tab
.find()
.tag("button")
.attr_contains("class", "active")
.attr_regex("data-id", r"^\d{4}$")
.containing_text("Buy")
.one()
.await
.unwrap();
assert!(
el.inner_text().await.unwrap().contains("Buy"),
"button text should contain 'Buy'"
);
browser.close().await.unwrap();
}
#[tokio::test]
#[serial]
#[ignore]
async fn select_all_returns_all_matches() {
let mock = fixture_with_html(
r#"<!doctype html><html><body>
<ul id="list">
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
</body></html>"#,
)
.await;
let browser = Browser::builder().headless(true).launch().await.unwrap();
let tab = browser.main_tab();
tab.goto(&mock.uri()).await.unwrap();
tab.wait_for_load().await.unwrap();
let items = tab.select_all("ul li").await.unwrap();
assert_eq!(items.len(), 3, "expected 3 <li> elements");
browser.close().await.unwrap();
}
#[tokio::test]
#[serial]
#[ignore]
async fn mixing_predicate_and_css_errors() {
let mock = fixture_with_html(r#"<!doctype html><html><body><div>x</div></body></html>"#).await;
let browser = Browser::builder().headless(true).launch().await.unwrap();
let tab = browser.main_tab();
tab.goto(&mock.uri()).await.unwrap();
tab.wait_for_load().await.unwrap();
let err = tab.find().css("div").tag("span").one().await.unwrap_err();
assert!(
matches!(err, zendriver::ZendriverError::ConflictingSelectors),
"expected ConflictingSelectors, got {err:?}"
);
browser.close().await.unwrap();
}