use bao_cdp_client::{dispatch_command, BridgeError, MockServoBackend};
use serde_json::json;
#[test]
fn sm_api_enable_records_wants_live_notifications() {
let b = MockServoBackend::new();
let r = dispatch_command(&b, "Debugger.enable", json!({}), "1").unwrap();
assert_eq!(r["debuggerId"].as_i64(), Some(1));
let log = b.call_log.lock().unwrap();
assert!(log.iter().any(|(_, m, _)| m == "debugger_enable"));
}
#[test]
fn sm_api_disable_records_disable() {
let b = MockServoBackend::new();
dispatch_command(&b, "Debugger.disable", json!({}), "1").unwrap();
let log = b.call_log.lock().unwrap();
assert!(log.iter().any(|(_, m, _)| m == "debugger_disable"));
}
#[test]
fn sm_api_set_breakpoint_by_url_returns_breakpoint_id() {
let b = MockServoBackend::new();
let r = dispatch_command(
&b,
"Debugger.setBreakpointByUrl",
json!({"url":"app.js","lineNumber":7,"columnNumber":3}),
"1",
)
.unwrap();
assert!(r["breakpointId"].is_string());
assert!(r["breakpointId"].as_str().unwrap().contains("7"));
let locs = r["locations"].as_array().unwrap();
assert_eq!(locs.len(), 1);
assert_eq!(locs[0]["lineNumber"].as_i64(), Some(7));
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_set_breakpoint_by_url" && p.contains("app.js")));
}
#[test]
fn sm_api_set_breakpoint_with_location_routes() {
let b = MockServoBackend::new();
let r = dispatch_command(
&b,
"Debugger.setBreakpoint",
json!({"location":{"scriptId":"42","lineNumber":3}}),
"1",
)
.unwrap();
assert!(r["breakpointId"].is_string());
assert_eq!(r["actualLocation"]["scriptId"].as_str(), Some("42"));
}
#[test]
fn sm_api_remove_breakpoint_routes_to_clear() {
let b = MockServoBackend::new();
dispatch_command(
&b,
"Debugger.removeBreakpoint",
json!({"breakpointId":"bp:1:10:5"}),
"1",
)
.unwrap();
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_remove_breakpoint" && p.contains("1:10:5")));
}
#[test]
fn sm_api_pause_routes_to_interrupt() {
let b = MockServoBackend::new();
dispatch_command(&b, "Debugger.pause", json!({}), "1").unwrap();
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_pause" && p == "Interrupt"));
}
#[test]
fn sm_api_resume_routes_to_resume_no_limit() {
let b = MockServoBackend::new();
dispatch_command(&b, "Debugger.resume", json!({}), "1").unwrap();
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_resume" && p == "Resume()"));
}
#[test]
fn sm_api_step_over_routes_to_resume_next() {
let b = MockServoBackend::new();
dispatch_command(&b, "Debugger.stepOver", json!({}), "1").unwrap();
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_resume" && p == "Resume(next)"));
}
#[test]
fn sm_api_step_into_routes_to_resume_step() {
let b = MockServoBackend::new();
dispatch_command(&b, "Debugger.stepInto", json!({}), "1").unwrap();
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_resume" && p == "Resume(step)"));
}
#[test]
fn sm_api_step_out_routes_to_resume_finish() {
let b = MockServoBackend::new();
dispatch_command(&b, "Debugger.stepOut", json!({}), "1").unwrap();
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_resume" && p == "Resume(finish)"));
}
#[test]
fn sm_api_evaluate_on_call_frame_routes_to_eval() {
let b = MockServoBackend::new();
let r = dispatch_command(
&b,
"Debugger.evaluateOnCallFrame",
json!({"callFrameId":"frame-0","expression":"x + 1"}),
"1",
)
.unwrap();
assert_eq!(r["result"]["type"].as_str(), Some("string"));
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, p)| m == "debugger_evaluate_on_call_frame" && p.contains("frame-0")));
}
#[test]
fn sm_api_get_possible_breakpoints_routes_to_backend() {
let b = MockServoBackend::new();
let r = dispatch_command(
&b,
"Debugger.getPossibleBreakpoints",
json!({"start":{"scriptId":"1","lineNumber":0}}),
"1",
)
.unwrap();
let arr = r["locations"].as_array().unwrap();
assert!(!arr.is_empty());
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, _)| m == "debugger_get_possible_breakpoints"));
}
#[test]
fn sm_api_get_script_source_routes_to_backend() {
let b = MockServoBackend::new();
let r = dispatch_command(&b, "Debugger.getScriptSource", json!({"scriptId":"1"}), "1").unwrap();
assert!(r["scriptSource"].is_string());
let log = b.call_log.lock().unwrap();
assert!(log
.iter()
.any(|(_, m, _)| m == "debugger_get_script_source"));
}
#[test]
fn sm_api_set_breakpoints_active_validates_bool_param() {
let b = MockServoBackend::new();
let r = dispatch_command(
&b,
"Debugger.setBreakpointsActive",
json!({"active":true}),
"1",
)
.unwrap();
assert!(r.as_object().unwrap().is_empty());
let err = dispatch_command(&b, "Debugger.setBreakpointsActive", json!({}), "1").unwrap_err();
assert!(matches!(err, BridgeError::InvalidParams(_)));
}
#[test]
fn sm_api_unknown_target_returns_page_not_found() {
let b = MockServoBackend::new();
let err = dispatch_command(&b, "Debugger.enable", json!({}), "999").unwrap_err();
assert!(matches!(err, BridgeError::PageNotFound(_)));
}
#[test]
fn sm_api_no_debugger_method_remains_e_class() {
let b = MockServoBackend::new();
for method in [
"Debugger.enable",
"Debugger.disable",
"Debugger.setBreakpoint",
"Debugger.setBreakpointByUrl",
"Debugger.removeBreakpoint",
"Debugger.pause",
"Debugger.resume",
"Debugger.stepOver",
"Debugger.stepInto",
"Debugger.stepOut",
"Debugger.evaluateOnCallFrame",
"Debugger.getPossibleBreakpoints",
"Debugger.getScriptSource",
"Debugger.setBreakpointsActive",
] {
let result = dispatch_command(&b, method, json!({}), "1");
assert!(
!matches!(result, Err(BridgeError::NotSupported(_))),
"{method} should NOT be E-class after BUG-CDP-006"
);
}
}