fix(open): graceful load-timeout + --wait-until override for SPAs (issue #10)

`open` waits for the `load` event by default. SPAs whose `load` never fires
(a long-pending XHR or a stuck sub-resource holds it open) made `open`
hard-fail after the lifecycle timeout — even though the DOM was ready and
eval/screenshot worked immediately right after.

- Graceful degradation: if the lifecycle event times out but document.readyState
  is interactive/complete, navigate returns success carrying a `warning` in the
  response (the CLI prints it to stderr; --json keeps the field) instead of
  erroring. Only a still-loading document is a real failure.
- `open/goto/navigate` now accept `--wait-until <load|domcontentloaded|
  networkidle|none>` so SPAs can return as soon as the DOM is parsed. The URL
  parser skips the --wait-until value so it isn't mistaken for the URL.
- WaitUntil::as_str() for the warning label; output.rs surfaces response warnings.

Verified live: --wait-until domcontentloaded returns immediately on a page whose
load never fires; default load on the same page now succeeds at the timeout with
a clear stderr warning instead of failing. Adds parse tests for both arg orders
+ bogus value.
This commit is contained in:
leeguooooo
2026-06-12 12:19:36 +09:00
parent 266b610358
commit b4c1707a01
3 changed files with 127 additions and 4 deletions
+6
View File
@@ -256,6 +256,12 @@ pub fn print_response_with_opts(resp: &Response, action: Option<&str>, opts: &Ou
// empty title line.
None => println!("{} {}", color::success_indicator(), color::dim(url)),
}
// Soft warning carried in the response (e.g. the load event timed out
// but the DOM was ready — issue #10). Goes to stderr so it doesn't
// pollute the stdout url/title that scripts parse.
if let Some(w) = data.get("warning").and_then(|v| v.as_str()) {
eprintln!("⚠ navigation: {w}");
}
return;
}
if let Some(cdp_url) = data.get("cdpUrl").and_then(|v| v.as_str()) {