Files
vectorcraft/crates/engine/src/tests_printpresets.rs
T
bflatasticandClaude Opus 5.5 7c748a5e3c M4.79: print presets in the Print dialog and Edit > Print Presets
The Print dialog's Print Preset list loads [Default] or a saved preset
(reading [Custom] once the settings differ) and Save Preset... names the
settings as a preset. Edit > Print Presets... lists [Default] (generated,
protected) and the saved presets with how they differ from it; New... and
Edit... open the preset editor (the Print dialog's sections), Delete,
Import... and Export... use .vcprintpresets files, which File > Open also
imports. Commands print.presets.list/save/delete/import/export; the presets
live in Prefs.print_presets and persist with the preferences.

The open-dialog filter count test counts the new Print presets filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:30:46 +07:00

109 lines
6.6 KiB
Rust

//! Edit → Print Presets: [Default] is protected, saved presets round-trip through files and
//! persist with the preferences.
use serde_json::json;
use super::*;
use crate::cmd::printpresets::DEFAULT_PRESET;
fn is_bad_params(r: Result<serde_json::Value>) -> bool {
matches!(r, Err(EngineError::BadParams { .. }))
}
#[test]
fn default_is_listed_first_and_protected() {
let mut s = Session::new();
let v = s.execute("print.presets.list", &json!({})).unwrap();
assert_eq!((v["presets"][0]["name"].clone(), v["presets"][0]["builtIn"].clone()), (json!(DEFAULT_PRESET), json!(true)));
assert_eq!(v["presets"][0]["settings"]["copies"], 1);
assert_eq!(v["presets"][0]["changed"], json!([]));
for name in [DEFAULT_PRESET, "default", " [default] "] {
assert!(is_bad_params(s.execute("print.presets.save", &json!({"name": name, "settings": {"copies": 2}}))), "{name}");
assert!(is_bad_params(s.execute("print.presets.delete", &json!({"name": name}))), "{name}");
}
// Nor can a saved preset take its name.
s.execute("print.presets.save", &json!({"name": "Proofs"})).unwrap();
assert!(is_bad_params(s.execute("print.presets.save", &json!({"name": "Proofs", "newName": "Default"}))));
assert_eq!(s.prefs.print_presets.len(), 1);
assert!(is_bad_params(s.execute("print.presets.delete", &json!({"name": "Nope"}))));
}
#[test]
fn presets_save_change_rename_and_delete() {
let mut s = Session::new();
let v = s.execute("print.presets.save", &json!({"settings": {"media": "a4", "marks": {"trim": true}}})).unwrap();
assert_eq!((v["name"].clone(), v["created"].clone()), (json!("Print Preset 1"), json!(true)));
// A saved preset changes from its own settings; `preset` starts from another one.
let v = s.execute("print.presets.save", &json!({"name": "print preset 1", "settings": {"copies": 3}})).unwrap();
assert_eq!((v["created"].clone(), v["settings"]["media"].clone(), v["settings"]["copies"].clone()), (json!(false), json!("a4"), json!(3)));
let v = s.execute("print.presets.save", &json!({"name": "Plain", "preset": "Print Preset 1", "settings": {"marks": {"trim": false}}})).unwrap();
assert_eq!((v["settings"]["copies"].clone(), v["settings"]["marks"]["trim"].clone()), (json!(3), json!(false)));
let v = s.execute("print.presets.list", &json!({})).unwrap();
let changed: Vec<&str> = v["presets"][1]["changed"].as_array().unwrap().iter().map(|c| c["option"].as_str().unwrap()).collect();
assert_eq!(changed, ["copies", "marks.trim", "media"]);
// Renames keep the settings; bad settings and unknown bases are refused.
s.execute("print.presets.save", &json!({"name": "Plain", "newName": "Draft"})).unwrap();
assert_eq!(s.prefs.print_presets[1].name, "Draft");
assert!(is_bad_params(s.execute("print.presets.save", &json!({"name": "Draft", "newName": "print preset 1"}))));
assert!(is_bad_params(s.execute("print.presets.save", &json!({"name": "X", "settings": {"copies": 0}}))));
assert!(is_bad_params(s.execute("print.presets.save", &json!({"name": "X", "preset": "Nope"}))));
assert!(is_bad_params(s.execute("print.presets.save", &json!({"name": " "}))));
assert_eq!(s.execute("print.presets.delete", &json!({"name": "draft"})).unwrap()["deleted"], "Draft");
assert_eq!(s.prefs.print_presets.len(), 1);
}
#[test]
fn presets_export_and_import_round_trip() {
let mut s = Session::new();
s.execute("print.presets.save", &json!({"name": "Tiles", "settings": {"scaling": "tileFull", "overlap": 18}})).unwrap();
let saved = s.prefs.print_presets.clone();
let data = s.execute("print.presets.export", &json!({"names": ["Tiles", DEFAULT_PRESET]})).unwrap();
assert_eq!(data["count"], 2);
let text = data["data"].as_str().unwrap().to_string();
s.execute("print.presets.delete", &json!({"name": "Tiles"})).unwrap();
let r = s.execute("print.presets.import", &json!({"data": text})).unwrap();
assert_eq!(r["imported"], json!(["Tiles", "Default 2"]), "[Default] comes in as a saved copy");
assert_eq!(s.prefs.print_presets[0], saved[0], "the same preset comes back");
assert_eq!(s.prefs.print_presets[1].settings, vectorcraft_pdf::PrintSettings::default());
// replace: saved presets of the same names are overwritten.
let r = s.execute("print.presets.import", &json!({"data": text, "replace": true})).unwrap();
assert_eq!(r["imported"], json!(["Tiles", "Default 3"]));
assert_eq!(s.prefs.print_presets.len(), 3);
// Through a file, and every saved preset by default.
let path = std::env::temp_dir().join(format!("vc-printpresets-{}.vcprintpresets", std::process::id())).to_string_lossy().to_string();
assert_eq!(s.execute("print.presets.export", &json!({"path": path})).unwrap()["count"], 3);
let mut t = Session::new();
assert_eq!(t.execute("print.presets.import", &json!({"path": path})).unwrap()["imported"].as_array().unwrap().len(), 3);
assert_eq!(t.prefs.print_presets, s.prefs.print_presets);
let _ = std::fs::remove_file(&path);
// Not a presets file, or values out of range: refused, nothing added.
for bad in [
json!({"data": "{}"}),
json!({"data": "{\"format\": \"vcpdfpresets\", \"presets\": []}"}),
json!({"data": "{\"format\": \"vcprintpresets\", \"presets\": [{\"name\": \"X\", \"settings\": {\"copies\": 5000}}]}"}),
json!({"data": "{\"format\": \"vcprintpresets\", \"presets\": [{\"name\": \"X\", \"settings\": {\"media\": \"quarto\"}}]}"}),
json!({"dataBase64": "!!"}),
json!({}),
] {
assert!(is_bad_params(t.execute("print.presets.import", &bad)), "{bad}");
}
assert_eq!(t.prefs.print_presets.len(), 3);
assert!(is_bad_params(Session::new().execute("print.presets.export", &json!({}))), "nothing saved to export");
assert!(is_bad_params(Session::new().execute("print.presets.export", &json!({"names": ["Nope"]}))));
}
#[test]
fn saved_presets_persist_with_the_preferences() {
let mut s = Session::new();
s.execute("print.presets.save", &json!({"name": "Kept", "settings": {"copies": 2}})).unwrap();
let back: crate::Prefs = serde_json::from_value(s.prefs.to_json()).unwrap();
assert_eq!(back.print_presets, s.prefs.print_presets);
// Resetting the preferences keeps them (a library, not a preference).
s.execute("prefs.reset", &json!({})).unwrap();
assert_eq!(s.prefs.print_presets.len(), 1);
// Preferences saved before print presets existed still load, and none are written while empty.
let old: crate::Prefs = serde_json::from_value(json!({"keyboardIncrement": 2.0})).unwrap();
assert!(old.print_presets.is_empty());
assert!(crate::Prefs::default().to_json().get("printPresets").is_none());
}