Files
ARCADIA-Studio/crates/oa-desktop/src/app/state_picker_escape_tests.rs
T

106 lines
4.0 KiB
Rust

//! The actual State workspace picker, App root and subscriptions.
use super::*;
use crate::behavior::canvas_workspace::tests::{Mounted, key};
use iced::{keyboard::key::Named, mouse};
async fn press_escape(mounted: &mut Mounted, app: &mut App) -> Vec<Message> {
let input = key(Named::Escape);
let (mut messages, statuses) = mounted.input_with_status(
app,
std::slice::from_ref(&input),
mouse::Cursor::Unavailable,
);
crate::app::escape::tests::subscriptions(app, input, statuses[0], &mut messages);
for message in messages.iter().cloned() {
let task = app.update(message);
mounted.perform(app, task).await;
}
mounted.settle(app).await;
messages
}
#[tokio::test]
async fn mounted_state_missing_picker_escape_preserves_exact_document_then_reopens_and_places() {
let mut f = fixture();
let diagram = create_view(&mut f).diagram;
let mut project = f.app.project().clone();
project
.diagrams
.get_mut(&diagram)
.unwrap()
.nodes
.retain(|_, node| node.element != f.b);
let mut app = App::with_project(project);
app.window_size = iced::Size::new(1800., 1100.);
send(&mut app, Message::Select(f.a));
send(&mut app, Message::Page(Page::Behavior));
let choice = Choice {
id: diagram,
label: app.project().diagrams[&diagram].name.clone(),
};
send(&mut app, Message::BehaviorDiagram(choice));
let mut mounted = Mounted::new(&mut app).await;
assert_eq!(state_edit::unplaced(app.project(), diagram), vec![f.b]);
let focus_id = iced::advanced::widget::Id::from("diagram-keyboard-owner");
let (_, canvas, _) = mounted
.geometry(&app)
.focused
.into_iter()
.find(|(id, _, _)| id.as_ref() == Some(&focus_id))
.unwrap();
// The existing picker is immediately above the measured canvas, separated
// by 8px. Its 12px text and 8px padding give a 31.6px row.
let picker = iced::Point::new(canvas.center_x(), canvas.y - 24.);
let option = iced::Point::new(picker.x, canvas.y + 8.);
let before = app.document.snapshot();
let original = app.project().clone();
let source = app.document.bundle().clone();
let selection = (
app.selected,
app.selected_node,
app.behavior.diagram.placement,
);
let camera = (
app.behavior.diagram.zoom,
app.behavior.diagram.pan,
app.behavior.diagram.fit,
);
let revision = app.document.revision();
let history = (app.document.can_undo(), app.document.can_redo());
mounted.click(&mut app, picker).await;
assert!(
press_escape(&mut mounted, &mut app).await.is_empty(),
"open picker owns Escape, not the State canvas or App"
);
assert!(std::sync::Arc::ptr_eq(&before, &app.document.snapshot()));
assert_eq!(app.document.bundle(), &source);
assert_eq!(
(
app.selected,
app.selected_node,
app.behavior.diagram.placement
),
selection
);
assert_eq!(
(
app.behavior.diagram.zoom,
app.behavior.diagram.pan,
app.behavior.diagram.fit
),
camera
);
assert_eq!(app.document.revision(), revision);
assert_eq!((app.document.can_undo(), app.document.can_redo()), history);
// If Escape left the menu open this click would close it, and the following
// option click would fail to place. This checks actual overlay dismissal.
mounted.click(&mut app, picker).await;
let messages = mounted.click(&mut app, option).await;
assert!(messages.iter().any(|message| matches!(message, Message::StateDiagram(Event::Place { element, .. }) if *element == f.b)));
assert!(state_edit::unplaced(app.project(), diagram).is_empty());
assert_eq!(app.project().elements, original.elements);
assert_eq!(app.project().relations, original.relations);
let _ = app.update(Message::Undo);
assert_eq!(app.document.bundle(), &source);
}