Integrate release recovery, semantic review, coverage and Windows packaging

This commit is contained in:
Codex
2026-09-06 16:31:55 -07:00
parent c091f80e6e
commit 2b2d2bc18b
174 changed files with 27635 additions and 127 deletions
@@ -89,6 +89,153 @@ fn assert_source_model_agree(app: &App) {
assert!(!app.source_dirty());
}
#[test]
fn state_diagram_routes_constructor_and_source_open_to_the_existing_workspace_without_edits() {
let mut f = fixture();
let diagram = create_view(&mut f).diagram;
let project = f.app.project().clone();
let app = App::with_project(project.clone());
assert_eq!(app.page, Page::Behavior);
assert_eq!(app.state_context().unwrap().diagram, diagram);
assert_eq!(behavior::selected_owner(&app), Some(f.machine));
assert_eq!(app.behavior.diagram.tool, Tool::Select);
assert_eq!(app.selected, project.id);
assert_eq!(app.project(), &project);
assert!(!app.document.can_undo());
let directory = tempfile::tempdir().unwrap();
let path = directory.path().join("state-view.arcadia");
let text = format!(
"// Exact authored source must remain unchanged.\n{}",
language::format(&project)
);
std::fs::write(&path, &text).unwrap();
let mut reopened = App::with_project(Project::empty());
send(
&mut reopened,
Message::Loaded(Ok(Some(read_snapshot(path.clone()).unwrap()))),
);
assert_eq!(reopened.page, Page::Behavior);
assert_eq!(reopened.state_context().unwrap().diagram, diagram);
assert_eq!(reopened.project(), &project);
assert_eq!(
reopened.document.bundle().files[&reopened.document.bundle().entry],
text
);
assert_eq!(std::fs::read_to_string(path).unwrap(), text);
assert!(!reopened.document.can_undo());
assert_source_model_agree(&reopened);
}
#[test]
fn state_diagram_routes_picker_and_reveal_but_explicit_architecture_does_not_bounce() {
let mut f = fixture();
let diagram = create_view(&mut f).diagram;
let mut project = f.app.project().clone();
let second = state_edit::create_view(&project, f.machine).unwrap();
project = prepare_command(&project, &second.command).unwrap().project;
let transition = project.relate(RelationKind::StateTransition, "Switch", f.a, f.b);
let mut app = App::with_project(project.clone());
let before = app.document.snapshot();
send(&mut app, Message::Page(Page::Diagram));
assert_eq!(app.page, Page::Diagram);
assert_eq!(app.active_diagram, None);
send(
&mut app,
Message::Diagram(Choice {
id: second.diagram,
label: "Second state view".into(),
}),
);
assert_eq!(app.page, Page::Behavior);
assert_eq!(app.state_context().unwrap().diagram, second.diagram);
send(&mut app, Message::RevealInDiagram(diagram, transition));
assert_eq!(app.page, Page::Behavior);
assert_eq!(app.state_context().unwrap().diagram, diagram);
assert_eq!(app.selected, transition);
assert_eq!(app.draft.as_ref().unwrap().original, transition);
assert!(Arc::ptr_eq(&before, &app.document.snapshot()));
assert_source_model_agree(&app);
let architecture = project.ensure_diagram(Layer::Sa);
let mut app = App::with_project(project);
send(
&mut app,
Message::Diagram(Choice {
id: diagram,
label: "State view".into(),
}),
);
assert_eq!(app.page, Page::Behavior);
send(&mut app, Message::Page(Page::Diagram));
assert_eq!(app.page, Page::Diagram);
assert_eq!(app.active_diagram, Some(architecture));
assert!(app.state_context().is_none());
assert!(!app.document.can_undo());
}
#[test]
fn state_diagram_routes_preserve_selected_raw_properties_and_pending_behavior_guards() {
let mut f = fixture();
let diagram = create_view(&mut f).diagram;
let mut app = App::with_project(f.app.project().clone());
send(&mut app, Message::Select(f.a));
send(
&mut app,
Message::Field("/alias".into(), "invalid alias!".into()),
);
let raw = serde_json::to_value(app.draft.as_ref().unwrap().recovery_snapshot()).unwrap();
assert!(!app.apply());
let before = app.document.snapshot();
// Exercise normalization itself with an existing raw draft, including callers
// that have just adopted a view without a successful property Apply.
app.page = Page::Diagram;
app.route_state_diagram_workspace();
assert_eq!(app.page, Page::Behavior);
assert_eq!(app.selected, f.a);
assert_eq!(
serde_json::to_value(app.draft.as_ref().unwrap().recovery_snapshot()).unwrap(),
raw
);
assert!(Arc::ptr_eq(&before, &app.document.snapshot()));
send(
&mut app,
Message::Diagram(Choice {
id: diagram,
label: "State view".into(),
}),
);
assert_eq!(
serde_json::to_value(app.draft.as_ref().unwrap().recovery_snapshot()).unwrap(),
raw
);
assert!(Arc::ptr_eq(&before, &app.document.snapshot()));
let mut app = App::with_project(f.app.project().clone());
form(
&mut app,
states::Event::Start(f.machine, states::Tool::Transition, f.a),
);
form(
&mut app,
states::Event::Name("Pending behavior stays".into()),
);
let pending = app.behavior.recovery_snapshot().unwrap();
let context = app.state_context().unwrap();
send(&mut app, Message::Page(Page::Diagram));
send(
&mut app,
Message::Diagram(Choice {
id: diagram,
label: "State view".into(),
}),
);
assert_eq!(app.page, Page::Behavior);
assert_eq!(app.state_context().unwrap().diagram, context.diagram);
assert_eq!(app.behavior.recovery_snapshot().unwrap(), pending);
assert!(!app.document.can_undo());
}
struct NavigationFixture {
app: App,
machine_a: Id,
@@ -789,12 +936,15 @@ fn fallback_owner_first_selection_keeps_the_captured_context_for_its_first_move(
let f = fixture();
let mut project = f.app.project().clone();
// One eligible machine makes the fallback deterministic. Start from a loaded
// project with no selected behavior element and no explicitly chosen owner.
// architecture view with no selected behavior element or chosen owner. A
// state-only project now opens its saved view with an explicit owner.
project
.elements
.retain(|id, element| f.members.contains(id) || element.kind() == Kind::System);
let plan = state_edit::create_view(&project, f.machine).unwrap();
let project = prepare_command(&project, &plan.command).unwrap().project;
let mut project = prepare_command(&project, &plan.command).unwrap().project;
let architecture = project.ensure_diagram(Layer::Sa);
project.diagrams.get_mut(&architecture).unwrap().projection = ProjectionKind::Allocation;
let mut app = App::with_project(project);
assert_eq!(app.selected, app.project().id);
assert!(app.behavior.active_owner.is_none());
@@ -917,7 +1067,11 @@ fn shared_semantic_states_keep_architecture_and_behavior_placements_independent(
id: architecture,
label: app.project().named(architecture).into(),
};
// The initial UUID-ordered view may be a state view, which correctly opens
// Behavior. Enter Architecture explicitly before testing its selection.
send(&mut app, Message::Page(Page::Diagram));
send(&mut app, Message::Diagram(architecture_choice));
assert_eq!(app.page, Page::Diagram);
send(&mut app, Message::Select(f.b));
assert_eq!(app.active_diagram, Some(architecture));
assert_eq!(app.selected_node, Some(arch_b));