test: added additional test coverage to graph components
This commit is contained in:
@@ -1049,7 +1049,6 @@ description: A graph agent
|
|||||||
model: anthropic:claude-sonnet-4-6
|
model: anthropic:claude-sonnet-4-6
|
||||||
temperature: 0.3
|
temperature: 0.3
|
||||||
top_p: 0.8
|
top_p: 0.8
|
||||||
agent_session: temp
|
|
||||||
global_tools:
|
global_tools:
|
||||||
- fetch_pdf.sh
|
- fetch_pdf.sh
|
||||||
mcp_servers:
|
mcp_servers:
|
||||||
@@ -1074,7 +1073,6 @@ nodes:
|
|||||||
);
|
);
|
||||||
assert_eq!(config.temperature, Some(0.3));
|
assert_eq!(config.temperature, Some(0.3));
|
||||||
assert_eq!(config.top_p, Some(0.8));
|
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.global_tools, vec!["fetch_pdf.sh"]);
|
||||||
assert_eq!(config.mcp_servers, vec!["pubmed-search"]);
|
assert_eq!(config.mcp_servers, vec!["pubmed-search"]);
|
||||||
assert_eq!(config.conversation_starters, vec!["Start here"]);
|
assert_eq!(config.conversation_starters, vec!["Start here"]);
|
||||||
|
|||||||
@@ -1429,6 +1429,23 @@ mod tests {
|
|||||||
assert!(tc.thought_signature.is_none());
|
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]
|
#[test]
|
||||||
fn toolcall_with_thought_signature() {
|
fn toolcall_with_thought_signature() {
|
||||||
let tc = ToolCall::new("t".into(), json!({}), None)
|
let tc = ToolCall::new("t".into(), json!({}), None)
|
||||||
|
|||||||
@@ -468,6 +468,33 @@ mod tests {
|
|||||||
assert!(state.state().get(OUTPUT_KEY).is_none());
|
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 {
|
fn node_with_schema(updates: Option<HashMap<String, String>>, schema: Value) -> LlmNode {
|
||||||
let mut n = node_with(updates);
|
let mut n = node_with(updates);
|
||||||
n.output_schema = Some(schema);
|
n.output_schema = Some(schema);
|
||||||
|
|||||||
@@ -863,6 +863,27 @@ nodes:
|
|||||||
assert!(graph.conversation_starters.is_empty());
|
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]
|
#[test]
|
||||||
fn has_agent_node_detects_agent_nodes() {
|
fn has_agent_node_detects_agent_nodes() {
|
||||||
let with_agent = r#"
|
let with_agent = r#"
|
||||||
|
|||||||
@@ -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]
|
#[test]
|
||||||
fn rag_node_without_documents_errors() {
|
fn rag_node_without_documents_errors() {
|
||||||
let graph = graph_with(
|
let graph = graph_with(
|
||||||
|
|||||||
Reference in New Issue
Block a user