Files
lightcraft/crates/ui-egui/src/tests_copy_paste_dialogs.rs
T
Jason Baldwin bbcbbebf8e LR-EDIT-COPY-PASTE: Enter applies the Copy and Paste Settings dialogs (#735)
Return presses OK in Choose Edit Settings to Copy and Paste Selected
Settings when no widget has the keyboard focus (a Tab-focused button or
checkbox takes Return itself, as egui does). Esc already cancelled them;
tests now cover both keys.
2026-10-10 16:49:39 +02:00

92 lines
3.4 KiB
Rust

//! Return presses OK in Copy Settings (⇧⌘C) and Paste Selected Settings (⇧⌘V); Esc cancels (#735).
use std::time::Duration;
use lightcraft_catalog::PhotoId;
use serde_json::{Value, json};
use crate::LightcraftApp;
use crate::headless::Headless;
use crate::state::Dialog;
const SETTLE: Duration = Duration::from_secs(120);
const T: Duration = Duration::from_secs(10);
/// The demo library with an edited first photo selected; returns the first two photos' ids.
fn edited() -> (Headless, [u64; 2]) {
let services = crate::Services { png: None, ..Default::default() };
let mut app = LightcraftApp::new(lightcraft_engine::Session::with_demo(), services);
app.ui.view = crate::state::ViewMode::PhotoGrid;
let mut h = Headless::new(app, [1200.0, 900.0], 1.0);
let ids: Vec<u64> = h.app.session.visible_cloned().iter().take(2).map(|p| p.0).collect();
let ids = [ids[0], ids[1]];
exec(&mut h, "library.select", json!({"ids": [ids[0]]}));
exec(&mut h, "develop.set", json!({"values": {"light.exposure": 1.0, "color.vibrance": 30}}));
(h, ids)
}
fn exec(h: &mut Headless, command: &str, params: Value) {
let r = h.request("engine.execute", json!({"command": command, "params": params}), T);
assert_eq!(r["ok"], true, "{command}: {r}");
}
fn key(h: &mut Headless, k: Value) {
let r = h.request("ui.key", k.clone(), T);
assert_eq!(r["ok"], true, "{k}: {r}");
h.settle(SETTLE);
}
fn copy_dialog(h: &mut Headless) {
key(h, json!({"key": "C", "cmd": true, "shift": true}));
assert!(matches!(h.app.ui.dialog, Some(Dialog::CopySettings { .. })), "dialog not open: {:?}", h.app.ui.dialog);
}
/// Copies light and colour from the first photo, selects the second and opens ⇧⌘V.
fn paste_dialog(h: &mut Headless, ids: [u64; 2]) {
exec(h, "develop.copy", json!({"groups": ["light", "color"]}));
exec(h, "library.select", json!({"ids": [ids[1]]}));
key(h, json!({"key": "V", "cmd": true, "shift": true}));
assert!(matches!(h.app.ui.dialog, Some(Dialog::PasteSettings { .. })), "dialog not open: {:?}", h.app.ui.dialog);
}
fn exposure(h: &Headless, id: u64) -> f64 {
h.app.session.develop_of(PhotoId(id)).map(|d| d.light.exposure).unwrap_or_default()
}
#[test]
fn return_copies_the_chosen_settings() {
let (mut h, _) = edited();
copy_dialog(&mut h);
assert!(h.app.session.clipboard.is_none());
key(&mut h, json!({"key": "Enter"}));
assert!(h.app.ui.dialog.is_none(), "Return closes the dialog");
assert!(h.app.session.clipboard.is_some(), "Return copies the settings");
}
#[test]
fn escape_closes_copy_settings_without_copying() {
let (mut h, _) = edited();
copy_dialog(&mut h);
key(&mut h, json!({"key": "Escape"}));
assert!(h.app.ui.dialog.is_none(), "Esc closes the dialog");
assert!(h.app.session.clipboard.is_none(), "Esc copies nothing");
}
#[test]
fn return_pastes_into_the_selected_photos() {
let (mut h, ids) = edited();
paste_dialog(&mut h, ids);
key(&mut h, json!({"key": "Enter"}));
assert!(h.app.ui.dialog.is_none(), "Return closes the dialog");
assert_eq!(exposure(&h, ids[1]), 1.0, "Return pastes the settings");
}
#[test]
fn escape_closes_paste_settings_without_pasting() {
let (mut h, ids) = edited();
paste_dialog(&mut h, ids);
key(&mut h, json!({"key": "Escape"}));
assert!(h.app.ui.dialog.is_none(), "Esc closes the dialog");
assert_eq!(exposure(&h, ids[1]), 0.0, "Esc pastes nothing");
}