Preserve editable routes across source projects and REST

This commit is contained in:
2026-09-05 20:19:38 +03:00
parent 4e5a88dc4d
commit a7c6f9678c
8 changed files with 718 additions and 6 deletions
+98
View File
@@ -27,6 +27,104 @@ fn id(project: &Project, alias: &str) -> Id {
.0
}
#[test]
fn route_edits_keep_diagram_file_ownership_and_comments_with_edge_identity() {
let input = bundle(
"arcadia 3; project p \"Routing\" { include \"views.arcadia\"; include \"work.arcadia\"; }",
&[
(
"work.arcadia",
"oa_activity a \"A\" {}\noa_activity b \"B\" {}\ninteraction first \"First\" { source @a; target @b; }\ninteraction second \"Second\" { source @b; target @a; }\n",
),
(
"views.arcadia",
r#"// Diagram routing decisions stay here.
diagram review "Review" {
routes [
// First edge's detour, including unusual numeric spelling.
{ edge @ // stable edge
first; waypoints [{ x 4.20e2; y // clearance
260; }];
label { fraction // near target
0.7; offset { x 0; y -16; }; }; },
// Second edge stays automatic.
{ edge @second; }
];
}
"#,
),
],
);
let original = compile(&input);
let mut changed = original.decoded.project.clone();
let diagram = id(&changed, "review");
let first = id(&changed, "first");
let routes = &mut changed.diagrams.get_mut(&diagram).unwrap().routes;
routes[0].waypoints[0].y = 300.;
routes[0].label.as_mut().unwrap().fraction = 0.6;
routes.swap(0, 1);
changed.relations.get_mut(&first).unwrap().alias = "detour".into();
let updated = update_bundle(&original, &changed, ProjectLimits::default()).unwrap();
assert_eq!(updated.decoded.project, changed);
assert_eq!(updated.index.declarations[&diagram].path, "views.arcadia");
assert_eq!(updated.bundle.files.len(), original.bundle.files.len());
let text = &updated.bundle.files["views.arcadia"];
assert!(
text.contains("edge @ // stable edge\n detour;"),
"{text}"
);
assert!(text.contains("x 4.20e2; y // clearance\n 300"), "{text}");
assert!(text.contains("fraction // near target\n 0.6"), "{text}");
assert!(
text.find("// Second edge stays automatic.").unwrap()
< text.find("// First edge's detour").unwrap(),
"{text}"
);
assert!(
text.find("// First edge's detour").unwrap()
< text.find("edge @ // stable edge\n detour").unwrap(),
"{text}"
);
let mut old_comments = comments(&original.bundle.files["views.arcadia"]);
let mut new_comments = comments(text);
old_comments.sort();
new_comments.sort();
assert_eq!(new_comments, old_comments);
}
#[test]
fn invalid_cross_file_route_references_and_geometry_locate_the_authored_view() {
let mut input = bundle(
"arcadia 3; project p \"Routing\" { include \"views.arcadia\"; include \"work.arcadia\"; }",
&[
(
"work.arcadia",
"oa_activity a \"A\" {}\noa_activity b \"B\" {}\ninteraction link \"Link\" { source @a; target @b; }\n",
),
(
"views.arcadia",
"// authored view\ndiagram review \"Review\" {\n routes [{ edge @absent; }];\n}\n",
),
],
);
let errors = compile_bundle(&input, ProjectLimits::default()).unwrap_err();
assert!(
errors.iter().any(|error| error.path == "views.arcadia"
&& error.diagnostic.line == 3
&& error.diagnostic.message.contains("absent")),
"{errors:?}"
);
input.files.get_mut("views.arcadia").unwrap().clone_from(&
"// authored view\ndiagram review \"Review\" {\n routes [{ edge @link; label { fraction -0.1; offset { x 0; y 0; }; }; }];\n}\n".into());
let errors = compile_bundle(&input, ProjectLimits::default()).unwrap_err();
assert!(
errors.iter().any(|error| error.path == "views.arcadia"
&& error.diagnostic.line == 3
&& error.diagnostic.field.as_deref() == Some("routes")),
"{errors:?}"
);
}
fn typed() -> SourceBundle {
bundle(
"arcadia 3; project test_model \"航海\" {\n include \"exchanges.arcadia\";\n include \"work/send.arcadia\";\n include \"work/receive.arcadia\";\n include \"types.arcadia\";\n}",