use std::time::Duration;
use playwright_cdp::options::LaunchOptions;
use playwright_cdp::types::Viewport;
use playwright_cdp::{expect, Playwright};
#[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 browser = Playwright::launch()
.await?
.chromium()
.launch_with_options(LaunchOptions::default())
.await?;
println!("browser version: {}", browser.version().await?);
let page = browser.new_page().await?;
page.set_viewport_size(Viewport::new(800, 600)).await?;
page.set_content(
r#"
<!doctype html>
<html><head><title>Assertions Extended</title></head>
<body>
<!-- inline-styled element for to_have_css / to_have_css_regex -->
<div id="colored" style="color: red">colored box</div>
<!-- multi-class element for to_have_class / to_have_class_regex -->
<div id="btn" class="btn primary">click me</div>
<!-- a focusable input; we focus() it before asserting to_be_focused -->
<input id="field" type="text" />
<!-- text carrying a number for to_have_text_regex -->
<p id="order">order #42857 confirmed</p>
<!-- an attribute whose value mixes letters+digits, for
to_have_attribute_regex -->
<span id="tagged" data-code="abc123">tagged</span>
<!-- a stable, fully-specified block for to_have_screenshot -->
<div id="badge" style="display:inline-block;width:120px;height:40px;
background:#3366cc;color:#ffffff;line-height:40px;text-align:center;
font-family:sans-serif;font-size:14px;">STABLE</div>
</body></html>
"#,
)
.await?;
let t = Duration::from_millis(2000);
expect(page.locator("#colored"))
.with_timeout(t)
.to_have_css("color", "rgb(255, 0, 0)")
.await?;
println!("to_have_css(#colored, color, rgb(255, 0, 0)) OK");
expect(page.locator("#colored"))
.with_timeout(t)
.to_have_css_regex("color", r"^rgb\(255,\s*0,\s*0\)$")
.await?;
println!("to_have_css_regex(#colored, color, ^rgb(255, 0, 0)$) OK");
expect(page.locator("#btn"))
.with_timeout(t)
.to_have_class("btn primary")
.await?;
println!("to_have_class(#btn, \"btn primary\") OK");
expect(page.locator("#btn"))
.with_timeout(t)
.to_have_class_regex(r"\bprimary\b")
.await?;
println!("to_have_class_regex(#btn, \\bprimary\\b) OK");
page.locator("#field").focus().await?;
expect(page.locator("#field"))
.with_timeout(t)
.to_be_focused()
.await?;
println!("to_be_focused(#field) after focus() OK");
expect(page.locator("#order"))
.with_timeout(t)
.to_have_text_regex(r"#\d+")
.await?;
println!("to_have_text_regex(#order, #\\d+) OK");
expect(page.locator("#tagged"))
.with_timeout(t)
.to_have_attribute_regex("data-code", r"\d+")
.await?;
println!("to_have_attribute_regex(#tagged, data-code, \\d+) OK");
let mut baseline = std::env::temp_dir();
baseline.push("pwc-assertions-extended-badge");
let baseline_path = baseline.to_string_lossy().into_owned();
println!("screenshot baseline path: {baseline_path}.png");
expect(page.locator("#badge"))
.with_timeout(t)
.to_have_screenshot(&baseline_path, None)
.await?;
println!("to_have_screenshot(#badge) first pass (baseline written) OK");
expect(page.locator("#badge"))
.with_timeout(t)
.to_have_screenshot(&baseline_path, None)
.await?;
println!("to_have_screenshot(#badge) second pass (matched baseline) OK");
let _ = std::fs::remove_file(format!("{baseline_path}.png"));
let _ = std::fs::remove_file(format!("{baseline_path}-actual.png"));
println!("all extended assertions passed.");
browser.close().await?;
println!("done.");
Ok(())
}