Test Process and Allocation stale gestures after real Text Apply

This commit is contained in:
2026-09-24 01:17:40 -07:00
parent 62d3ffe9cb
commit 542b10ac58
2 changed files with 304 additions and 0 deletions
@@ -144,6 +144,151 @@ fn marker(app: &mut App, owner: Id, occurrence: Id) {
assert!(app.diagram_focus(Surface::Process(owner)).is_some());
}
#[test]
fn completed_text_apply_rejects_captured_process_reorder_without_retiring_current_state() {
for layer in [Layer::Oa, Layer::Sa] {
let mut f = fixture(layer);
pair(&mut f);
let stale = f.app.multiselect_snapshot().unwrap();
let before = f.app.document.snapshot();
assert!(!f.app.document.can_undo());
let element = f.nodes[0];
let location = f.app.document.compiled().index.declarations[&element].clone();
let original = &before.bundle.files[&location.path];
let quoted_name = format!("\"{}\"", f.app.project().elements[&element].name);
assert_eq!(original.matches(quoted_name.as_str()).count(), 1);
let edited = original.replace(quoted_name.as_str(), "\"Changed through Text\"");
let mut expected = before.decoded.project.clone();
expected.elements.get_mut(&element).unwrap().name = "Changed through Text".into();
let mut expected_bundle = before.bundle.clone();
expected_bundle
.files
.insert(location.path.clone(), edited.clone());
let _ = f.app.update(Message::Page(Page::Text));
let _ = f.app.update(Message::SourceFile(location.path));
let _ = f
.app
.update(Message::SourceEdit(text_editor::Action::SelectAll));
let _ = f.app.update(Message::SourceEdit(text_editor::Action::Edit(
text_editor::Edit::Paste(Arc::new(edited.clone())),
)));
assert!(f.app.source_dirty());
assert_eq!(f.app.source_editor.text(), edited);
assert!(Arc::ptr_eq(&before, &f.app.document.snapshot()));
let _ = f.app.update(Message::ApplySource);
assert!(!f.app.source_dirty(), "{}", f.app.status);
assert_eq!(f.app.project(), &expected);
assert_eq!(f.app.document.bundle(), &expected_bundle);
source_matches(&f.app);
let _ = f.app.update(Message::Page(Page::Behavior));
assert_eq!(f.app.topology_context().unwrap().owner, f.owner);
pair(&mut f);
let current = f.app.multiselect_snapshot().unwrap();
assert_eq!(current.targets(), stale.targets());
assert_eq!(current.primary(), stale.primary());
assert_ne!(current.context(), stale.context());
let destination = Destination::After(f.nodes[2]);
assert!(
matches!(
Prepared::new(f.app.project(), f.owner, current.targets())
.unwrap()
.plan(destination)
.unwrap(),
Plan::Change(_)
),
"the replay must be a real reorder, not a no-op"
);
assert!(
f.app
.multiselect_envelope(&Event::ProcessReorder(current.clone(), destination))
);
let accepted = f.app.document.snapshot();
let revision = f.app.document.revision();
let workspace = f.app.source_workspace.bundle();
let editor = f.app.source_editor.text();
let selected = (
f.app.selected,
f.app.selected_node,
f.app.selected_bend,
f.app.selected_attachment,
);
let camera = (f.app.zoom, f.app.pan, f.app.fit_to_view, f.app.canvas_size);
let process_camera = f.app.behavior.topology.camera_boundary();
let epochs = (
f.app.canvas_epoch,
f.app.camera_epoch,
f.app.allocation_drag.epoch,
);
let draft = f
.app
.draft
.as_ref()
.map(|d| serde_json::to_value(d.recovery_snapshot()).unwrap());
let form = f.app.behavior.recovery_snapshot();
let status = f.app.status.clone();
let pending_reveal = f.app.pending_diagram_reveal.clone();
send(&mut f.app, Event::ProcessReorder(stale, destination));
assert!(Arc::ptr_eq(&accepted, &f.app.document.snapshot()));
assert_eq!(f.app.project(), &expected);
assert_eq!(f.app.document.bundle(), &expected_bundle);
assert_eq!(f.app.document.revision(), revision);
assert_eq!(f.app.source_workspace.bundle(), workspace);
assert_eq!(f.app.source_editor.text(), editor);
assert_eq!(f.app.multiselect_snapshot(), Some(current));
assert_eq!(
(
f.app.selected,
f.app.selected_node,
f.app.selected_bend,
f.app.selected_attachment
),
selected
);
assert_eq!(
(f.app.zoom, f.app.pan, f.app.fit_to_view, f.app.canvas_size),
camera
);
assert!(f.app.behavior.topology.camera_boundary() == process_camera);
assert_eq!(
(
f.app.canvas_epoch,
f.app.camera_epoch,
f.app.allocation_drag.epoch
),
epochs
);
assert_eq!(
f.app
.draft
.as_ref()
.map(|d| serde_json::to_value(d.recovery_snapshot()).unwrap()),
draft
);
assert_eq!(f.app.behavior.recovery_snapshot(), form);
assert_eq!(f.app.pending_diagram_reveal, pending_reveal);
assert_eq!(f.app.status, status);
assert!(!f.app.source_dirty());
assert!(f.app.document.can_undo());
assert!(!f.app.document.can_redo());
let _ = f.app.update(Message::Undo);
assert_eq!(f.app.project(), &before.decoded.project);
assert_eq!(f.app.document.bundle(), &before.bundle);
assert!(!f.app.document.can_undo());
assert!(f.app.document.can_redo());
source_matches(&f.app);
let _ = f.app.update(Message::Redo);
assert_eq!(f.app.project(), &expected);
assert_eq!(f.app.document.bundle(), &expected_bundle);
assert!(f.app.document.can_undo());
assert!(!f.app.document.can_redo());
source_matches(&f.app);
}
}
#[test]
fn process_group_reverse_click_order_changes_only_owner_steps_and_undoes_once() {
for layer in [Layer::Oa, Layer::Sa] {