Files
ARCADIA-Studio/crates/oa-core/tests/release_diagrams.rs
T

249 lines
7.5 KiB
Rust

use oa_core::{projection::*, *};
#[test]
fn unplaced_work_parent_cannot_detach_a_leaf_from_its_visible_performer() {
let mut p = Project::empty();
let performer = p
.add_element(Kind::Entity, Layer::Oa, "Rescue team", None)
.unwrap();
let work = p
.add_element(Kind::Activity, Layer::Oa, "Respond", None)
.unwrap();
let leaf = p
.add_element(Kind::Activity, Layer::Oa, "Dispatch", Some(work))
.unwrap();
p.relate(RelationKind::Allocation, "Performs", performer, leaf);
let diagram = p.ensure_diagram(Layer::Oa);
p.diagrams.get_mut(&diagram).unwrap().projection = ProjectionKind::Allocation;
let owner = p.place(diagram, performer, Position { x: 0., y: 0. });
let child = p.place(diagram, leaf, Position { x: 40., y: 80. });
let view = project_view(&p, diagram);
assert_eq!(
view.nodes
.iter()
.find(|n| n.id == child)
.unwrap()
.visual_parent,
Some(owner)
);
let summary = p.place(diagram, work, Position { x: 24., y: 64. });
let view = project_view(&p, diagram);
assert!(
view.nodes
.iter()
.find(|n| n.id == summary)
.unwrap()
.allocation_summary
);
assert!(
!view
.nodes
.iter()
.find(|n| n.id == child)
.unwrap()
.allocation_summary
);
assert_eq!(
view.nodes
.iter()
.find(|n| n.id == child)
.unwrap()
.visual_parent,
Some(summary)
);
p.diagrams.get_mut(&diagram).unwrap().projection = ProjectionKind::FunctionalDataflow;
assert!(
project_view(&p, diagram)
.nodes
.iter()
.all(|n| !n.allocation_summary)
);
p.diagrams.get_mut(&diagram).unwrap().projection = ProjectionKind::Allocation;
p.diagrams.get_mut(&diagram).unwrap().nodes.remove(&summary);
let view = project_view(&p, diagram);
assert_eq!(
view.nodes
.iter()
.find(|n| n.id == child)
.unwrap()
.visual_parent,
Some(owner)
);
}
#[test]
fn architecture_is_nested_exchange_context_and_ports_attach_without_placements() {
let p = Project::demo();
let d = p
.diagrams
.values()
.find(|d| d.layer == Layer::Sa && d.projection == ProjectionKind::Allocation)
.unwrap();
let view = project_view(&p, d.id);
assert!(!view.nodes.is_empty());
assert!(view.nodes.iter().all(|n| {
let kind = p.elements[&n.element].kind();
kind.is_performer() || kind.is_work()
}));
for n in view
.nodes
.iter()
.filter(|n| p.elements[&n.element].kind().is_work())
{
let parent = view
.nodes
.iter()
.find(|parent| Some(parent.id) == n.visual_parent)
.unwrap();
assert!(p.elements[&parent.element].kind().is_performer());
assert!(n.position.x > parent.position.x && n.position.y > parent.position.y);
}
assert_eq!(view.ports.len(), 4);
assert!(
d.nodes
.values()
.all(|n| p.elements[&n.element].kind() != Kind::Port)
);
assert!(
view.edges
.iter()
.any(|e| p.relations[&e.id].kind() == RelationKind::BoundaryExchange)
);
for edge in &view.edges {
assert!(matches!(
p.relations[&edge.id].kind(),
RelationKind::FunctionalExchange | RelationKind::BoundaryExchange
));
for (id, owner) in [
(edge.source_port, edge.source),
(edge.target_port, edge.target),
] {
let port = view.ports.iter().find(|p| Some(p.element) == id).unwrap();
assert_eq!(port.owner, owner);
let node = view.nodes.iter().find(|n| n.id == owner).unwrap();
assert!(
port.position.x == node.position.x
|| port.position.x == node.position.x + node.size.width
);
}
}
}
#[test]
fn port_identity_collapse_and_group_movement_do_not_invent_semantic_edges() {
let mut p = Project::demo();
let diagram = p
.diagrams
.values()
.find(|d| d.layer == Layer::Sa && d.projection == ProjectionKind::Allocation)
.unwrap()
.id;
let view = project_view(&p, diagram);
let system = view
.nodes
.iter()
.find(|n| p.elements[&n.element].kind() == Kind::System)
.unwrap();
let node = system.id;
let before = p.clone();
let moved = execute_batch(
&p,
&[Command::MoveNode {
diagram,
node,
position: Position {
x: p.diagrams[&diagram].nodes[&node].position.x + 140.,
y: p.diagrams[&diagram].nodes[&node].position.y + 80.,
},
with_descendants: true,
}],
)
.unwrap();
let after = project_view(&moved, diagram);
for port in view.ports.iter().filter(|port| {
port.owner == node
|| view
.nodes
.iter()
.any(|n| n.id == port.owner && n.visual_parent == Some(node))
}) {
let shifted = after
.ports
.iter()
.find(|p| p.element == port.element)
.unwrap();
assert_eq!(shifted.position.x, port.position.x + 140.);
assert_eq!(shifted.position.y, port.position.y + 80.);
}
assert_eq!(moved.elements, before.elements);
assert_eq!(moved.relations, before.relations);
p.diagrams
.get_mut(&diagram)
.unwrap()
.nodes
.get_mut(&node)
.unwrap()
.collapsed = true;
let collapsed = project_view(&p, diagram);
assert!(collapsed.ports.iter().all(|port| {
p.elements[&port.element].parent
!= Some(
view.nodes
.iter()
.find(|n| n.visual_parent == Some(node))
.unwrap()
.element,
)
}));
let exchange = collapsed
.edges
.iter()
.find(|e| p.relations[&e.id].kind() == RelationKind::FunctionalExchange)
.unwrap();
assert_eq!(exchange.target, node);
assert_eq!(
exchange.target_port, None,
"A collapsed link must not invent a system port"
);
assert_eq!(p.relations, before.relations);
}
#[test]
fn view_filtering_keeps_placements_and_source_and_separates_capability_content() {
let mut p = Project::demo();
let diagram = p
.diagrams
.values()
.find(|d| d.layer == Layer::Oa && d.projection == ProjectionKind::Allocation)
.unwrap()
.id;
let cap = p
.elements
.values()
.find(|e| e.kind() == Kind::Capability)
.unwrap()
.id;
p.place(diagram, cap, Position { x: 600., y: 0. });
let original = p.clone();
assert!(
!project_view(&p, diagram)
.nodes
.iter()
.any(|n| n.element == cap)
);
p.diagrams.get_mut(&diagram).unwrap().projection = ProjectionKind::Capabilities;
let view = project_view(&p, diagram);
assert!(view.nodes.iter().any(|n| n.element == cap));
assert!(
!view
.nodes
.iter()
.any(|n| p.elements[&n.element].kind().is_work())
);
assert_eq!(
p.diagrams[&diagram].nodes,
original.diagrams[&diagram].nodes
);
assert_eq!(language::parse(&language::format(&p)).unwrap(), p);
}