Variables: art on a locked artboard is not bound or rewritten by a data set

Squashed from #5118 onto main.
This commit is contained in:
dotCooCoo
2026-11-02 15:21:58 +07:00
committed by bflatastic
parent 30dd4fe8f5
commit e68bf6af55
25 changed files with 158 additions and 30 deletions
+62
View File
@@ -438,6 +438,68 @@ fn locked_art_is_neither_bound_nor_rewritten() {
assert!(!s.doc().unwrap().doc.node(r).unwrap().visible, "the unlocked rectangle still applied");
}
/// The art on a locked artboard acts as locked art: a data set skips it, Update Data Set reads
/// nothing from it, and it takes no new binding. Unlocking the artboard lets the data set rewrite it.
#[test]
fn art_on_a_locked_artboard_is_neither_bound_nor_rewritten() {
let mut s = session();
let t = NodeId(s.execute("text.create", &json!({"x": 2050, "y": 50, "text": "cat"})).unwrap()["id"].as_u64().unwrap());
let fresh = NodeId(s.execute("text.create", &json!({"x": 2100, "y": 100, "text": "new"})).unwrap()["id"].as_u64().unwrap());
let r = rect(&mut s);
s.execute("artboard.new", &json!({"x": 2000, "y": 0, "width": 400, "height": 400})).unwrap();
s.execute("variable.define", &json!({"name": "Name", "kind": "text"})).unwrap();
s.execute("variable.define", &json!({"name": "Show", "kind": "visibility"})).unwrap();
s.execute("variable.define", &json!({"name": "Box", "kind": "visibility"})).unwrap();
s.execute("variable.bind", &json!({"variable": "Name", "ids": [t.0]})).unwrap();
s.execute("variable.bind", &json!({"variable": "Show", "ids": [t.0]})).unwrap();
s.execute("variable.bind", &json!({"variable": "Box", "ids": [r.0]})).unwrap();
s.execute("dataset.capture", &json!({"name": "A"})).unwrap();
s.execute("dataset.new", &json!({"name": "B", "values": {"Name": "Bob", "Show": false, "Box": false}})).unwrap();
s.execute("select.none", &json!({})).unwrap();
s.execute("artboard.setProps", &json!({"index": 1, "locked": true})).unwrap();
let e = s.execute("variable.bind", &json!({"variable": "Name", "ids": [fresh.0]})).unwrap_err().to_string();
assert!(e.contains(&format!("node {} is on a locked artboard", fresh.0)), "{e}");
let v = s.execute("dataset.select", &json!({"name": "B"})).unwrap();
assert_eq!((v["applied"].as_u64(), v["skipped"].as_u64()), (Some(1), Some(2)), "{v}");
assert_eq!(plain(&s, t), "cat", "the text on the locked artboard was left alone");
assert!(s.doc().unwrap().doc.node(t).unwrap().visible, "and still shows");
assert!(!s.doc().unwrap().doc.node(r).unwrap().visible, "the rectangle off it applied");
// Update Data Set keeps the row's values for the art it can't read.
let v = s.execute("dataset.update", &json!({})).unwrap();
assert_eq!(v["values"], 1, "{v}");
let row = s.doc().unwrap().doc.variables.dataset("B").unwrap().values.clone();
assert_eq!(row.get("Name"), Some(&vectorcraft_doc::DataValue::Text("Bob".into())));
assert_eq!(row.get("Show"), Some(&vectorcraft_doc::DataValue::Visible(false)));
s.execute("artboard.setProps", &json!({"index": 1, "locked": false})).unwrap();
let v = s.execute("dataset.select", &json!({"name": "B"})).unwrap();
assert_eq!((v["applied"].as_u64(), v["skipped"].as_u64()), (Some(3), Some(0)), "{v}");
assert_eq!(plain(&s, t), "Bob");
}
/// A locked artboard elsewhere in the document does not stop threaded type on an unlocked artboard
/// from having its whole story rewritten, and type on the locked artboard is still left alone.
#[test]
fn threaded_type_on_an_unlocked_artboard_is_rewritten_beside_a_locked_artboard() {
let (mut s, a, b, story) = threaded(200);
let far = NodeId(s.execute("text.create", &json!({"x": 2050, "y": 50, "text": "cat"})).unwrap()["id"].as_u64().unwrap());
s.execute("artboard.new", &json!({"x": 2000, "y": 0, "width": 400, "height": 400})).unwrap();
s.execute("variable.define", &json!({"name": "Name", "kind": "text"})).unwrap();
s.execute("variable.define", &json!({"name": "Tail", "kind": "text"})).unwrap();
s.execute("variable.bind", &json!({"variable": "Name", "ids": [a.0]})).unwrap();
s.execute("variable.bind", &json!({"variable": "Tail", "ids": [far.0]})).unwrap();
s.execute("dataset.new", &json!({"name": "B", "values": {"Name": "Bob", "Tail": "dog"}})).unwrap();
s.execute("select.none", &json!({})).unwrap();
s.execute("artboard.setProps", &json!({"index": 1, "locked": true})).unwrap();
let v = s.execute("dataset.select", &json!({"name": "B"})).unwrap();
assert_eq!((v["applied"].as_u64(), v["skipped"].as_u64()), (Some(1), Some(1)), "{v}");
assert_eq!((plain(&s, a), plain(&s, b)), ("Bob".to_string(), String::new()), "the whole story was rewritten");
assert_eq!(plain(&s, far), "cat", "the text on the locked artboard was left alone");
assert!(!story.is_empty());
}
/// Binding fails for locked art and for art in a hidden or locked group or layer, and the
/// error names which of the three applies.
#[test]