1use std::collections::HashMap;
4
5use crate::step::StepOutput;
6
7#[derive(Debug, Clone, Default)]
11pub struct WorkflowContext {
12 outputs: HashMap<String, StepOutput>,
13}
14
15impl WorkflowContext {
16 pub fn new() -> Self {
18 Self::default()
19 }
20
21 pub fn output(&self, step_id: &str) -> Option<&StepOutput> {
23 self.outputs.get(step_id)
24 }
25
26 pub fn step_outputs(&self) -> &HashMap<String, StepOutput> {
28 &self.outputs
29 }
30
31 pub fn set_output(&mut self, step_id: &str, output: StepOutput) {
33 self.outputs.insert(step_id.into(), output);
34 }
35
36 pub fn is_completed(&self, step_id: &str) -> bool {
38 self.outputs.contains_key(step_id)
39 }
40
41 pub fn completed_step_ids(&self) -> Vec<&str> {
43 self.outputs.keys().map(String::as_str).collect()
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
54 fn new_context_has_no_outputs() {
55 let ctx = WorkflowContext::new();
56 assert!(ctx.step_outputs().is_empty());
57 }
58
59 #[test]
62 fn stores_step_output() {
63 let mut ctx = WorkflowContext::new();
64 let output = StepOutput::new("hello");
65 ctx.set_output("step_a", output);
66 assert!(ctx.output("step_a").is_some());
67 assert_eq!(ctx.output("step_a").unwrap().value(), "hello");
68 }
69
70 #[test]
71 fn returns_none_for_unknown_step() {
72 let ctx = WorkflowContext::new();
73 assert!(ctx.output("unknown").is_none());
74 }
75
76 #[test]
77 fn stores_multiple_outputs() {
78 let mut ctx = WorkflowContext::new();
79 ctx.set_output("a", StepOutput::new("A result"));
80 ctx.set_output("b", StepOutput::new("B result"));
81 assert_eq!(ctx.step_outputs().len(), 2);
82 }
83
84 #[test]
87 fn tracks_completed_steps() {
88 let mut ctx = WorkflowContext::new();
89 ctx.set_output("a", StepOutput::new("done"));
90 assert!(ctx.is_completed("a"));
91 assert!(!ctx.is_completed("b"));
92 }
93
94 #[test]
95 fn completed_step_ids_returns_all() {
96 let mut ctx = WorkflowContext::new();
97 ctx.set_output("x", StepOutput::new("1"));
98 ctx.set_output("y", StepOutput::new("2"));
99 let mut ids = ctx.completed_step_ids();
100 ids.sort_unstable();
101 assert_eq!(ids, vec!["x", "y"]);
102 }
103}