Files
cadcraft/crates/engine/tests/it/layoff_repeat.rs
T
aiongg 9cf115e808 CI: one test binary per crate, nextest, line tables only (#1989)
* 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
2026-10-23 13:34:26 -04:00

95 lines
4.3 KiB
Rust

//! LAYOFF stays active until Enter or Esc (#1418): every pick turns off its object's layer and the
//! prompt comes straight back, the way AutoCAD's Layer Off works.
use cadcraft_engine::doc::Handle;
use cadcraft_engine::{Input, Session};
use serde_json::json;
/// The handles of the objects on `layer`.
fn on_layer(s: &Session, layer: &str) -> Vec<Handle> {
s.doc().unwrap().model.iter().filter(|e| e.common.layer == layer).map(|e| e.handle).collect()
}
/// Three lines, one on layer "A", one on "B" and one on "0" (the current layer).
fn session_with_three_layers() -> Session {
let mut s = Session::new();
s.execute("layer.new", &json!({ "name": "A", "current": true })).unwrap();
s.execute("line", &json!({ "points": [[0, 0], [10, 0]] })).unwrap();
s.execute("layer.new", &json!({ "name": "B", "current": true })).unwrap();
s.execute("line", &json!({ "points": [[0, 5], [10, 5]] })).unwrap();
s.execute("layer.current", &json!({ "name": "0" })).unwrap();
s.execute("line", &json!({ "points": [[0, 10], [10, 10]] })).unwrap();
s
}
fn is_on(s: &Session, layer: &str) -> bool {
s.doc().unwrap().layer(layer).unwrap().on
}
#[test]
fn layoff_keeps_asking_until_enter() {
let mut s = session_with_three_layers();
let undo_before = s.state().unwrap().undo.len();
s.start("layoff").unwrap();
assert!(s.prompt_text().contains("layer to be turned off"), "{}", s.prompt_text());
// The first pick turns off its layer's object and the command stays active (#1418).
s.input(Input::Pick(on_layer(&s, "A"))).unwrap();
assert!(s.running.is_some(), "LAYOFF is still running: {}", s.prompt_text());
assert!(s.prompt_text().contains("layer to be turned off"), "it asks again: {}", s.prompt_text());
assert!(!is_on(&s, "A"), "the picked object's layer is off");
assert!(is_on(&s, "B"), "no other layer was touched");
// The second pick turns off the second layer as well, without the command ending.
s.input(Input::Pick(on_layer(&s, "B"))).unwrap();
assert!(s.running.is_some(), "LAYOFF is still running: {}", s.prompt_text());
assert!(!is_on(&s, "B"), "the second object's layer is off");
assert!(is_on(&s, "0"), "the layer nothing was picked on is untouched");
// Enter ends it, and the whole run is one undo step.
s.input(Input::Enter).unwrap();
assert!(s.running.is_none(), "Enter ends LAYOFF: {}", s.prompt_text());
assert_eq!(s.state().unwrap().undo.len(), undo_before + 1, "one undo step for the whole run");
s.undo().unwrap();
assert!(is_on(&s, "A") && is_on(&s, "B"), "one undo takes both layers back");
}
#[test]
fn esc_ends_layoff_and_keeps_what_it_turned_off() {
let mut s = session_with_three_layers();
let undo_before = s.state().unwrap().undo.len();
s.start("layoff").unwrap();
s.input(Input::Pick(on_layer(&s, "A"))).unwrap();
s.input(Input::Cancel).unwrap();
assert!(s.running.is_none(), "Esc ends LAYOFF: {}", s.prompt_text());
assert!(!is_on(&s, "A"), "the layer turned off before Esc stays off");
assert_eq!(s.state().unwrap().undo.len(), undo_before + 1, "one undo step, the LAYOFF command");
}
#[test]
fn an_empty_pick_keeps_layoff_running() {
let mut s = session_with_three_layers();
s.start("layoff").unwrap();
// A window that finds nothing is not a pick: the prompt stays and nothing is turned off.
s.input(Input::Pick(Vec::new())).unwrap();
assert!(s.running.is_some(), "{}", s.prompt_text());
assert!(s.log.iter().any(|l| l.contains("0 found")), "{:?}", s.log);
assert!(is_on(&s, "A") && is_on(&s, "B") && is_on(&s, "0"));
s.input(Input::Pick(on_layer(&s, "A"))).unwrap();
assert!(s.running.is_some() && !is_on(&s, "A"));
}
/// A pickfirst selection still acts at once and ends the command, and the JSON form never prompts.
#[test]
fn pickfirst_and_json_calls_are_unchanged() {
let mut s = session_with_three_layers();
let a = on_layer(&s, "A");
s.set_selection(a);
s.start("layoff").unwrap();
assert!(s.running.is_none(), "pickfirst: no prompt");
assert!(!is_on(&s, "A"), "{:?}", s.log);
let mut s = session_with_three_layers();
s.execute("layoff", &json!({ "handles": on_layer(&s, "B").iter().map(|h| h.hex()).collect::<Vec<_>>() })).unwrap();
assert!(s.running.is_none(), "the JSON form must not prompt");
assert!(!is_on(&s, "B"));
}