mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-29 13:16:50 -06:00
Engine: a headless call that fails for want of a file is not recorded
file.open with no file succeeds by queuing a dialog, which execute_headless turns into an error for callers with no UI; the recording kept the step. Recorder::truncate forgets it and keeps the byte count right. Regression test.
This commit is contained in:
@@ -826,10 +826,17 @@ impl Session {
|
||||
/// queued a file dialog because it got no file (`file.open`, `file.saveAs`, `file.save` on a workbook with no
|
||||
/// file yet, `data.getData`) is an error instead of a silent success.
|
||||
pub fn execute_headless(&mut self, id: &str, params: Json) -> Result<Json> {
|
||||
let recorded = self.recorder.as_ref().map(|r| (r.steps.len(), r.dropped));
|
||||
let r = self.execute(id, params);
|
||||
let requests = self.take_ui_requests();
|
||||
let asked_for_file = requests.iter().any(|q| matches!(q, UiRequest::Dialog(name, _) if name == "open" || name == "saveAs"));
|
||||
if r.is_ok() && asked_for_file {
|
||||
// The caller gets an error, so the recording keeps no step for the command.
|
||||
if let Some((steps, dropped)) = recorded
|
||||
&& let Some(rec) = self.recorder.as_mut()
|
||||
{
|
||||
rec.truncate(steps, dropped);
|
||||
}
|
||||
let what = match id {
|
||||
"file.open" => "`path` or `base64`",
|
||||
"data.getData" | "data.fromTextCsv" => "`path` or `text`",
|
||||
|
||||
@@ -58,4 +58,13 @@ impl Recorder {
|
||||
self.dropped = self.dropped.saturating_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Forgets the steps after the first `steps` and puts the dropped count back to `dropped`,
|
||||
/// for a command the caller received as failed after it was recorded.
|
||||
pub fn truncate(&mut self, steps: usize, dropped: usize) {
|
||||
for step in self.steps.drain(steps.min(self.steps.len())..) {
|
||||
self.bytes = self.bytes.saturating_sub(serde_json::to_vec(&step).map_or(0, |v| v.len()));
|
||||
}
|
||||
self.dropped = dropped;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,6 +571,19 @@ fn recorded_ids(s: &Session) -> Vec<String> {
|
||||
s.recorder.as_ref().unwrap().steps.iter().map(|st| st.id.clone()).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_headless_call_that_fails_for_want_of_a_file_is_not_recorded() {
|
||||
// `file.open` with no file queues a dialog and succeeds; a headless caller gets an error for
|
||||
// it instead, so the recording keeps no step for it either.
|
||||
let mut s = s();
|
||||
s.start_recording();
|
||||
set(&mut s, "A1", "1");
|
||||
assert!(s.execute_headless("file.open", json!({})).is_err());
|
||||
assert_eq!(recorded_ids(&s), ["cell.set"]);
|
||||
let rec = s.stop_recording().unwrap();
|
||||
assert_eq!(rec.dropped, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_recorder_keeps_top_level_calls_with_where_they_ran() {
|
||||
let mut s = s();
|
||||
|
||||
Reference in New Issue
Block a user