test: added additional test coverage to graph components

This commit is contained in:
2026-05-18 10:08:36 -06:00
parent b7a20a000a
commit 4f244618ca
5 changed files with 143 additions and 2 deletions
-2
View File
@@ -1049,7 +1049,6 @@ description: A graph agent
model: anthropic:claude-sonnet-4-6
temperature: 0.3
top_p: 0.8
agent_session: temp
global_tools:
- fetch_pdf.sh
mcp_servers:
@@ -1074,7 +1073,6 @@ nodes:
);
assert_eq!(config.temperature, Some(0.3));
assert_eq!(config.top_p, Some(0.8));
assert_eq!(config.agent_session.as_deref(), Some("temp"));
assert_eq!(config.global_tools, vec!["fetch_pdf.sh"]);
assert_eq!(config.mcp_servers, vec!["pubmed-search"]);
assert_eq!(config.conversation_starters, vec!["Start here"]);
+17
View File
@@ -1429,6 +1429,23 @@ mod tests {
assert!(tc.thought_signature.is_none());
}
#[test]
fn direct_invoker_maps_each_language() {
assert_eq!(
Language::Bash.direct_invoker(),
Some(("bash", &[] as &[&str]))
);
assert_eq!(
Language::Python.direct_invoker(),
Some(("python3", &[] as &[&str]))
);
assert_eq!(
Language::TypeScript.direct_invoker(),
Some(("npx", &["tsx"] as &[&str]))
);
assert_eq!(Language::Unsupported.direct_invoker(), None);
}
#[test]
fn toolcall_with_thought_signature() {
let tc = ToolCall::new("t".into(), json!({}), None)
+27
View File
@@ -468,6 +468,33 @@ mod tests {
assert!(state.state().get(OUTPUT_KEY).is_none());
}
#[test]
fn next_for_llm_node_success_routes_to_next() {
assert_eq!(
next_for_llm_node(Some("nx"), false, Some("fb")).unwrap(),
"nx"
);
}
#[test]
fn next_for_llm_node_failure_with_fallback_routes_to_fallback() {
assert_eq!(
next_for_llm_node(Some("nx"), true, Some("fb")).unwrap(),
"fb"
);
}
#[test]
fn next_for_llm_node_failure_without_fallback_routes_to_next() {
assert_eq!(next_for_llm_node(Some("nx"), true, None).unwrap(), "nx");
}
#[test]
fn next_for_llm_node_errors_without_next_or_fallback() {
assert!(next_for_llm_node(None, false, None).is_err());
assert!(next_for_llm_node(None, true, None).is_err());
}
fn node_with_schema(updates: Option<HashMap<String, String>>, schema: Value) -> LlmNode {
let mut n = node_with(updates);
n.output_schema = Some(schema);
+21
View File
@@ -863,6 +863,27 @@ nodes:
assert!(graph.conversation_starters.is_empty());
}
#[test]
fn node_ids_lists_nodes_in_order() {
let yaml = r#"
name: g
start: first
nodes:
first:
id: first
type: agent
agent: helper
prompt: hi
next: last
last:
id: last
type: end
output: done
"#;
let graph: Graph = serde_yaml::from_str(yaml).unwrap();
assert_eq!(graph.node_ids(), vec!["first", "last"]);
}
#[test]
fn has_agent_node_detects_agent_nodes() {
let with_agent = r#"
+78
View File
@@ -464,6 +464,84 @@ mod tests {
}
}
fn input_node(id: &str, on_timeout: Option<&str>, next: Option<&str>) -> Node {
Node {
id: id.into(),
description: String::new(),
node_type: NodeType::Input(InputNode {
question: "?".into(),
default: None,
validation: None,
state_updates: None,
timeout: None,
on_timeout: on_timeout.map(String::from),
}),
next: next.map(String::from),
}
}
fn llm_node(id: &str, fallback: Option<&str>, next: Option<&str>) -> Node {
Node {
id: id.into(),
description: String::new(),
node_type: NodeType::Llm(LlmNode {
instructions: None,
prompt: "p".into(),
tools: None,
model: None,
temperature: None,
top_p: None,
fallback: fallback.map(String::from),
max_attempts: 1,
max_iterations: 10,
state_updates: None,
output_schema: None,
timeout: None,
}),
next: next.map(String::from),
}
}
#[test]
fn flags_missing_approval_on_timeout_target() {
let mut approval = approval_node("a", &["yes"], &[("yes", "end")], "end");
if let NodeType::Approval(ref mut n) = approval.node_type {
n.on_timeout = Some("ghost".into());
}
let graph = graph_with(vec![("a", approval), ("end", end_node("end"))], "a");
let result = validator().validate(&graph);
assert!(!result.is_valid());
assert!(result.errors.iter().any(|e| e.message.contains("ghost")));
}
#[test]
fn flags_missing_input_on_timeout_target() {
let graph = graph_with(
vec![
("i", input_node("i", Some("ghost"), Some("end"))),
("end", end_node("end")),
],
"i",
);
let result = validator().validate(&graph);
assert!(!result.is_valid());
assert!(result.errors.iter().any(|e| e.message.contains("ghost")));
}
#[test]
fn flags_missing_llm_fallback_target() {
let graph = graph_with(
vec![
("l", llm_node("l", Some("ghost"), Some("end"))),
("end", end_node("end")),
],
"l",
);
let result = validator().validate(&graph);
assert!(!result.is_valid());
assert!(result.errors.iter().any(|e| e.message.contains("ghost")));
}
#[test]
fn rag_node_without_documents_errors() {
let graph = graph_with(