use openquiver_graph::{
Anchor, Document, Edge, EdgeKind, Graph, Layout, Node, NodeName, NodeTypeId, PinRef, Trivia,
};
fn pin(node: &str, pin: &str) -> PinRef {
PinRef::new(NodeName::new(node), pin)
}
fn wired() -> Document {
let mut graph = Graph::new("g");
for name in ["ask", "out", "start"] {
graph.insert_node(Node::new(NodeName::new(name), NodeTypeId::new("t.x")));
}
graph.insert_edge(Edge::new(
EdgeKind::Exec,
pin("start", "out"),
pin("ask", "in"),
));
graph.insert_edge(Edge::new(
EdgeKind::Data,
pin("ask", "text"),
pin("out", "value"),
));
let mut trivia = Trivia::default();
trivia.add(
Anchor::Node(NodeName::new("ask")),
vec!["// the agent".to_owned()],
);
trivia.add(
Anchor::Edge(Edge::new(
EdgeKind::Data,
pin("ask", "text"),
pin("out", "value"),
)),
vec!["// the answer".to_owned()],
);
let mut layout = Layout::default();
layout.set(NodeName::new("ask"), (80, 40));
Document::new(graph, trivia, layout)
}
#[test]
fn renaming_rewrites_every_wire_that_mentions_the_node() {
let mut doc = wired();
doc.rename_node("ask", "prompt")
.expect("rename should succeed");
assert!(doc.graph.node("ask").is_none(), "the old name is gone");
assert!(
doc.graph.node("prompt").is_some(),
"the new name is present"
);
let mentions: Vec<_> = doc
.graph
.edges()
.filter(|e| e.from().node() == "ask" || e.to().node() == "ask")
.collect();
assert!(
mentions.is_empty(),
"wires still point at the old name: {mentions:?}"
);
assert_eq!(
doc.graph.edges().count(),
2,
"no wire was lost along the way"
);
}
#[test]
fn renaming_carries_the_comments_across() {
let mut doc = wired();
doc.rename_node("ask", "prompt")
.expect("rename should succeed");
assert_eq!(
doc.trivia.get(&Anchor::Node(NodeName::new("prompt"))),
["// the agent".to_owned()],
"the node's own comment did not follow it"
);
let moved = Edge::new(EdgeKind::Data, pin("prompt", "text"), pin("out", "value"));
assert_eq!(
doc.trivia.get(&Anchor::Edge(moved)),
["// the answer".to_owned()],
"the comment on a wire touching the node did not follow it"
);
}
#[test]
fn renaming_onto_a_name_that_is_taken_is_refused() {
let mut doc = wired();
doc.rename_node("ask", "out")
.expect_err("should be refused");
assert!(
doc.graph.node("ask").is_some(),
"the graph was left untouched"
);
assert_eq!(doc.graph.edges().count(), 2);
}
#[test]
fn removing_a_node_takes_its_wires_with_it() {
let mut doc = wired();
doc.remove_node("ask");
assert_eq!(doc.graph.edges().count(), 0);
assert!(
doc.trivia
.get(&Anchor::Node(NodeName::new("ask")))
.is_empty()
);
}
#[test]
fn wires_can_be_found_by_the_pin_they_touch() {
let doc = wired();
assert_eq!(doc.graph.edges_from(&pin("start", "out")).count(), 1);
assert_eq!(doc.graph.edges_into(&pin("ask", "in")).count(), 1);
assert_eq!(doc.graph.edges_into(&pin("start", "out")).count(), 0);
}
#[test]
fn removing_by_a_denormalized_name_still_takes_the_wires() {
let mut doc = Document::new(Graph::new("g"), Trivia::default(), Layout::default());
doc.graph
.insert_node(Node::new(NodeName::new("é"), NodeTypeId::new("t.x")));
doc.graph
.insert_node(Node::new(NodeName::new("b"), NodeTypeId::new("t.y")));
doc.graph
.insert_edge(Edge::new(EdgeKind::Exec, pin("é", "out"), pin("b", "in")));
doc.remove_node("e\u{0301}");
assert!(doc.graph.node("é").is_none(), "the node is gone");
assert_eq!(doc.graph.edges().count(), 0, "and so are its wires");
}