Run a local JavaScript file inside the page context
(
client: &mut CdpClient,
session_id: &str,
file_path: &str,
script_args: &serde_json::Value,
format: OutputFormat,
output: Option<&str>,
track_navigation: bool,
)
| 218 | |
| 219 | /// Run a local JavaScript file inside the page context |
| 220 | pub async fn run_script( |
| 221 | client: &mut CdpClient, |
| 222 | session_id: &str, |
| 223 | file_path: &str, |
| 224 | script_args: &serde_json::Value, |
| 225 | format: OutputFormat, |
| 226 | output: Option<&str>, |
| 227 | track_navigation: bool, |
| 228 | ) -> Result<CommandResult> { |
| 229 | let script_content = tokio::fs::read_to_string(file_path) |
| 230 | .await |
| 231 | .map_err(|e| anyhow::anyhow!("Failed to read script file '{}': {}", file_path, e))?; |
| 232 | |
| 233 | // Perform auto-navigation if @url or @navigate comments exist at the top of the file |
| 234 | let target_url = parse_script_url_marker(&script_content); |
| 235 | |
| 236 | if let Some(ref url) = target_url { |
| 237 | // Interpolate {arg_name} placeholders from script_args |
| 238 | let mut interpolated_url = url.clone(); |
| 239 | if let Some(obj) = script_args.as_object() { |
| 240 | for (key, val) in obj { |
| 241 | let placeholder = format!("{{{}}}", key); |
| 242 | let val_str = match val { |
| 243 | serde_json::Value::String(s) => s.clone(), |
| 244 | other => other.to_string(), |
| 245 | }; |
| 246 | let encoded_val = url_encode(&val_str); |
| 247 | interpolated_url = interpolated_url.replace(&placeholder, &encoded_val); |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | let nav_url = if interpolated_url.starts_with("http://") || interpolated_url.starts_with("https://") { |
| 252 | interpolated_url.clone() |
| 253 | } else if is_local_host(&interpolated_url) { |
| 254 | format!("http://{}", interpolated_url) |
| 255 | } else { |
| 256 | format!("https://{}", interpolated_url) |
| 257 | }; |
| 258 | |
| 259 | let current_url = client.current_url(session_id).await?; |
| 260 | if current_url.trim_end_matches('/') != nav_url.trim_end_matches('/') { |
| 261 | eprintln!("[script] Current URL '{}' does not match target URL '{}'. Auto-navigating...", current_url, nav_url); |
| 262 | |
| 263 | crate::commands::navigate::navigate( |
| 264 | client, |
| 265 | session_id, |
| 266 | Some(&nav_url), |
| 267 | false, |
| 268 | false, |
| 269 | false, |
| 270 | None, |
| 271 | None, |
| 272 | ) |
| 273 | .await?; |
| 274 | |
| 275 | let post_nav_url = client.current_url(session_id).await?; |
| 276 | if post_nav_url.trim_end_matches('/') != nav_url.trim_end_matches('/') { |
| 277 | // Not a hard failure: sites commonly redirect (www., trailing |
no test coverage detected