use matrixcode_core::workflow::{
parse_workflow, parse_workflow_from_file, WorkflowEngine, WorkflowPersistence,
WorkflowStatus, to_yaml,
};
use std::collections::HashMap;
#[test]
fn test_simple_workflow_execution() {
let yaml = r#"
id: simple-test
name: Simple Test Workflow
version: "1.0.0"
nodes:
- id: start
type: start
name: Start
- id: end
type: end
name: End
edges:
- from: start
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
assert_eq!(workflow.id, "simple-test");
let engine = WorkflowEngine::new(workflow).expect("Failed to create engine");
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
let context = rt.block_on(async {
engine.run(HashMap::new()).await
}).expect("Failed to run workflow");
assert_eq!(context.status, WorkflowStatus::Completed);
assert_eq!(context.execution_path.len(), 2);
}
#[test]
fn test_workflow_with_inputs() {
let yaml = r#"
id: input-test
name: Input Test Workflow
version: "1.0.0"
inputs:
- name: user_name
type: string
required: true
- name: count
type: number
required: false
default: 1
nodes:
- id: start
type: start
name: Start
- id: end
type: end
name: End
edges:
- from: start
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
let engine = WorkflowEngine::new(workflow).expect("Failed to create engine");
let mut inputs = HashMap::new();
inputs.insert("user_name".to_string(), serde_json::json!("Alice"));
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
let context = rt.block_on(async {
engine.run(inputs).await
}).expect("Failed to run workflow");
assert_eq!(context.status, WorkflowStatus::Completed);
assert_eq!(context.get_input("user_name").unwrap(), &serde_json::json!("Alice"));
}
#[test]
fn test_workflow_missing_required_input() {
let yaml = r#"
id: required-input-test
name: Required Input Test
version: "1.0.0"
inputs:
- name: required_field
type: string
required: true
nodes:
- id: start
type: start
name: Start
- id: end
type: end
name: End
edges:
- from: start
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
let engine = WorkflowEngine::new(workflow).expect("Failed to create engine");
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
let result = rt.block_on(async {
engine.run(HashMap::new()).await
});
assert!(result.is_err());
}
#[test]
fn test_workflow_persistence_roundtrip() {
use tempfile::tempdir;
let yaml = r#"
id: persistence-test
name: Persistence Test Workflow
version: "1.0.0"
nodes:
- id: start
type: start
name: Start
- id: end
type: end
name: End
edges:
- from: start
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
let engine = WorkflowEngine::new(workflow).expect("Failed to create engine");
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
let context = rt.block_on(async {
engine.run(HashMap::new()).await
}).expect("Failed to run workflow");
let dir = tempdir().expect("Failed to create temp dir");
let persistence = WorkflowPersistence::with_base_path(dir.path().to_path_buf());
persistence.save(&context).expect("Failed to save");
let loaded = persistence.load(&context.instance_id)
.expect("Failed to load")
.expect("No context found");
assert_eq!(loaded.instance_id, context.instance_id);
assert_eq!(loaded.workflow_id, "persistence-test");
assert_eq!(loaded.status, WorkflowStatus::Completed);
}
#[test]
fn test_workflow_yaml_serialization() {
let yaml = r#"
id: serialization-test
name: Serialization Test Workflow
version: "1.0.0"
nodes:
- id: start
type: start
name: Start
- id: end
type: end
name: End
edges:
- from: start
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
let serialized = to_yaml(&workflow).expect("Failed to serialize");
let reparsed = parse_workflow(&serialized).expect("Failed to reparse");
assert_eq!(reparsed.id, workflow.id);
assert_eq!(reparsed.nodes.len(), workflow.nodes.len());
}
#[test]
fn test_parse_workflow_from_file() {
let example_path = std::path::PathBuf::from("workflows/hello-world.yaml");
if example_path.exists() {
let workflow = parse_workflow_from_file(&example_path)
.expect("Failed to parse workflow from file");
assert_eq!(workflow.id, "hello-world");
assert_eq!(workflow.name, "Hello World Workflow");
assert!(workflow.nodes.len() >= 3);
}
}
#[test]
fn test_workflow_pause_resume() {
let yaml = r#"
id: pause-test
name: Pause Test Workflow
version: "1.0.0"
nodes:
- id: start
type: start
name: Start
- id: end
type: end
name: End
edges:
- from: start
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
let engine = WorkflowEngine::new(workflow).expect("Failed to create engine");
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
let mut context = rt.block_on(async {
engine.run(HashMap::new()).await
}).expect("Failed to run workflow");
context.pause();
assert_eq!(context.status, WorkflowStatus::Paused);
assert!(!context.can_continue());
context.resume();
assert_eq!(context.status, WorkflowStatus::Running);
assert!(context.can_continue());
}
#[test]
fn test_workflow_failure_ignore_strategy() {
let yaml = r#"
id: ignore-failure-test
name: Ignore Failure Test
version: "1.0.0"
nodes:
- id: start
type: start
name: Start
- id: task1
type: task
name: Task 1
task: nonexistent_task
on_failure:
type: ignore
- id: end
type: end
name: End
edges:
- from: start
to: task1
- from: task1
to: end
"#;
let workflow = parse_workflow(yaml).expect("Failed to parse workflow");
let engine = WorkflowEngine::new(workflow).expect("Failed to create engine");
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");
let context = rt.block_on(async {
engine.run(HashMap::new()).await
});
assert!(context.is_ok() || context.is_err());
}
#[test]
fn test_workflow_template_rendering() {
use matrixcode_core::workflow::render_template;
let mut vars = HashMap::new();
vars.insert("name".to_string(), serde_json::json!("World"));
vars.insert("count".to_string(), serde_json::json!(42));
let result = render_template("Hello {{name}}! Count: {{count}}", &vars)
.expect("Failed to render template");
assert_eq!(result, "Hello World! Count: 42");
}
#[test]
fn test_workflow_rule_validation() {
use matrixcode_core::workflow::{Rule, RuleEngine};
let mut engine = RuleEngine::new();
let mut context = HashMap::new();
context.insert("status".to_string(), serde_json::json!("success"));
context.insert("score".to_string(), serde_json::json!(95));
let rule = Rule::All {
rules: vec![
Rule::Equals {
field: "status".to_string(),
value: serde_json::json!("success"),
},
Rule::GreaterThan {
field: "score".to_string(),
value: 80.0,
},
],
};
let result = engine.validate(&rule, &context).expect("Failed to validate");
assert!(result.passed);
}