Files
OneCAD/crates/ui-egui/tests/parameter_enter.rs
T
DuBearte 9dc12b4d0f Parameters: reset the new row's expression after Add (#1170) (#1235)
After Add in Change Parameters, the new-parameter row's expression goes back to the default a new row starts with. Fixes #1170.
2026-10-14 21:45:04 -04:00

140 lines
6.5 KiB
Rust

//! Enter submits only the focused Parameters editor row.
use egui::{Event, Key, Modifiers};
use serde_json::json;
use solidcraft_ui_egui::scenario::Harness;
fn open() -> Harness {
let mut h = Harness::new();
h.step(&json!({"widget":"Parameters"})).unwrap();
assert!(h.app.params.is_some());
h
}
fn fill(h: &mut Harness, field: &str, text: &str) {
h.run(&json!([
{"click":{"handle":format!("param:new:{field}")}},
{"key":"A","cmd":true}, {"text":text}
]))
.unwrap();
}
fn enter(h: &mut Harness, repeat: bool) {
h.app.synthetic.push(Event::Key { key: Key::Enter, physical_key: None, pressed: true, repeat, modifiers: Modifiers::NONE });
h.frame();
h.app.synthetic.push(Event::Key { key: Key::Enter, physical_key: None, pressed: false, repeat: false, modifiers: Modifiers::NONE });
h.frames(3);
}
#[test]
fn parameter_enter_adds_once_and_focuses_next_name() {
let mut h = open();
fill(&mut h, "name", "width");
fill(&mut h, "expression", "25 mm");
let undo = h.app.session.undo.len();
enter(&mut h, false);
assert_eq!(h.app.session.undo.len(), undo + 1);
assert!(h.app.params.as_ref().unwrap().new_name.is_empty());
assert!(h.app.params.as_ref().unwrap().error.is_none());
let saved = h.app.session.doc.to_json();
enter(&mut h, true);
assert_eq!(h.app.session.doc.to_json(), saved);
assert_eq!(h.app.session.undo.len(), undo + 1);
// Name has focus after successful creation; no mouse needed for the next name.
h.run(&json!([{"text":"height"}])).unwrap();
assert_eq!(h.app.params.as_ref().unwrap().new_name, "height");
enter(&mut h, false);
assert_eq!(h.app.session.undo.len(), undo + 2);
let result = h.app.session.execute("parameters.list", &json!({})).unwrap();
assert!(result["parameters"].as_array().unwrap().iter().any(|p| p["name"] == "height"));
}
#[test]
fn parameter_enter_invalid_preserves_draft_and_other_rows() {
let mut h = open();
h.app.session.execute("parameters.add", &json!({"name":"existing","expression":"10 mm"})).unwrap();
h.frames(3);
fill(&mut h, "name", "bad");
fill(&mut h, "expression", "missing + 1 mm");
let saved = h.app.session.doc.to_json();
let undo = h.app.session.undo.len();
enter(&mut h, false);
assert_eq!(h.app.session.doc.to_json(), saved);
assert_eq!(h.app.session.undo.len(), undo);
let d = h.app.params.as_ref().unwrap();
assert_eq!(d.new_name, "bad");
assert_eq!(d.new_expr, "missing + 1 mm");
assert!(d.error.is_some());
fill(&mut h, "expression", "15 mm");
fill(&mut h, "name", "existing");
enter(&mut h, false);
assert_eq!(h.app.session.doc.to_json(), saved);
assert!(h.app.params.as_ref().unwrap().error.is_some());
}
#[test]
fn parameter_enter_edits_expression_without_adding_draft() {
let mut h = open();
h.app.session.execute("parameters.add", &json!({"name":"width","expression":"10 mm"})).unwrap();
h.frames(3);
fill(&mut h, "name", "unsubmitted");
let undo = h.app.session.undo.len();
h.run(&json!([{"click":{"handle":"param:width"}}, {"key":"A","cmd":true}, {"text":"20 mm"}])).unwrap();
enter(&mut h, false);
assert_eq!(h.app.session.undo.len(), undo + 1);
assert_eq!(h.app.params.as_ref().unwrap().new_name, "unsubmitted");
let result = h.app.session.execute("parameters.list", &json!({})).unwrap();
let ps = result["parameters"].as_array().unwrap();
assert!(ps.iter().any(|p| p["name"] == "width" && p["expression"] == "20 mm"));
assert!(!ps.iter().any(|p| p["name"] == "unsubmitted"));
let saved = h.app.session.doc.to_json();
h.run(&json!([{"click":{"handle":"param:width"}}, {"key":"A","cmd":true}, {"text":"missing + 2 mm"}])).unwrap();
enter(&mut h, false);
assert_eq!(h.app.session.doc.to_json(), saved);
assert!(h.app.params.as_ref().unwrap().error.is_some());
assert_eq!(h.app.params.as_ref().unwrap().editing.get("width").map(String::as_str), Some("missing + 2 mm"));
}
#[test]
fn parameter_enter_comment_uses_selected_unit_and_unrelated_focus_does_not_submit() {
let mut h = open();
fill(&mut h, "name", "length");
h.run(&json!([{"click":{"handle":"param:new:unit"}}, {"widget":"cm"}])).unwrap();
fill(&mut h, "expression", "2 cm");
fill(&mut h, "comment", "Overall length");
let undo = h.app.session.undo.len();
h.run(&json!([{"click":{"handle":"params:title"}}])).unwrap();
enter(&mut h, false);
assert_eq!(h.app.session.undo.len(), undo);
h.run(&json!([{"click":{"handle":"param:new:comment"}}])).unwrap();
enter(&mut h, false);
let result = h.app.session.execute("parameters.list", &json!({})).unwrap();
assert!(result["parameters"].as_array().unwrap().iter().any(|p| p["name"] == "length" && p["unit"] == "cm" && p["comment"] == "Overall length"));
assert_eq!(h.app.session.undo.len(), undo + 1);
}
#[test]
fn parameter_rename_arrow_keys_move_cursor_and_keep_editing() {
let mut h = open();
h.app.session.execute("parameters.add", &json!({"name":"width","expression":"10 mm"})).unwrap();
// Let the click that opened the dialog age, or egui counts the double-click as a triple.
h.frames(30);
h.run(&json!([{"click":{"handle":"param:name:width"},"double":true}])).unwrap();
h.frames(2);
let renaming = |h: &Harness| h.app.params.as_ref().unwrap().renaming.clone();
assert_eq!(renaming(&h), Some(("width".to_string(), "width".to_string())));
// Move the cursor to the start and type there; every arrow key keeps the rename open.
h.run(&json!([{"key":"ArrowLeft"}, {"key":"ArrowUp"}, {"key":"ArrowDown"}, {"key":"ArrowRight"}, {"key":"Home"}, {"text":"plate_"}])).unwrap();
assert_eq!(renaming(&h), Some(("width".to_string(), "plate_width".to_string())));
enter(&mut h, false);
assert_eq!(renaming(&h), None);
let result = h.app.session.execute("parameters.list", &json!({})).unwrap();
assert!(result["parameters"].as_array().unwrap().iter().any(|p| p["name"] == "plate_width"));
}
#[test]
fn parameter_add_resets_expression_for_next_row() {
let mut h = open();
let initial = h.app.params.as_ref().unwrap().new_expr.clone();
fill(&mut h, "name", "width");
fill(&mut h, "expression", "25 mm");
enter(&mut h, false);
let result = h.app.session.execute("parameters.list", &json!({})).unwrap();
assert!(result["parameters"].as_array().unwrap().iter().any(|p| p["name"] == "width" && p["expression"] == "25 mm"));
let d = h.app.params.as_ref().unwrap();
assert!(d.new_name.is_empty());
assert_eq!(d.new_expr, initial);
}