* WIP deep rename (not for push) * WIP2 * WIP3 * WIP4 wxs fix * rustfmt * Rename the remaining identifiers in merged crash-report code Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
89 lines
4.2 KiB
Rust
89 lines
4.2 KiB
Rust
use serde_json::json;
|
|
use solidcraft_engine::{Sel, sketch::ConstraintKind};
|
|
use solidcraft_ui_egui::scenario::Harness;
|
|
|
|
fn setup() -> Harness {
|
|
let mut h = Harness::new();
|
|
h.app.run("sketch.create", json!({"plane":"XY"})).unwrap();
|
|
h.app.run("sketch.line", json!({"points":[[10,10],[30,10]],"infer":false,"connect":false})).unwrap();
|
|
h.app.run("sketch.point", json!({"point":[20,20],"id":"a"})).unwrap();
|
|
h.app.run("sketch.point", json!({"point":[25,30],"id":"b"})).unwrap();
|
|
h.call("ui.view", json!({"view":"top"}));
|
|
h
|
|
}
|
|
|
|
#[test]
|
|
fn clicked_point_constraint_preselection_applies_and_undoes_once() {
|
|
for (command, picks) in [
|
|
("coincident", vec![[20, 20], [25, 30]]),
|
|
("coincident", vec![[20, 20], [20, 10]]),
|
|
("coincident", vec![[20, 10], [20, 20]]),
|
|
("midpoint", vec![[20, 20], [20, 10]]),
|
|
("midpoint", vec![[20, 10], [20, 20]]),
|
|
("symmetry", vec![[20, 10], [20, 20], [25, 30]]),
|
|
("symmetry", vec![[20, 20], [20, 10], [25, 30]]),
|
|
] {
|
|
let mut h = setup();
|
|
for (index, pick) in picks.iter().enumerate() {
|
|
h.step(&json!({"click":{"sketch":pick},"shift":index>0})).unwrap();
|
|
}
|
|
assert_eq!(h.app.session.selection.len(), picks.len(), "{command}");
|
|
let before = h.app.session.doc.to_json();
|
|
let undo = h.app.session.undo.len();
|
|
h.step(&json!({"start":format!("sketch.constraint.{command}")})).unwrap();
|
|
assert!(!h.app.status.as_ref().is_some_and(|(_, _, error)| *error), "{command}: {:?}", h.app.status);
|
|
assert!(h.app.tool.is_none());
|
|
assert!(h.app.session.selection.is_empty());
|
|
assert_eq!(h.app.session.undo.len(), undo + 1);
|
|
let state = h.app.session.world_state();
|
|
let sk = &state.sketch(h.app.session.active_sketch.unwrap()).unwrap().sketch;
|
|
assert!(sk.constraints.iter().any(|c| match command {
|
|
"coincident" => matches!(c.kind, ConstraintKind::Coincident { .. } | ConstraintKind::PointOnCurve { .. }),
|
|
"midpoint" => matches!(c.kind, ConstraintKind::Midpoint { .. }),
|
|
_ => matches!(c.kind, ConstraintKind::Symmetric { .. }),
|
|
}));
|
|
let point = |id| sk.point(sk.resolve_point(id).unwrap()).unwrap();
|
|
let a = point("a");
|
|
let b = point("b");
|
|
let start = point("l1.start");
|
|
let end = point("l1.end");
|
|
let axis = (end - start).normalized().unwrap();
|
|
match command {
|
|
"midpoint" => assert!(a.dist((start + end) * 0.5) < 1e-6),
|
|
"symmetry" => {
|
|
assert!(((a + b) * 0.5 - start).cross(axis).abs() < 1e-6);
|
|
assert!((b - a).dot(axis).abs() < 1e-6);
|
|
}
|
|
_ if picks.contains(&[20, 10]) => assert!((a - start).cross(axis).abs() < 1e-6),
|
|
_ => assert!(a.dist(b) < 1e-6),
|
|
}
|
|
let after = h.app.session.doc.to_json();
|
|
h.app.run("edit.undo", json!({})).unwrap();
|
|
assert_eq!(h.app.session.doc.to_json(), before);
|
|
h.app.run("edit.redo", json!({})).unwrap();
|
|
assert_eq!(h.app.session.doc.to_json(), after);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn rejected_and_ambiguous_preselection_preserve_document_and_selection() {
|
|
let mut h = setup();
|
|
h.app.run("sketch.constraint.fix", json!({"entities":["a","b"]})).unwrap();
|
|
h.app.session.selection = vec![Sel::SketchPoint { id: "a".into() }, Sel::SketchPoint { id: "b".into() }];
|
|
let selection = h.app.session.selection.clone();
|
|
let before = h.app.session.doc.to_json();
|
|
let undo = h.app.session.undo.len();
|
|
h.step(&json!({"start":"sketch.constraint.coincident"})).unwrap();
|
|
assert!(h.app.status.as_ref().is_some_and(|(_, _, error)| *error));
|
|
assert_eq!(h.app.session.selection, selection);
|
|
assert_eq!(h.app.session.doc.to_json(), before);
|
|
assert_eq!(h.app.session.undo.len(), undo);
|
|
for command in ["coincident", "midpoint", "symmetry"] {
|
|
h.app.session.selection = vec![Sel::SketchPoint { id: "a".into() }];
|
|
h.step(&json!({"start":format!("sketch.constraint.{command}")})).unwrap();
|
|
assert!(h.app.tool.as_ref().unwrap().picks.is_empty());
|
|
assert_eq!(h.app.session.selection.len(), 1);
|
|
assert_eq!(h.app.session.doc.to_json(), before);
|
|
}
|
|
}
|