use std::time::Duration;
use drission::prelude::*;
const PAGE: &str = concat!("file://", env!("CARGO_MANIFEST_DIR"), "/examples/1.html");
const USERNAME: &str = "自动化测试机器人";
const JOB: &str = "dev"; const TOOL: &str = "Playwright";
const PAINPOINTS: &[&str] = &["dynamic_id", "verification_code"];
const FEEDBACK: &str = "drission-rs 填表链路验证:输入/下拉/单选/多选/文本域/分步提交。";
#[tokio::main]
async fn main() -> drission::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "warn".into()),
)
.init();
let headless = std::env::var("HL").map(|v| v != "0").unwrap_or(true);
let browser = Browser::launch(BrowserOptions::new().headless(headless)).await?;
let tab = browser.latest_tab().await?;
println!("打开本地表单: {PAGE}");
tab.get(PAGE).await?;
let _ = tab
.run_js("window.alert=function(){};window.confirm=function(){return true};window.prompt=function(){return ''};true")
.await;
println!("\n[第1步] 填姓名 + 选职业");
tab.ele("#username").await?.input(USERNAME).await?;
tab.ele("#job").await?.select_value(JOB).await?;
let got_name = tab.ele("#username").await?.value().await?;
let got_job = tab.ele("#job").await?.value().await?;
println!(" 姓名={got_name:?} 职业={got_job:?}");
next(&tab).await?;
println!("[第2步] 选工具(单选 {TOOL})");
let radio = format!("css:input[name=\"tool\"][value=\"{TOOL}\"]");
ensure_checked(&tab, &radio).await?;
next(&tab).await?;
println!("[第3步] 勾选难点(多选 {PAINPOINTS:?})");
for v in PAINPOINTS {
let cb = format!("css:input[name=\"painpoint\"][value=\"{v}\"]");
ensure_checked(&tab, &cb).await?;
}
next(&tab).await?;
println!("[第4步] 写反馈并提交");
let fb = tab.ele("#feedback").await?;
fb.clear().await?; fb.input(FEEDBACK).await?;
next(&tab).await?; tokio::time::sleep(Duration::from_millis(500)).await;
let result = tab
.run_js("document.getElementById('result-display').textContent")
.await?
.as_str()
.unwrap_or_default()
.to_string();
println!("\n页面生成的提交结果:\n{result}");
let mut checks: Vec<(&str, bool)> = vec![
("姓名", result.contains(USERNAME)),
("职业=研发", result.contains("研发") || result.contains(JOB)),
("单选=Playwright", result.contains(TOOL)),
("反馈备注", result.contains("drission-rs 填表链路验证")),
];
for v in PAINPOINTS {
checks.push(("多选含", result.contains(v)));
}
let ok = checks.iter().all(|(_, b)| *b);
println!("\n校验:");
for (name, b) in &checks {
println!(" {} {name}", if *b { "✅" } else { "❌" });
}
println!(
"\n{}",
if ok {
"✅ 填表端到端验证通过"
} else {
"❌ 有字段未通过"
}
);
browser.quit().await?;
if ok {
Ok(())
} else {
Err(Error::Other("填表校验失败".into()))
}
}
async fn next(tab: &Tab) -> Result<()> {
tab.ele("#next-btn").await?.click().await?;
tokio::time::sleep(Duration::from_millis(400)).await;
Ok(())
}
async fn ensure_checked(tab: &Tab, selector: &str) -> Result<()> {
let el = tab.ele(selector).await?;
el.click().await.ok();
tokio::time::sleep(Duration::from_millis(150)).await;
if el.is_checked().await.unwrap_or(false) {
println!(" {selector} → 点击选中 ✓");
return Ok(());
}
el.set_checked(true).await?;
println!(" {selector} → set_checked 兜底 ✓");
Ok(())
}