mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-26 20:06:50 -06:00
* Build: line tables only in dev, no debug info for dependencies * Tests: one integration-test binary per crate Each crate's tests/*.rs becomes a module of tests/it/main.rs. Files that install process-wide state (the file io hooks, user aliases, SAVETIME and SAVEFILEPATH, user linetype and pattern files, registered fonts) stay their own test binaries. * xtask ci: nextest, tests without examples, one wasm check call
189 lines
8.4 KiB
Rust
189 lines
8.4 KiB
Rust
//! OPTIONS: the JSON form reads and sets the user-profile variables without a dialog.
|
|
|
|
use cadcraft_engine::Session;
|
|
use cadcraft_engine::cmd::options::{PROFILE_VARS, profile, restore};
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn options_json_reports_sets_and_resets_the_profile() {
|
|
let mut s = Session::new();
|
|
let all = s.execute("options", &json!({})).unwrap();
|
|
for name in PROFILE_VARS {
|
|
assert!(all.get(*name).is_some(), "{name} is reported");
|
|
}
|
|
assert_eq!(all["PICKBOX"], json!(3.0));
|
|
|
|
// Names in any case; the reply is the whole profile.
|
|
let r = s.execute("options", &json!({"pickbox": 6, "GRIPSIZE": 9, "PICKFIRST": 0, "CursorSize": 25})).unwrap();
|
|
assert_eq!(
|
|
(r["PICKBOX"].clone(), r["GRIPSIZE"].clone(), r["PICKFIRST"].clone(), r["CURSORSIZE"].clone()),
|
|
(json!(6.0), json!(9.0), json!(0), json!(25.0))
|
|
);
|
|
assert_eq!(s.execute("getvar", &json!({"name": "PICKBOX"})).unwrap()["value"], json!(6.0));
|
|
|
|
// All or nothing: a bad name or value changes nothing.
|
|
assert!(s.execute("options", &json!({"PICKBOX": 2, "LUNITS": 4})).is_err(), "drawing variables are not profile settings");
|
|
assert!(s.execute("options", &json!({"APERTURE": 20, "SNAPUNIT": "wide"})).is_err());
|
|
assert!(s.execute("options", &json!({"reset": "yes"})).is_err());
|
|
assert!(s.execute("options", &json!([1, 2])).is_err());
|
|
let now = s.execute("options", &json!({})).unwrap();
|
|
assert_eq!((now["PICKBOX"].clone(), now["APERTURE"].clone()), (json!(6.0), json!(10.0)));
|
|
|
|
// Reset, then apply in the same call.
|
|
let r = s.execute("options", &json!({"reset": true, "APERTURE": 15})).unwrap();
|
|
assert_eq!((r["PICKBOX"].clone(), r["GRIPSIZE"].clone(), r["APERTURE"].clone()), (json!(3.0), json!(5.0), json!(15.0)));
|
|
}
|
|
|
|
#[test]
|
|
fn saved_profile_restores_and_hostile_entries_are_skipped() {
|
|
let mut a = Session::new();
|
|
a.execute("options", &json!({"OSMODE": 515, "ORTHOMODE": 1, "POLARANG": 15, "GRIDUNIT": [2, 2], "DYNMODE": 0, "QPMODE": 1})).unwrap();
|
|
let saved = profile(&a);
|
|
let mut b = Session::new();
|
|
restore(&mut b, &saved);
|
|
assert_eq!(profile(&b), saved);
|
|
|
|
// Unknown names, drawing variables, bad values and non-objects are ignored, never panic.
|
|
let mut c = Session::new();
|
|
restore(&mut c, &json!({"PICKBOX": "huge", "LUNITS": 4, "NOPE": 1, "POLARANG": -5, "SNAPUNIT": ["x"], "GRIPSIZE": 8}));
|
|
restore(&mut c, &json!("not an object"));
|
|
restore(&mut c, &json!(null));
|
|
let p = profile(&c);
|
|
assert_eq!((p["PICKBOX"].clone(), p["GRIPSIZE"].clone()), (json!(3.0), json!(8.0)));
|
|
assert_ne!(c.execute("getvar", &json!({"name": "LUNITS"})).ok().map(|v| v["value"].clone()), Some(json!(4)));
|
|
}
|
|
|
|
#[test]
|
|
fn typed_options_without_a_dialog_reports_how_to_change_settings() {
|
|
let mut s = Session::new();
|
|
s.cmdline("OP").unwrap();
|
|
assert!(s.log.iter().any(|l| l.contains("SETVAR")), "{:?}", s.log);
|
|
}
|
|
|
|
fn getvar(s: &mut Session, name: &str) -> serde_json::Value {
|
|
s.execute("getvar", &json!({"name": name})).unwrap()["value"].clone()
|
|
}
|
|
|
|
#[test]
|
|
fn selection_highlight_variables() {
|
|
let mut s = Session::new();
|
|
// AutoCAD's defaults: highlighted, the colour effect, preview with and without a command,
|
|
// the preview dashed and thicker.
|
|
for (name, v) in [("HIGHLIGHT", 1), ("SELECTIONEFFECT", 1), ("SELECTIONPREVIEW", 3), ("PREVIEWEFFECT", 2)] {
|
|
assert_eq!(getvar(&mut s, name), json!(v), "{name}");
|
|
}
|
|
s.execute("setvar", &json!({"name": "HIGHLIGHT", "value": 0})).unwrap();
|
|
s.execute("options", &json!({"SELECTIONEFFECT": 0, "SELECTIONPREVIEW": 2, "PREVIEWEFFECT": 1})).unwrap();
|
|
let saved = profile(&s);
|
|
assert_eq!(saved["SELECTIONEFFECT"], json!(0));
|
|
// HIGHLIGHT lasts the session only (AutoCAD doesn't save it either): not in the profile, and
|
|
// OPTIONS, which sets profile variables, refuses it.
|
|
assert!(saved.get("HIGHLIGHT").is_none());
|
|
assert!(s.execute("options", &json!({"HIGHLIGHT": 0})).is_err());
|
|
for (name, value) in [("SELECTIONEFFECT", json!(2)), ("SELECTIONPREVIEW", json!(4)), ("PREVIEWEFFECT", json!(-1)), ("PREVIEWEFFECT", json!("x"))]
|
|
{
|
|
assert!(s.execute("setvar", &json!({"name": name, "value": value})).is_err(), "{name} {value}");
|
|
}
|
|
assert_eq!(getvar(&mut s, "SELECTIONPREVIEW"), json!(2), "a refused value changes nothing");
|
|
// A new session restores the profile and starts highlighted, even from a profile saved
|
|
// with HIGHLIGHT 0 by a build that kept it.
|
|
let mut t = Session::new();
|
|
let mut old = saved.clone();
|
|
old["HIGHLIGHT"] = json!(0);
|
|
restore(&mut t, &old);
|
|
assert_eq!((getvar(&mut t, "HIGHLIGHT"), getvar(&mut t, "SELECTIONPREVIEW"), getvar(&mut t, "PREVIEWEFFECT")), (json!(1), json!(2), json!(1)));
|
|
}
|
|
|
|
#[test]
|
|
fn selection_preview_follows_its_bits() {
|
|
let mut s = Session::new();
|
|
s.settings.pickfirst = true;
|
|
s.settings.selectionpreview = 3;
|
|
assert!(s.previews_selection(), "no command, bit 1");
|
|
s.settings.selectionpreview = 2;
|
|
assert!(!s.previews_selection(), "bit 1 off");
|
|
s.start("erase").unwrap();
|
|
assert!(s.picking_objects());
|
|
assert!(s.previews_selection(), "ERASE asks for objects, bit 2");
|
|
s.settings.selectionpreview = 1;
|
|
assert!(!s.previews_selection(), "bit 2 off");
|
|
}
|
|
|
|
#[test]
|
|
fn selection_tab_variables_have_autocads_defaults_ranges_and_are_saved() {
|
|
let mut s = Session::new();
|
|
for (name, v) in [
|
|
("PREVIEWFILTER", json!(3)),
|
|
("GRIPS", json!(1)),
|
|
("GRIPOBJLIMIT", json!(100)),
|
|
("SELECTIONAREA", json!(1)),
|
|
("WINDOWAREACOLOR", json!(150)),
|
|
("CROSSINGAREACOLOR", json!(100)),
|
|
("SELECTIONAREAOPACITY", json!(25)),
|
|
] {
|
|
assert_eq!(getvar(&mut s, name), v, "{name}");
|
|
}
|
|
s.execute("options", &json!({"PREVIEWFILTER": 20, "GRIPS": 0, "GRIPOBJLIMIT": 0, "SELECTIONAREA": 0, "WINDOWAREACOLOR": 5, "CROSSINGAREACOLOR": 3, "SELECTIONAREAOPACITY": 80, "PICKSTYLE": 0})).unwrap();
|
|
for (name, value) in [
|
|
("PREVIEWFILTER", json!(64)),
|
|
("GRIPS", json!(3)),
|
|
("GRIPOBJLIMIT", json!(40_000)),
|
|
("WINDOWAREACOLOR", json!(0)),
|
|
("CROSSINGAREACOLOR", json!(256)),
|
|
("SELECTIONAREAOPACITY", json!(101)),
|
|
] {
|
|
assert!(s.execute("setvar", &json!({"name": name, "value": value})).is_err(), "{name} {value}");
|
|
}
|
|
let mut t = Session::new();
|
|
restore(&mut t, &profile(&s));
|
|
assert_eq!(
|
|
(
|
|
getvar(&mut t, "PREVIEWFILTER"),
|
|
getvar(&mut t, "GRIPS"),
|
|
getvar(&mut t, "SELECTIONAREA"),
|
|
getvar(&mut t, "WINDOWAREACOLOR"),
|
|
getvar(&mut t, "PICKSTYLE")
|
|
),
|
|
(json!(20), json!(0), json!(0), json!(5), json!(0)),
|
|
"saved with the profile"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn grips_show_up_to_the_object_limit() {
|
|
let mut s = Session::new();
|
|
assert!(s.shows_grips(100) && !s.shows_grips(101), "GRIPOBJLIMIT 100");
|
|
s.settings.gripobjlimit = 0;
|
|
assert!(s.shows_grips(100_000), "0: no limit");
|
|
s.settings.grips = 0;
|
|
assert!(!s.shows_grips(1), "GRIPS 0");
|
|
}
|
|
|
|
#[test]
|
|
fn preview_filter_excludes_each_kind_it_names() {
|
|
use cadcraft_engine::select::preview_filtered;
|
|
let mut s = Session::new();
|
|
s.execute("mtext", &json!({"at": [0, 0], "text": "NOTE", "height": 2})).unwrap();
|
|
s.execute("rectang", &json!({"p1": [10, 0], "p2": [20, 10]})).unwrap();
|
|
s.execute("hatch", &json!({"points": [[15, 5]], "pattern": "SOLID"})).unwrap();
|
|
s.execute("line", &json!({"points": [[30, 0], [40, 0]]})).unwrap();
|
|
let d = s.doc().unwrap();
|
|
let find = |k: &str| d.model.iter().find(|e| e.kind.type_name() == k).unwrap().clone();
|
|
let (mtext, hatch, line) = (find("MText"), find("Hatch"), find("Line"));
|
|
assert!(preview_filtered(d, &mtext, 8) && !preview_filtered(d, &mtext, 16));
|
|
assert!(preview_filtered(d, &hatch, 16) && !preview_filtered(d, &hatch, 8));
|
|
assert!(!preview_filtered(d, &line, 63), "a line on an unlocked layer, in no group");
|
|
// Locked layers (1) and groups (32).
|
|
let d = s.doc_mut().unwrap();
|
|
d.ensure_layer("LOCKED");
|
|
if let Some(l) = d.layers.iter_mut().find(|l| l.name == "LOCKED") {
|
|
l.locked = true;
|
|
}
|
|
d.model.modify(line.handle, |e| e.common.layer = "LOCKED".into());
|
|
d.groups.push(cadcraft_engine::doc::Group { name: "G".into(), description: String::new(), selectable: true, members: vec![mtext.handle] });
|
|
let d = s.doc().unwrap();
|
|
let line = d.entity(line.handle).unwrap();
|
|
assert!(preview_filtered(d, line, 1) && !preview_filtered(d, line, 62));
|
|
assert!(preview_filtered(d, &mtext, 32));
|
|
}
|