fix(cli,js): add --version flag and script-error-resilience test (#147)

Two improvements while investigating #147:

1. `obscura --version` / `-V` now print the CARGO_PKG_VERSION instead of
   erroring out. The issue reporter explicitly called out that there was
   no version flag, and the existing `obscura serve` banner is the only
   way to discover the version.

2. New regression test in obscura-js verifies that a TypeError thrown
   from one script does not poison the runtime: subsequent scripts and
   DOM queries must continue to work. The reporter's symptom was that
   offside.js crashing collapsed --dump text output to 1 byte; that
   cascade should never happen and this test pins it down.

The classList error itself is offside.js's own bug (it indexes into the
querySelectorAll result without checking for an empty array) and only
fires when the .slideout-navigation element is absent from the DOM.
On current main that element parses correctly and offside.js runs
without error against a captured copy of the affected page.
This commit is contained in:
SGavrl committed 2026-05-16 15:11:18 +00:00
1 parent 8cb0cb429b
commit 935cb5c0da
2 files changed
+36 -1

No files matched your search

+31
View File
@@ -934,6 +934,37 @@ mod tests {
assert_eq!(result, serde_json::json!(["A", "B"]));
}
/// Regression test for #147: a TypeError in one script must not poison
/// the runtime so that subsequent scripts (or DOM queries) collapse to
/// empty. The reporter saw `--dump text` return 1 byte after offside.js
/// crashed; that cascade should never happen.
#[test]
fn script_typeerror_does_not_poison_subsequent_execution() {
let mut rt = setup_runtime(
"<html><body><p id=hit>BODY_TEXT</p></body></html>",
);
// 1. First script throws the same flavor of error offside.js produced
// (`Cannot read properties of undefined (reading 'classList')`).
let err = rt
.execute_script("buggy", "var x; x.classList.add('y');")
.unwrap_err();
assert!(err.contains("classList") || err.contains("undefined"),
"expected classList/undefined error, got: {}", err);
// 2. The runtime must still be usable: a follow-up script runs.
rt.execute_script("ok", "globalThis.__after_error = 'still alive';")
.unwrap();
let result = rt.evaluate("globalThis.__after_error").unwrap();
assert_eq!(result, serde_json::json!("still alive"));
// 3. DOM queries still work after the script error.
let text = rt
.evaluate("document.querySelector('#hit').textContent")
.unwrap();
assert_eq!(text, serde_json::json!("BODY_TEXT"));
}
#[test]
fn test_console_log() {
let mut rt = setup_runtime("<html><body></body></html>");