diff --git a/crates/oa-desktop/src/app/scenario_reorder/tests.rs b/crates/oa-desktop/src/app/scenario_reorder/tests.rs index 67fe3ed7..a5bc5308 100644 --- a/crates/oa-desktop/src/app/scenario_reorder/tests.rs +++ b/crates/oa-desktop/src/app/scenario_reorder/tests.rs @@ -78,6 +78,8 @@ fn setup(saved: bool) -> (App, Id, [Id; 4]) { id: diagram, label: "Saved".into(), })); + } else { + let _ = app.update(Message::Page(Page::Behavior)); } for (id, choice) in [ (f.reply, multiselect::Choice::Replace), @@ -335,11 +337,11 @@ fn temporal_refusal_is_terminal_without_model_or_history_change() { } #[test] -fn source_write_refusal_is_atomic_and_dirty_properties_block_begin() { - let (mut app, owner, _) = setup(true); +fn exact_source_budget_permutation_preserves_trivia_and_dirty_properties_block_begin() { + let (mut app, owner, [a, b, x, y]) = setup(true); let mut bundle = app.document.bundle().clone(); - // A legal compact authored list is smaller than the source writer's new - // canonical list. The exact source budget forces a real write failure. + // Reordering existing list chunks preserves their authored trivia and byte + // count; an exact budget is not a source-write failure injection. for text in bundle.files.values_mut() { *text = text .split_inclusive('\n') @@ -369,20 +371,38 @@ fn source_write_refusal_is_atomic_and_dirty_properties_block_begin() { let epoch = app.canvas_epoch; finish(&mut app, slot); assert!( - app.status.starts_with("Reorder was not applied:"), + app.status.starts_with("Semantic order updated."), "{}", app.status ); assert_ne!(app.canvas_epoch, epoch); - assert_eq!(app.project(), &baseline.decoded.project); - assert_eq!(app.document.bundle(), &baseline.bundle); + let mut expected = baseline.decoded.project.clone(); + *expected + .elements + .get_mut(&owner) + .unwrap() + .steps_mut() + .unwrap() = vec![x, y, a, b]; + assert_eq!(app.project(), &expected); + assert_eq!( + app.document + .bundle() + .files + .values() + .map(String::len) + .sum::(), + limits.model.max_source_bytes + ); assert_eq!( app.multiselect_snapshot().unwrap().targets(), selection.targets() ); assert_eq!(app.selected, primary); assert!(camera == app.behavior.scenario.camera_boundary()); - assert!(!app.document.can_undo()); + assert!(app.document.can_undo()); + let _ = app.update(Message::Undo); + assert_eq!(app.project(), &baseline.decoded.project); + assert_eq!(app.document.bundle(), &baseline.bundle); let _ = app.update(Message::Field("/name".into(), "Unapplied name".into())); assert!(app.draft_dirty()); let event = packet(&app, Intent::Begin);