#![allow(
clippy::too_many_lines,
clippy::doc_markdown,
clippy::uninlined_format_args,
clippy::unwrap_used,
clippy::expect_used,
clippy::needless_pass_by_value
)]
use super::client::McpClient;
const BLANK_HTML: &str = "<!doctype html><html><body><h1>x</h1></body></html>";
fn urlencoding(s: &str) -> String {
s.replace(' ', "%20").replace('#', "%23").replace('"', "%22")
}
pub fn test_console_message_primitives(c: &mut McpClient) {
c.nav_url(&format!("data:text/html,{}", urlencoding(BLANK_HTML)));
let script = r#"
const waiter = page.waitForEvent("console", 5000);
await page.evaluate(() => console.log("hello", 42));
const msg = await waiter;
return {
type: msg.type(),
text: msg.text(),
argsLen: msg.args().length,
};
"#;
let v = c.script_value(script);
assert_eq!(v["type"].as_str(), Some("log"), "type should be 'log': {v}");
let text = v["text"].as_str().unwrap_or("");
assert!(
text.contains("hello") && text.contains("42"),
"text should include both primitive args: {v}"
);
assert_eq!(v["argsLen"].as_u64(), Some(2), "should report 2 args: {v}");
}
pub fn test_console_message_warn_maps_to_warning(c: &mut McpClient) {
c.nav_url(&format!("data:text/html,{}", urlencoding(BLANK_HTML)));
let script = r#"
const waiter = page.waitForEvent("console", 5000);
await page.evaluate(() => console.warn("careful"));
const msg = await waiter;
return { type: msg.type(), text: msg.text() };
"#;
let v = c.script_value(script);
assert_eq!(
v["type"].as_str(),
Some("warning"),
"console.warn should surface as type 'warning' (Playwright parity): {v}"
);
assert!(
v["text"].as_str().unwrap_or("").contains("careful"),
"warn text should include the payload: {v}"
);
}
pub fn test_console_message_error_type(c: &mut McpClient) {
c.nav_url(&format!("data:text/html,{}", urlencoding(BLANK_HTML)));
let script = r#"
const waiter = page.waitForEvent("console", 5000);
await page.evaluate(() => console.error("boom"));
const msg = await waiter;
return { type: msg.type(), text: msg.text() };
"#;
let v = c.script_value(script);
assert_eq!(
v["type"].as_str(),
Some("error"),
"console.error should surface as type 'error': {v}"
);
assert!(
v["text"].as_str().unwrap_or("").contains("boom"),
"error text should include the payload: {v}"
);
}
pub fn test_console_message_location_shape(c: &mut McpClient) {
c.nav_url(&format!("data:text/html,{}", urlencoding(BLANK_HTML)));
let script = r#"
const waiter = page.waitForEvent("console", 5000);
await page.evaluate(() => console.log("loc-check"));
const msg = await waiter;
const loc = msg.location();
return {
url: loc.url,
line: loc.lineNumber,
column: loc.columnNumber,
};
"#;
let v = c.script_value(script);
assert!(
v.get("url").is_some() && v.get("line").is_some() && v.get("column").is_some(),
"location object should have url/line/column: {v}"
);
assert!(v["url"].is_string(), "url must be string: {v}");
assert!(v["line"].is_number(), "line must be number: {v}");
assert!(v["column"].is_number(), "column must be number: {v}");
}