use std::time::Duration;
use playwright_cdp::options::LaunchOptions;
use playwright_cdp::Playwright;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
async fn http_server(body: &'static str) -> String {
let l = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let port = l.local_addr().unwrap().port();
tokio::spawn(async move {
loop {
let Ok((mut s, _)) = l.accept().await else { break };
tokio::spawn(async move {
let mut buf = [0u8; 4096];
let _ = s.read(&mut buf).await;
let resp = format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
body.len(),
body
);
let _ = s.write_all(resp.as_bytes()).await;
let _ = s.flush().await;
});
}
});
format!("http://127.0.0.1:{port}/")
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let _ = tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "playwright_cdp=info".into()),
)
.try_init();
let url1 = http_server("<html><head><title>expect_response target</title></head><body><h1>one</h1></body></html>").await;
let url2 = http_server("<html><head><title>expect_event target</title></head><body><h1>two</h1></body></html>").await;
let browser = Playwright::launch()
.await?
.chromium()
.launch_with_options(LaunchOptions::default())
.await?;
println!("browser version: {}", browser.version().await?);
let page = browser.new_page().await?;
let (resp, nav1) = tokio::join!(
page.expect_response("127.0.0.1", Some(Duration::from_secs(5))),
page.goto(&url1, None),
);
nav1?;
let resp = resp?;
println!("expect_response matched: status={} url={}", resp.status(), resp.url());
assert_eq!(resp.status(), 200);
let (params, nav2) = tokio::join!(
page.expect_event("Page.loadEventFired", Some(Duration::from_secs(5))),
page.goto(&url2, None),
);
nav2?;
let _params = params?;
println!("expect_event matched: Page.loadEventFired (params keys present)");
let (msg, eval) = tokio::join!(
page.expect_console_message("hello", Some(Duration::from_secs(5))),
page.evaluate::<()>("console.log('hello world')"),
);
eval?;
let msg = msg?;
println!(
"expect_console_message matched: type={} text={:?}",
msg.r#type(),
msg.text()
);
assert!(msg.text().contains("hello"));
let (popup, eval) = tokio::join!(
page.expect_popup(Some(Duration::from_secs(5))),
page.evaluate::<()>("window.open('about:blank')"),
);
eval?;
match popup {
Ok(popup) => {
let popup_url = popup.url().await.unwrap_or_default();
println!("expect_popup matched: popup url={popup_url}");
popup.close().await.ok();
}
Err(e) => {
println!("expect_popup did not match within timeout (polling approximation): {e}");
}
}
println!("all event-waiting demos completed.");
browser.close().await?;
println!("done.");
Ok(())
}