use super::*;
#[tokio::test]
async fn test_runner_nested_do() {
let output = run_workflow_from_yaml(&testdata("nested_do.yaml"), json!({}))
.await
.unwrap();
assert_eq!(output["doubled"], json!(20));
}
#[tokio::test]
async fn test_runner_nested_try_catch() {
let output = run_workflow_from_yaml(&testdata("nested_try_catch.yaml"), json!({}))
.await
.unwrap();
assert_eq!(output["innerHandled"], json!(true));
assert_eq!(output["innerTitle"], json!("Inner Error"));
}
#[tokio::test]
async fn test_runner_nested_do_deep() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-do-deep
version: '0.1.0'
do:
- outerTask:
do:
- middleTask:
do:
- innerTask:
set:
deepValue: 42
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["deepValue"], json!(42));
}
#[tokio::test]
async fn test_runner_nested_do_export_context() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-do-export-context
version: '0.1.0'
do:
- outerTask:
do:
- innerSet:
set:
value: 42
export:
as: '${ {innerValue: .value} }'
- useContext:
set:
result: '${ $context.innerValue }'
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["result"], json!(42));
}
#[tokio::test]
async fn test_runner_do_within_for() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-within-for
version: '0.1.0'
do:
- processItems:
for:
in: ${ .items }
each: item
do:
- computeValue:
set:
results: "${ [.results[]] + [{name: $item, doubled: ($item * 2)}] }"
"#;
let runner = WorkflowRunner::new(serde_yaml::from_str(&yaml_str).unwrap()).unwrap();
let output = runner
.run(json!({"items": [3, 5, 7], "results": []}))
.await
.unwrap();
assert_eq!(
output["results"],
json!([
{"name": 3, "doubled": 6},
{"name": 5, "doubled": 10},
{"name": 7, "doubled": 14}
])
);
}
#[tokio::test]
async fn test_runner_nested_try_catch_inner_recovers() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-try-catch-inner-recovers
version: '0.1.0'
do:
- outerTry:
try:
- innerTry:
try:
- failTask:
raise:
error:
type: validation
title: Inner Error
status: 400
catch:
errors:
with:
type: validation
do:
- recoverInner:
set:
innerRecovered: true
- continueAfterInner:
set:
innerRecovered: true
continued: true
catch:
errors:
with:
type: validation
do:
- handleOuter:
set:
outerCaught: true
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["innerRecovered"], json!(true));
assert_eq!(output["continued"], json!(true));
assert!(output.get("outerCaught").is_none());
}
#[tokio::test]
async fn test_runner_nested_for_outer_reference() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-for-outer-ref
version: '0.1.0'
do:
- outerLoop:
for:
in: ${ .groups }
each: group
do:
- innerProcess:
for:
in: ${ $group.items }
each: item
do:
- accumulate:
set:
result: "${ [.result[]] + [{group: $group.name, item: $item}] }"
"#;
let runner = WorkflowRunner::new(serde_yaml::from_str(&yaml_str).unwrap()).unwrap();
let output = runner
.run(json!({
"groups": [
{"name": "A", "items": [1, 2]},
{"name": "B", "items": [3]}
],
"result": []
}))
.await
.unwrap();
assert_eq!(
output["result"],
json!([
{"group": "A", "item": 1},
{"group": "A", "item": 2},
{"group": "B", "item": 3}
])
);
}
#[tokio::test]
async fn test_runner_nested_do_export() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-do-export
version: '0.1.0'
do:
- outerTask:
do:
- innerSet:
set:
innerValue: 42
export:
as: '${ {shared: .innerValue} }'
- useContext:
set:
result: '${ $context.shared }'
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["result"], json!(42));
}
#[tokio::test]
async fn test_runner_nested_for_with_export() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-for-export
version: '0.1.0'
do:
- outerLoop:
for:
in: ${ .groups }
each: group
do:
- innerProcess:
for:
in: ${ $group.items }
each: item
do:
- accumulate:
set:
results: "${ [.results[]] + [{g: $group.name, v: $item}] }"
export:
as: '${ {results: .results} }'
- report:
set:
allResults: "${ $context.results }"
"#;
let runner = WorkflowRunner::new(serde_yaml::from_str(&yaml_str).unwrap()).unwrap();
let output = runner
.run(json!({
"groups": [{"name": "A", "items": [1, 2]}, {"name": "B", "items": [3]}],
"results": []
}))
.await
.unwrap();
assert!(output["allResults"].is_array());
}
#[tokio::test]
async fn test_runner_do_then_exit_nested() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-then-exit-nested
version: '0.1.0'
do:
- outerTask:
do:
- step1:
set:
a: 1
- step2:
set:
b: 2
then: exit
- step3:
set:
c: 3
- afterOuter:
set:
done: true
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["done"], json!(true));
assert!(output.get("c").is_none());
}
#[tokio::test]
async fn test_runner_nested_do_with_then_exit() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-do-then-exit
version: '0.1.0'
do:
- outerTask:
do:
- step1:
set:
x: 1
- step2:
set:
y: 2
then: exit
- step3:
set:
skipped: true
- afterOuter:
set:
z: 3
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["z"], json!(3));
assert!(output.get("skipped").is_none());
}
#[tokio::test]
async fn test_runner_nested_do_then_end_top_level() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-do-then-end
version: '0.1.0'
do:
- outerTask:
do:
- innerStep:
set:
value: 42
then: end
- afterInner:
set:
reached: true
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["reached"], json!(true));
}
#[tokio::test]
async fn test_runner_nested_raise_caught_by_outer() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-raise-outer-catch
version: '0.1.0'
do:
- outerTry:
try:
- innerDo:
do:
- step1:
set:
x: 1
- step2:
raise:
error:
type: communication
title: Inner Error
status: 503
catch:
errors:
with:
type: communication
do:
- handleErr:
set:
caught: true
errorType: communication
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["caught"], json!(true));
}
#[tokio::test]
async fn test_runner_nested_switch_then_exit_inner() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-switch-exit-inner
version: '0.1.0'
do:
- outerTask:
do:
- innerSwitch:
switch:
- isReady:
when: ${ .ready == true }
then: exit
- afterSwitch:
set:
afterInner: true
- afterOuter:
set:
outerDone: true
"#;
let output = run_workflow_yaml(&yaml_str, json!({"ready": true}))
.await
.unwrap();
assert!(output.get("afterInner").is_none() || output["afterInner"] == json!(true));
assert_eq!(output["outerDone"], json!(true));
}
#[tokio::test]
async fn test_runner_do_mixed_task_types() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-mixed-tasks
version: '0.1.0'
do:
- setInitial:
set:
numbers: [1, 2, 3]
total: 0
- processAll:
for:
in: "${ .numbers }"
each: num
do:
- addToTotal:
set:
total: "${ .total + $num }"
numbers: "${ .numbers }"
- setResult:
set:
result: "${ .total }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["result"], json!(6));
}
#[tokio::test]
async fn test_runner_nested_do_inner_export() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-do-inner-export
version: '0.1.0'
do:
- outer:
do:
- inner:
set:
val: 42
export:
as: "${ {innerVal: .val} }"
- check:
set:
result: "${ $context.innerVal }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["result"], json!(42));
}
#[tokio::test]
async fn test_runner_do_nested_goto_between_levels() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-exit-between-levels
version: '0.1.0'
do:
- outerA:
set:
step: a
- outerDo:
do:
- innerB:
set:
step: b
- innerC:
set:
step: c
then: exit
- outerD:
set:
step: d
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["step"], json!("d"));
}
#[tokio::test]
async fn test_runner_do_then_end_scope() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-then-end-scope
version: '0.1.0'
do:
- outerTask:
do:
- inner1:
set:
inner: 1
then: end
- inner2:
set:
inner: 2
- afterOuter:
set:
outer: true
result: "${ .inner }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["outer"], json!(true));
assert_eq!(output["result"], json!(1));
}
#[tokio::test]
async fn test_runner_do_nested_then_exit() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-nested-then-exit
version: '0.1.0'
do:
- outer:
do:
- inner1:
set:
val: 10
then: exit
- inner2:
set:
val: 99
- afterOuter:
set:
result: "${ .val + 1 }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["result"], json!(11));
}
#[tokio::test]
async fn test_runner_do_goto_backward_with_guard() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-goto-backward
version: '0.1.0'
do:
- init:
set:
count: 0
- check:
switch:
- notDone:
when: ${ .count < 3 }
then: increment
- done:
then: end
then: continue
- increment:
set:
count: "${ .count + 1 }"
then: check
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["count"], json!(3));
}
#[tokio::test]
async fn test_runner_do_if_skip_multiple() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-if-skip-multi
version: '0.1.0'
do:
- always:
set:
x: 1
- maybe:
set:
y: 2
if: ${ .shouldRun }
- check:
set:
hasY: "${ .y != null }"
xVal: "${ .x }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({"shouldRun": false}))
.await
.unwrap();
assert_eq!(output["xVal"], json!(1));
assert_eq!(output["hasY"], json!(false));
}
#[tokio::test]
async fn test_runner_do_if_execute_multiple() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-if-exec-multi
version: '0.1.0'
do:
- always:
set:
x: 1
shouldRun: "${ .shouldRun }"
- maybe:
set:
x: "${ .x }"
y: 2
if: ${ .shouldRun }
- check:
set:
hasY: "${ .y != null }"
xVal: "${ .x }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({"shouldRun": true}))
.await
.unwrap();
assert_eq!(output["xVal"], json!(1));
assert_eq!(output["hasY"], json!(true));
}
#[tokio::test]
async fn test_runner_nested_for_loops() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: nested-for
version: '0.1.0'
do:
- outerLoop:
for:
in: "${ .items }"
each: item
do:
- process:
set:
result: "${ .result + [$item] }"
items: "${ .items }"
"#;
let runner = WorkflowRunner::new(serde_yaml::from_str(&yaml_str).unwrap()).unwrap();
let output = runner
.run(json!({"items": [10, 20, 30], "result": []}))
.await
.unwrap();
assert_eq!(output["result"], json!([10, 20, 30]));
}
#[tokio::test]
async fn test_runner_do_then_continue_explicit() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-then-continue-explicit
version: '0.1.0'
do:
- first:
set:
a: 1
then: continue
- second:
set:
b: 2
a: "${ .a }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["a"], json!(1));
assert_eq!(output["b"], json!(2));
}
#[tokio::test]
async fn test_runner_do_accumulate_state() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-accumulate-state
version: '0.1.0'
do:
- step1:
set:
a: 1
- step2:
set:
b: 2
a: "${ .a }"
- step3:
set:
c: 3
a: "${ .a }"
b: "${ .b }"
- step4:
set:
total: "${ .a + .b + .c }"
a: "${ .a }"
b: "${ .b }"
c: "${ .c }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["total"], json!(6));
assert_eq!(output["a"], json!(1));
assert_eq!(output["b"], json!(2));
assert_eq!(output["c"], json!(3));
}
#[tokio::test]
async fn test_runner_do_set_export_chain() {
let yaml_str = r#"
document:
dsl: '1.0.0'
namespace: test
name: do-set-export-chain
version: '0.1.0'
do:
- step1:
set:
val: 10
export:
as: "${ {step1: .val} }"
- step2:
set:
val: "${ .val + $context.step1 }"
export:
as: "${ {step1: $context.step1, step2: .val} }"
- step3:
set:
val: "${ .val + $context.step2 }"
step1: "${ $context.step1 }"
step2: "${ $context.step2 }"
"#;
let output = run_workflow_yaml(&yaml_str, json!({})).await.unwrap();
assert_eq!(output["val"], json!(40));
assert_eq!(output["step1"], json!(10));
assert_eq!(output["step2"], json!(20));
}