Commands: a boolean or number given as text is refused

Squashed from #3428 onto main.
This commit is contained in:
bflatastic
2026-10-22 00:10:57 +07:00
parent 14f804cdee
commit e7cdf154ca
32 changed files with 1467 additions and 105 deletions
+47
View File
@@ -137,6 +137,32 @@ fn moving_a_key_point_moves_the_key_and_the_other_way_round() {
assert!(s.execute("object.blend.spine.moveAnchor", &json!({"id": g.0, "anchor": 0, "x": f64::MAX, "y": 0})).is_err());
}
/// Moving a spine point refuses an `independent`, and reshaping a spine segment a `perpendicular`,
/// given as text or as another value that is not true or false, and the blend stays as it was; null
/// is read as the key left out.
#[test]
fn spine_edits_refuse_a_boolean_given_as_text() {
let mut s = session();
let (_, _, g) = blend(&mut s);
s.execute("object.blend.spine.addAnchor", &json!({"id": g.0, "x": 55, "y": 5})).unwrap();
s.execute("object.blend.spine.convertAnchor", &json!({"id": g.0, "anchor": 1, "to": "smooth", "x": 75, "y": 5})).unwrap();
let before = node(&s, g);
for (cmd, key, p) in [
("object.blend.spine.moveAnchor", "independent", json!({"id": g.0, "anchor": 1, "handle": "out", "x": 75, "y": 40, "independent": "true"})),
("object.blend.spine.moveAnchor", "independent", json!({"id": g.0, "anchor": 1, "x": 55, "y": 60, "independent": 1})),
("object.blend.spine.reshapeSegment", "perpendicular", json!({"id": g.0, "segment": 0, "dx": 10, "dy": 40, "perpendicular": "true"})),
("object.blend.spine.reshapeSegment", "perpendicular", json!({"id": g.0, "segment": 0, "dy": 40, "perpendicular": [false]})),
] {
let r = s.execute(cmd, &p);
assert!(matches!(&r, Err(EngineError::BadParams { msg, .. }) if *msg == format!("`{key}` must be true or false")), "{cmd} {p}: {r:?}");
assert_eq!(node(&s, g), before, "{cmd} {p}");
}
s.execute("object.blend.spine.moveAnchor", &json!({"id": g.0, "anchor": 1, "handle": "out", "x": 75, "y": 40, "independent": null})).unwrap();
let a = spec(&s, g).spine.unwrap().subpaths[0].anchors[1];
assert_eq!((a.h_out, a.kind), (Point::new(75.0, 40.0), vectorcraft_geom::AnchorKind::Smooth), "the point stays smooth");
s.execute("object.blend.spine.reshapeSegment", &json!({"id": g.0, "segment": 0, "dy": 40, "perpendicular": null})).unwrap();
}
#[test]
fn only_points_without_a_key_can_be_deleted() {
let mut s = session();
@@ -170,6 +196,27 @@ fn spine_commands_refuse_an_index_that_is_not_a_whole_number() {
assert_eq!(spec(&s, g).spine.unwrap().subpaths[0].anchors[1].p, Point::new(55.0, 60.0));
}
/// Reshape Spine Segment refuses a `t`, `dx` or `dy` given as text or as another value that is not
/// a number, instead of bending the spine by 0 or at the segment's middle, and the blend stays as
/// it was; null is read as the key left out.
#[test]
fn spine_reshape_segment_refuses_a_number_given_as_text() {
let mut s = session();
let (_, _, g) = blend(&mut s);
let before = node(&s, g);
for key in ["t", "dx", "dy"] {
for v in [json!("10"), json!([10]), json!(true)] {
let mut p = json!({"id": g.0, "segment": 0, "t": 0.5, "dx": 0, "dy": 40});
p[key] = v.clone();
let r = s.execute("object.blend.spine.reshapeSegment", &p);
assert!(matches!(&r, Err(EngineError::BadParams { msg, .. }) if *msg == format!("`{key}` must be a number, not {v}")), "{p}: {r:?}");
assert_eq!(node(&s, g), before, "{p}");
}
}
s.execute("object.blend.spine.reshapeSegment", &json!({"id": g.0, "segment": 0, "t": null, "dx": null, "dy": 40})).unwrap();
assert!(center(&steps(&s, g)[1]).y > 20.0, "the step follows the bent spine");
}
#[test]
fn info_lists_the_spine() {
let mut s = session();