Save unverified allocation and repair work at user-requested pause
This commit is contained in:
@@ -132,7 +132,7 @@ fn mounted_oa_sa_ordered_incoming_between_outgoing_are_exact_single_history_step
|
||||
let mut f = fixture(layer);
|
||||
let original = f.app.project().clone();
|
||||
let original_source = f.app.document.bundle().clone();
|
||||
drag(&mut f, screen(xy(160., 140.)));
|
||||
drag(&mut f, screen(xy(160., 190.)));
|
||||
assert_eq!(f.app.document.revision(), 1, "{}", f.app.status);
|
||||
let relation = f
|
||||
.app
|
||||
@@ -150,7 +150,7 @@ fn mounted_oa_sa_ordered_incoming_between_outgoing_are_exact_single_history_step
|
||||
assert!(!f.app.document.can_undo());
|
||||
let _ = f.app.update(Message::Redo);
|
||||
assert_eq!(f.app.document.bundle(), &after_in);
|
||||
drag(&mut f, screen(xy(960., 140.)));
|
||||
drag(&mut f, screen(xy(960., 190.)));
|
||||
let reassigned = &f.app.project().relations[&relation.id];
|
||||
assert_eq!(reassigned.source(), f.b, "{}", f.app.status);
|
||||
assert_eq!(reassigned.name, relation.name);
|
||||
@@ -208,7 +208,7 @@ fn mounted_dirty_property_press_does_not_select_apply_or_destroy_draft() {
|
||||
let input = &f.app.draft.as_ref().unwrap().inputs["/name"];
|
||||
let raw = input.raw.clone();
|
||||
let cursor = input.editor.cursor();
|
||||
let events = batch(&f.app, start(&f), screen(xy(160., 140.)));
|
||||
let events = batch(&f.app, start(&f), screen(xy(160., 190.)));
|
||||
assert!(matches!(
|
||||
events.first(),
|
||||
Some(Message::WorkDrag(Event::Refused(..)))
|
||||
@@ -256,7 +256,7 @@ fn source_and_modal_admission_reject_prebuilt_clean_press_without_selecting() {
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Release(
|
||||
p.stamp,
|
||||
p.token,
|
||||
Some(screen(xy(160., 140.))),
|
||||
Some(screen(xy(160., 190.))),
|
||||
)));
|
||||
assert_eq!(f.app.selected, selection);
|
||||
assert_eq!(f.app.document.bundle(), &source);
|
||||
@@ -302,7 +302,7 @@ fn modal_roundtrip_equal_fit_undo_resize_and_focus_retire_press_before_replay()
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Release(
|
||||
p.stamp,
|
||||
p.token,
|
||||
Some(screen(xy(160., 140.))),
|
||||
Some(screen(xy(160., 190.))),
|
||||
)));
|
||||
assert_eq!(f.app.document.bundle(), &before);
|
||||
assert!(!f.app.document.can_undo());
|
||||
@@ -321,7 +321,7 @@ fn stale_packets_do_not_cancel_a_newer_token_and_each_release_is_consumed_once()
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Preview(
|
||||
old.stamp,
|
||||
old.token,
|
||||
Some(screen(xy(160., 140.))),
|
||||
Some(screen(xy(160., 190.))),
|
||||
)));
|
||||
assert_eq!(
|
||||
f.app.allocation_drag.active.as_ref().unwrap().press.token,
|
||||
@@ -330,7 +330,7 @@ fn stale_packets_do_not_cancel_a_newer_token_and_each_release_is_consumed_once()
|
||||
let release = Message::WorkDrag(Event::Release(
|
||||
new.stamp,
|
||||
new.token,
|
||||
Some(screen(xy(160., 140.))),
|
||||
Some(screen(xy(160., 190.))),
|
||||
));
|
||||
let _ = f.app.update(release.clone());
|
||||
let revision = f.app.document.revision();
|
||||
@@ -370,7 +370,7 @@ fn arrange_is_one_gesture_and_snapped_noop_preserves_redo_and_source() {
|
||||
#[test]
|
||||
fn outside_release_is_cancel_and_does_not_remove_an_assignment() {
|
||||
let mut f = fixture(Layer::Oa);
|
||||
drag(&mut f, screen(xy(160., 140.)));
|
||||
drag(&mut f, screen(xy(160., 190.)));
|
||||
let before = f.app.document.bundle().clone();
|
||||
let revision = f.app.document.revision();
|
||||
drag(
|
||||
@@ -386,8 +386,8 @@ fn candidate_semantics_are_cached_per_destination_with_stable_ids_and_own_index(
|
||||
let mut f = fixture(Layer::Oa);
|
||||
let p = press(&f);
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Press(p.clone())));
|
||||
let a = screen(xy(160., 140.));
|
||||
let b = screen(xy(960., 140.));
|
||||
let a = screen(xy(160., 190.));
|
||||
let b = screen(xy(960., 190.));
|
||||
let _ = f
|
||||
.app
|
||||
.update(Message::WorkDrag(Event::Preview(p.stamp, p.token, Some(a))));
|
||||
@@ -508,8 +508,8 @@ fn frozen_targets_use_half_open_semantic_priority_and_refuse_incomparable_overla
|
||||
fn release_uses_ordered_native_position_before_later_motion_in_same_batch() {
|
||||
let mut f = fixture(Layer::Oa);
|
||||
let from = start(&f);
|
||||
let a = screen(xy(160., 140.));
|
||||
let b = screen(xy(960., 140.));
|
||||
let a = screen(xy(160., 190.));
|
||||
let b = screen(xy(960., 190.));
|
||||
let mut state = CanvasState::default();
|
||||
let canvas = canvas(&f.app);
|
||||
let events: Vec<_> = [
|
||||
@@ -603,7 +603,7 @@ fn source_refusal_is_atomic_and_a_new_gesture_can_retry_against_live_revision()
|
||||
f.app.document = crate::document::Document::from_bundle(before.clone(), limits).unwrap();
|
||||
f.app.sync();
|
||||
let snapshot = f.app.document.snapshot();
|
||||
drag(&mut f, screen(xy(160., 140.)));
|
||||
drag(&mut f, screen(xy(160., 190.)));
|
||||
assert!(Arc::ptr_eq(&snapshot, &f.app.document.snapshot()));
|
||||
assert_eq!(f.app.document.bundle(), &before);
|
||||
assert!(!f.app.document.can_undo());
|
||||
@@ -611,7 +611,7 @@ fn source_refusal_is_atomic_and_a_new_gesture_can_retry_against_live_revision()
|
||||
assert!(f.app.allocation_drag.active.is_none());
|
||||
f.app.document = crate::document::Document::from_bundle(before, Default::default()).unwrap();
|
||||
f.app.sync();
|
||||
drag(&mut f, screen(xy(160., 140.)));
|
||||
drag(&mut f, screen(xy(160., 190.)));
|
||||
assert_eq!(
|
||||
validation::effective_performer(f.app.project(), f.work),
|
||||
Some(f.a),
|
||||
@@ -656,7 +656,7 @@ fn mounted_role_only_outgoing_refusal_retains_placement_and_same_performer_creat
|
||||
.find(|t| t.element == f.a)
|
||||
.unwrap()
|
||||
.region;
|
||||
drag(&mut f, screen(xy(target.x + 45., target.y + 40.)));
|
||||
drag(&mut f, screen(xy(target.x + 45., target.y + 100.)));
|
||||
assert_eq!(f.app.document.revision(), 1, "{}", f.app.status);
|
||||
assert_eq!(f.app.project().relations, relations);
|
||||
assert!(
|
||||
@@ -686,7 +686,7 @@ fn mounted_uniform_parent_moves_hidden_placements_and_assigns_only_leaves() {
|
||||
.collapsed = true;
|
||||
replace(&mut f, project);
|
||||
let before = f.app.project().diagrams[&f.diagram].nodes.clone();
|
||||
drag(&mut f, screen(xy(960., 140.)));
|
||||
drag(&mut f, screen(xy(960., 190.)));
|
||||
assert_eq!(f.app.document.revision(), 1, "{}", f.app.status);
|
||||
let after = &f.app.project().diagrams[&f.diagram].nodes;
|
||||
let dx = after[&f.node].position.x - before[&f.node].position.x;
|
||||
@@ -805,7 +805,7 @@ fn pending_behavior_draft_refuses_actual_work_press_and_equal_document_replaceme
|
||||
crate::behavior::Event::Creation(crate::behavior::creation::Event::Open(Layer::Oa)),
|
||||
);
|
||||
assert!(f.app.behavior.has_pending());
|
||||
let events = batch(&f.app, start(&f), screen(xy(160., 140.)));
|
||||
let events = batch(&f.app, start(&f), screen(xy(160., 190.)));
|
||||
assert!(matches!(
|
||||
events.first(),
|
||||
Some(Message::WorkDrag(Event::Refused(..)))
|
||||
@@ -823,7 +823,7 @@ fn pending_behavior_draft_refuses_actual_work_press_and_equal_document_replaceme
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Release(
|
||||
p.stamp,
|
||||
p.token,
|
||||
Some(screen(xy(160., 140.))),
|
||||
Some(screen(xy(160., 190.))),
|
||||
)));
|
||||
assert_eq!(f.app.document.bundle(), &source);
|
||||
assert!(!f.app.document.can_undo());
|
||||
@@ -854,7 +854,7 @@ fn actual_canvas_origin_change_cancels_held_work_before_any_legacy_release() {
|
||||
&mut state,
|
||||
&canvas::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)),
|
||||
moved_bounds,
|
||||
mouse::Cursor::Available(screen(xy(160., 140.))),
|
||||
mouse::Cursor::Available(screen(xy(160., 190.))),
|
||||
)
|
||||
.and_then(|a| a.into_inner().0)
|
||||
.unwrap();
|
||||
@@ -953,3 +953,92 @@ fn toolbar_status_leaves_transformed_top_edge_frozen_target_label_readable() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oa_sa_label_overlap_refuses_preview_release_and_retries_without_partial_source_or_history() {
|
||||
for layer in [Layer::Oa, Layer::Sa] {
|
||||
for (zoom, pan) in [
|
||||
(1., Vector::ZERO),
|
||||
(0.75, Vector::new(37., -15.)),
|
||||
(1.25, Vector::new(-30., 23.)),
|
||||
] {
|
||||
let mut f = fixture(layer);
|
||||
let mut project = f.app.project().clone();
|
||||
project.elements.get_mut(&f.a).unwrap().name = "Receiver".into();
|
||||
replace(&mut f, project);
|
||||
// Refusals must also preserve an existing redo branch.
|
||||
let _ = f.app.update(Message::Command(Command::Rename(f.work, "Temporary".into())));
|
||||
let _ = f.app.update(Message::Undo);
|
||||
f.app.zoom = zoom;
|
||||
f.app.pan = pan;
|
||||
f.app.fit_to_view = false;
|
||||
let screen = |world: Position| Point::new(
|
||||
bounds().x + world.x * zoom + pan.x,
|
||||
bounds().y + world.y * zoom + pan.y,
|
||||
);
|
||||
let from = screen(xy(140., 535.));
|
||||
let overlap = screen(xy(160., 140.));
|
||||
let clear = screen(xy(160., 190.));
|
||||
let accepted = f.app.project().clone();
|
||||
let source = f.app.document.bundle().clone();
|
||||
let snapshot = f.app.document.snapshot();
|
||||
let revision = f.app.document.revision();
|
||||
let mut events = batch(&f.app, from, overlap);
|
||||
let release = events.pop().unwrap();
|
||||
send(&mut f.app, events);
|
||||
assert!(f.app.allocation_drag.preview.is_none());
|
||||
let feedback = f.app.allocation_drag.feedback.as_ref().unwrap();
|
||||
assert!(feedback.refused, "{}", feedback.text);
|
||||
assert!(feedback.text.contains("Aim below or beside"));
|
||||
assert_eq!(feedback.press.frozen.targets[feedback.targets[0]].element, f.a);
|
||||
assert_eq!(f.app.project(), &accepted);
|
||||
assert_eq!(f.app.document.bundle(), &source);
|
||||
assert!(Arc::ptr_eq(&snapshot, &f.app.document.snapshot()));
|
||||
assert!(!f.app.document.can_undo());
|
||||
assert!(f.app.document.can_redo());
|
||||
let _ = f.app.update(release);
|
||||
assert!(f.app.allocation_drag.active.is_none());
|
||||
assert!(f.app.allocation_drag.preview.is_none());
|
||||
assert_eq!(f.app.project(), &accepted);
|
||||
assert_eq!(f.app.document.bundle(), &source);
|
||||
assert_eq!(f.app.document.revision(), revision);
|
||||
assert!(Arc::ptr_eq(&snapshot, &f.app.document.snapshot()));
|
||||
assert!(!f.app.document.can_undo());
|
||||
assert!(f.app.document.can_redo());
|
||||
|
||||
// In a new gesture, moving out of the collision reuses its semantic
|
||||
// candidate and stable allocation identity; only geometry changes.
|
||||
let mut events = batch(&f.app, from, overlap);
|
||||
events.pop();
|
||||
send(&mut f.app, events);
|
||||
let active = f.app.allocation_drag.active.as_ref().unwrap();
|
||||
let p = active.press.clone();
|
||||
let semantic = active.cache[0].1.as_ref().unwrap().clone();
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Preview(p.stamp, p.token, Some(clear))));
|
||||
let preview = f.app.allocation_drag.preview.as_ref().expect(&f.app.status);
|
||||
assert!(Arc::ptr_eq(&semantic, &preview.semantic));
|
||||
assert_eq!(preview.placement.diagram.nodes[&f.node].position, xy(120., 160.));
|
||||
assert_eq!(preview.placement.view, projection::project_diagram_with_index(
|
||||
semantic.project(), &preview.placement.diagram, semantic.index(),
|
||||
));
|
||||
let mut expected = semantic.project().clone();
|
||||
expected.diagrams.insert(f.diagram, preview.placement.diagram.clone());
|
||||
assert_eq!(f.app.project(), &accepted);
|
||||
assert_eq!(f.app.document.bundle(), &source);
|
||||
let _ = f.app.update(Message::WorkDrag(Event::Release(p.stamp, p.token, Some(clear))));
|
||||
assert_eq!(f.app.project(), &expected, "{}", f.app.status);
|
||||
assert_eq!(f.app.document.revision(), revision + 1);
|
||||
assert!(f.app.document.can_undo());
|
||||
assert!(!f.app.document.can_redo());
|
||||
let after = f.app.document.bundle().clone();
|
||||
assert_eq!(oa_core::source_project::compile_bundle(&after, Default::default()).unwrap().decoded.project, expected);
|
||||
let _ = f.app.update(Message::Undo);
|
||||
assert_eq!(f.app.project(), &accepted);
|
||||
assert_eq!(f.app.document.bundle(), &source);
|
||||
assert!(!f.app.document.can_undo());
|
||||
let _ = f.app.update(Message::Redo);
|
||||
assert_eq!(f.app.project(), &expected);
|
||||
assert_eq!(f.app.document.bundle(), &after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user