Files
OneCAD/crates/ui-egui/tests/coincident_lines.rs
T
bherbruckandClaude Opus 5.5 296683229d Rename SolveCraft to SolidCraft everywhere, with compatibility shims (#389)
* 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>
2026-10-12 17:17:01 -04:00

64 lines
3.3 KiB
Rust

//! Coincident accepts clicked line bodies as well as explicit sketch points.
use serde_json::json;
use solidcraft_engine::sketch::ConstraintKind;
use solidcraft_ui_egui::scenario::Harness;
fn setup() -> Harness {
let mut h = Harness::new();
h.run(&json!([
{"call":"engine.execute","params":{"command":"sketch.create","params":{"plane":"XY"}}},
{"call":"engine.execute","params":{"command":"sketch.line","params":{"points":[[10,10],[30,10]],"infer":false,"connect":false}}},
{"call":"engine.execute","params":{"command":"sketch.line","params":{"points":[[35,15],[35,40]],"infer":false,"connect":false}}},
{"call":"ui.view","params":{"view":"top"}}
]))
.unwrap();
h
}
#[test]
fn clicked_lines_join_closest_endpoints_in_both_orders() {
for reverse in [false, true] {
let mut h = setup();
let before = serde_json::to_value(&h.app.session.doc).unwrap();
let undo = h.app.session.undo.len();
let picks = if reverse { [[35.0, 27.5], [20.0, 10.0]] } else { [[20.0, 10.0], [35.0, 27.5]] };
h.run(
&json!([{"start":"sketch.constraint.coincident"}, {"click":{"sketch":picks[0]}}, {"click":{"sketch":picks[1]}}, {"expect":{"errors":0}}]),
)
.unwrap();
assert!(!h.app.status.as_ref().is_some_and(|(_, _, error)| *error));
let sk = h.app.session.doc.sketch(h.app.session.active_sketch.unwrap()).unwrap();
let a = sk.resolve_point("l1.end").unwrap();
let b = sk.resolve_point("l2.start").unwrap();
assert!(sk.point(a).unwrap().dist(sk.point(b).unwrap()) < 1e-6);
assert!(sk.constraints.iter().any(|c| matches!(c.kind, ConstraintKind::Coincident {p,q} if (p,q)==(a,b) || (p,q)==(b,a))));
let fixed_ref = if reverse { "l2.end" } else { "l1.start" };
let expected = if reverse { [35.0, 40.0] } else { [10.0, 10.0] };
let fixed = sk.point(sk.resolve_point(fixed_ref).unwrap()).unwrap();
assert!((fixed.x - expected[0]).abs() < 1e-6 && (fixed.y - expected[1]).abs() < 1e-6);
assert_eq!(h.app.session.undo.len(), undo + 1);
let after = serde_json::to_value(&h.app.session.doc).unwrap();
h.run(&json!([{"call":"engine.execute","params":{"command":"edit.undo","params":{}}}])).unwrap();
assert_eq!(serde_json::to_value(&h.app.session.doc).unwrap(), before);
h.run(&json!([{"call":"engine.execute","params":{"command":"edit.redo","params":{}}}])).unwrap();
assert_eq!(serde_json::to_value(&h.app.session.doc).unwrap(), after);
}
}
#[test]
fn fixed_line_pair_rejects_without_changing_document_or_history() {
let mut h = setup();
h.run(&json!([
{"call":"engine.execute","params":{"command":"sketch.constraint.fix","params":{"entity":"l1"}}},
{"call":"engine.execute","params":{"command":"sketch.constraint.fix","params":{"entity":"l2"}}}
]))
.unwrap();
let before = serde_json::to_value(&h.app.session.doc).unwrap();
let undo = h.app.session.undo.len();
h.run(&json!([{"start":"sketch.constraint.coincident"},{"click":{"sketch":[20,10]}},{"click":{"sketch":[35,27.5]}}])).unwrap();
assert!(h.app.status.as_ref().is_some_and(|(_, _, error)| *error));
assert_eq!(serde_json::to_value(&h.app.session.doc).unwrap(), before);
assert_eq!(h.app.session.undo.len(), undo);
}