Merge PR #284
This commit is contained in:
commit
6d22d1235b
|
|
@ -71,6 +71,8 @@ USAGE:
|
|||
per line: {\"method\": \"ui.set\", \"params\": {\"view\": \"detail\"}}.
|
||||
Replies go to stdout. `ui.screenshot` without a path writes -o (then
|
||||
OUT-2.png, OUT-3.png…); `ui.settle {timeoutMs?}` waits for renders.
|
||||
A failed request (\"ok\": false) does not stop the script, but the exit
|
||||
status is non-zero when any request failed.
|
||||
-o, --output OUT PNG path (a final screenshot is written here if the script took none)
|
||||
--size WxH window size in points (default 1600x1000)
|
||||
--scale S pixels per point (default 1)
|
||||
|
|
@ -755,6 +757,9 @@ fn snapshot(args: &[String]) -> Result<(), String> {
|
|||
Some(p.with_file_name(format!("{stem}-{shots}.{ext}")).to_string_lossy().to_string())
|
||||
};
|
||||
let mut wrote_output = false;
|
||||
// Issue #166: a scripted request that fails still gets its reply printed and the run carries
|
||||
// on (like `run --keep-going`), but the exit status reports it — CI judges by exit status.
|
||||
let mut failed = 0usize;
|
||||
if let Some(script) = &script {
|
||||
let text = std::fs::read_to_string(script).map_err(|e| format!("{script}: {e}"))?;
|
||||
let mut out = std::io::stdout().lock();
|
||||
|
|
@ -787,6 +792,9 @@ fn snapshot(args: &[String]) -> Result<(), String> {
|
|||
}
|
||||
_ => h.request(&method, params, timeout),
|
||||
};
|
||||
if reply["ok"] != true {
|
||||
failed += 1;
|
||||
}
|
||||
if let Some(o) = reply.as_object_mut() {
|
||||
o.insert("id".into(), id);
|
||||
// wall time of the request (incl. the frames it ran), and since the start
|
||||
|
|
@ -823,7 +831,7 @@ fn snapshot(args: &[String]) -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
eprintln!("lightcraft-cli snapshot: done in {:.2} s ({} frames)", t0.elapsed().as_secs_f64(), h.frames());
|
||||
Ok(())
|
||||
if failed > 0 { Err(format!("{failed} scripted request(s) failed")) } else { Ok(()) }
|
||||
}
|
||||
|
||||
fn commands(args: &[String]) -> Result<(), String> {
|
||||
|
|
|
|||
|
|
@ -183,6 +183,39 @@ fn snapshot_subcommand_renders_the_ui_headlessly() {
|
|||
assert_eq!((d.width, d.height), (640, 480));
|
||||
}
|
||||
|
||||
/// Issue #166: a scripted request that fails makes `snapshot` exit non-zero. The failed reply is
|
||||
/// still printed, the later lines still run, and the final `-o` screenshot is still written.
|
||||
#[test]
|
||||
fn snapshot_script_failure_exits_non_zero() {
|
||||
let script = tmp("snap-fail.jsonl");
|
||||
let out = tmp("snap-fail.png");
|
||||
std::fs::write(
|
||||
&script,
|
||||
format!(
|
||||
"{}\n{}\n",
|
||||
json!({"method": "ui.set", "params": {"view": "grid"}}), // not a view: `photoGrid`, `detail`, …
|
||||
json!({"method": "ui.set", "params": {"view": "photoGrid"}}),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = std::fs::remove_file(&out);
|
||||
let o = Command::new(BIN)
|
||||
.args(["snapshot", "--demo", "--script", script.to_str().unwrap(), "-o", out.to_str().unwrap(), "--size", "320x200"])
|
||||
.output()
|
||||
.unwrap();
|
||||
let stderr = String::from_utf8_lossy(&o.stderr);
|
||||
assert!(!o.status.success(), "a failed scripted request must fail the run\n{stderr}");
|
||||
assert!(stderr.contains("1 scripted request(s) failed"), "{stderr}");
|
||||
let replies: Vec<Value> = String::from_utf8_lossy(&o.stdout).lines().map(|l| serde_json::from_str(l).unwrap()).collect();
|
||||
assert_eq!(replies.len(), 2, "{replies:?}");
|
||||
assert_eq!(replies[0]["ok"], false, "{replies:?}");
|
||||
assert!(replies[0]["error"].as_str().unwrap_or("").contains("grid"), "{replies:?}");
|
||||
assert_eq!(replies[1]["ok"], true, "{replies:?}");
|
||||
// continue-and-report: the final screenshot is still written
|
||||
let d = lightcraft_codecs::decode(&std::fs::read(&out).unwrap(), Default::default()).unwrap();
|
||||
assert_eq!((d.width, d.height), (320, 200));
|
||||
}
|
||||
|
||||
/// Issue #136: with the GPU switched off from the environment the UI starts and renders on the CPU,
|
||||
/// without creating a GPU device (no driver is loaded), and says why.
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -86,7 +86,10 @@ lightcraft-cli snapshot --library DIR --script tour.jsonl -o shot.png
|
|||
|
||||
`tour.jsonl` holds one request per line (`#` comments allowed), e.g.
|
||||
`{"method": "ui.set", "params": {"view": "detail", "right": "edit", "openSections": ["optics"]}}`
|
||||
then `{"method": "ui.screenshot"}`. Replies are printed to stdout. A `ui.screenshot` without
|
||||
then `{"method": "ui.screenshot"}`. Replies are printed to stdout. A failed request
|
||||
(`"ok": false`) does not stop the script — the remaining lines and the final screenshot still
|
||||
run — but the exit status is non-zero when any request failed, as with `run --keep-going`, so
|
||||
CI and nightly runs can judge a snapshot by its exit status. A `ui.screenshot` without
|
||||
`path` writes `-o` (then `OUT-2.png`, `OUT-3.png`, …); `ui.settle {timeoutMs?}` waits until no
|
||||
renders are in flight. Each request runs frames until it is answered and its injected input
|
||||
(clicks, keys, drags) has played out. Widget ids for `ui.clickWidget` come from `ui.widgets`
|
||||
|
|
|
|||
Loading…
Reference in New Issue