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

185 lines
6.9 KiB
Rust

//! Accepted semantic review keeps selection, layer and visible diagram coherent.
use super::*;
use crate::{
semantic_review::{RowEvent, State},
workflow::{Event, Workflow},
};
fn send(app: &mut App, message: Message) {
let _ = app.update(message);
}
fn state(app: &App) -> &State {
let Some(Workflow::Semantic(state)) = &app.workflow else {
panic!("{}", app.status)
};
state
}
fn row_event(app: &mut App, event: RowEvent) {
let event = state(app).address_event(event);
send(app, Message::Workflow(Event::Semantic(event)));
}
fn fixture(reverse: bool, destination_view: bool) -> (App, Id, Id, Id, Option<Id>) {
let mut p = Project::empty();
let oa = p
.add_element(Kind::Activity, Layer::Oa, "Confirm stable pressure", None)
.unwrap();
let sa = p
.add_element(Kind::Function, Layer::Sa, "Confirm safe pressure", None)
.unwrap();
let trace = Id::new_v4();
p.traces.insert(
trace,
Trace {
id: trace,
alias: "confirm_trace".into(),
name: "Confirmation refinement".into(),
description: String::new(),
oa,
sa,
kind: TraceKind::Refinement,
baseline: None,
},
);
let (source, target, source_layer, target_layer) = if reverse {
(sa, oa, Layer::Sa, Layer::Oa)
} else {
(oa, sa, Layer::Oa, Layer::Sa)
};
let from = p.ensure_diagram(source_layer);
p.place(from, source, Position { x: 91., y: 143. });
let to = destination_view.then(|| {
let view = p.ensure_diagram(target_layer);
p.place(view, target, Position { x: 487., y: 213. });
view
});
let mut app = App::with_project(p);
app.page = Page::Diagram;
app.layer = source_layer;
app.active_diagram = Some(from);
app.selected = source;
app.refresh_draft();
(app, source, target, from, to)
}
fn name_take(app: &mut App, source: Id) -> Project {
send(app, Message::StartSemanticReview(source));
let facet = FacetSelector::Header(HeaderFacet::Name);
row_event(app, RowEvent::Select(facet.clone()));
row_event(
app,
RowEvent::Decide(facet, Some(SemanticDecision::TakeSource)),
);
assert!(state(app).can_apply(), "{:?}", state(app).error);
let Some(Workflow::Semantic(state)) = &mut app.workflow else {
unreachable!()
};
let command = state.command(app.document.project()).unwrap();
execute_batch(app.document.project(), &[command]).unwrap()
}
#[test]
fn semantic_name_take_selects_the_counterpart_view_in_both_directions_with_one_exact_history_entry()
{
for reverse in [false, true] {
let (mut app, source, target, from, to) = fixture(reverse, true);
app.search = format!("@{}", app.project().elements[&source].alias);
let query = app.search.clone();
let before = app.document.snapshot();
let expected = name_take(&mut app, source);
app.selected_node = app.project().diagrams[&from].nodes.keys().next().copied();
send(&mut app, Message::Workflow(Event::Apply));
assert_eq!(app.project(), &expected);
assert_eq!(app.project().diagrams, before.decoded.project.diagrams);
assert_eq!(app.selected, target);
assert_eq!(app.layer, app.project().elements[&target].layer());
assert_eq!(app.active_diagram, to);
assert_eq!(
app.project().diagrams[&app.active_diagram.unwrap()].layer,
app.layer
);
// refresh_draft deliberately selects the target's visible placement.
// The invariant is that the old-layer placement cannot survive.
let placement = app.selected_node.expect("visible counterpart placement");
assert_eq!(
app.project().diagrams[&to.unwrap()].nodes[&placement].element,
target
);
assert!(!app.project().diagrams[&from].nodes.contains_key(&placement));
assert_eq!(app.page, Page::Diagram);
assert_eq!(app.search, query);
assert!(app.workflow.is_none());
assert_eq!(app.document.revision(), 1);
let accepted = app.document.snapshot();
assert_eq!(
source_project::compile_bundle(&accepted.bundle, LIMITS)
.unwrap()
.decoded
.project,
expected
);
send(&mut app, Message::Undo);
assert_eq!(app.project(), &before.decoded.project);
assert_eq!(app.document.bundle(), &before.bundle);
assert!(!app.document.can_undo());
send(&mut app, Message::Redo);
assert_eq!(app.project(), &accepted.decoded.project);
assert_eq!(app.document.bundle(), &accepted.bundle);
}
}
#[test]
fn semantic_review_without_a_destination_view_clears_the_old_layer_canvas_without_creating_a_view()
{
let (mut app, source, target, _, _) = fixture(false, false);
let expected = name_take(&mut app, source);
send(&mut app, Message::Workflow(Event::Apply));
assert_eq!(app.project(), &expected);
assert_eq!(app.selected, target);
assert_eq!(app.layer, Layer::Sa);
assert_eq!(app.active_diagram, None);
assert_eq!(app.project().diagrams.len(), 1);
}
#[test]
fn review_already_showing_the_target_keeps_its_camera_and_query() {
let (mut app, source, target, _, to) = fixture(false, true);
app.layer = Layer::Sa;
app.active_diagram = to;
app.selected = target;
app.zoom = 1.31;
app.pan = iced::Vector::new(-219., 88.);
app.search = "pressure".into();
app.refresh_draft();
let expected = name_take(&mut app, source);
send(&mut app, Message::Workflow(Event::Apply));
assert_eq!(app.project(), &expected);
assert_eq!(app.active_diagram, to);
assert_eq!(app.zoom, 1.31);
assert_eq!(app.pan, iced::Vector::new(-219., 88.));
assert_eq!(app.search, "pressure");
}
#[test]
fn rejected_semantic_source_writeback_retains_review_camera_and_original_navigation() {
let (mut app, source, _, from, _) = fixture(false, true);
let bundle = app.document.bundle().clone();
let mut limits = source_project::ProjectLimits::default();
limits.model.max_source_bytes = bundle.files.values().map(String::len).sum::<usize>() + 1;
app.document = Document::from_bundle(bundle, limits).unwrap();
app.zoom = 1.21;
app.pan = iced::Vector::new(72., -44.);
app.search = "confirmation".into();
let before = app.document.snapshot();
let _valid_model = name_take(&mut app, source);
send(&mut app, Message::Workflow(Event::Apply));
assert!(Arc::ptr_eq(&before, &app.document.snapshot()));
assert_eq!(app.selected, source);
assert_eq!(app.layer, Layer::Oa);
assert_eq!(app.active_diagram, Some(from));
assert_eq!(app.page, Page::Diagram);
assert_eq!(app.zoom, 1.21);
assert_eq!(app.pan, iced::Vector::new(72., -44.));
assert_eq!(app.search, "confirmation");
assert!(state(&app).error.is_some());
assert!(!app.document.can_undo());
}