oxify_model/
edge.rs

1use crate::NodeId;
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[cfg(feature = "openapi")]
6use utoipa::ToSchema;
7
8/// Unique identifier for an edge
9pub type EdgeId = Uuid;
10
11/// Edge connecting nodes in the workflow DAG
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[cfg_attr(feature = "openapi", derive(ToSchema))]
14pub struct Edge {
15    /// Unique edge identifier
16    #[cfg_attr(feature = "openapi", schema(value_type = String))]
17    pub id: EdgeId,
18
19    /// Source node
20    #[cfg_attr(feature = "openapi", schema(value_type = String))]
21    pub from: NodeId,
22
23    /// Target node
24    #[cfg_attr(feature = "openapi", schema(value_type = String))]
25    pub to: NodeId,
26
27    /// Optional label for the edge
28    pub label: Option<String>,
29
30    /// Condition for this edge (for conditional nodes)
31    pub condition: Option<String>,
32}
33
34impl Edge {
35    pub fn new(from: NodeId, to: NodeId) -> Self {
36        Self {
37            id: Uuid::new_v4(),
38            from,
39            to,
40            label: None,
41            condition: None,
42        }
43    }
44
45    pub fn with_label(mut self, label: String) -> Self {
46        self.label = Some(label);
47        self
48    }
49
50    pub fn with_condition(mut self, condition: String) -> Self {
51        self.condition = Some(condition);
52        self
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_edge_creation() {
62        let from = Uuid::new_v4();
63        let to = Uuid::new_v4();
64        let edge = Edge::new(from, to)
65            .with_label("success".to_string())
66            .with_condition("result.ok".to_string());
67
68        assert_eq!(edge.from, from);
69        assert_eq!(edge.to, to);
70        assert_eq!(edge.label, Some("success".to_string()));
71        assert_eq!(edge.condition, Some("result.ok".to_string()));
72    }
73
74    #[test]
75    fn test_edge_basic_creation() {
76        let from = Uuid::new_v4();
77        let to = Uuid::new_v4();
78        let edge = Edge::new(from, to);
79
80        assert_eq!(edge.from, from);
81        assert_eq!(edge.to, to);
82        assert_eq!(edge.label, None);
83        assert_eq!(edge.condition, None);
84        assert_ne!(edge.id, Uuid::nil());
85    }
86
87    #[test]
88    fn test_edge_with_label_only() {
89        let from = Uuid::new_v4();
90        let to = Uuid::new_v4();
91        let edge = Edge::new(from, to).with_label("branch_a".to_string());
92
93        assert_eq!(edge.label, Some("branch_a".to_string()));
94        assert_eq!(edge.condition, None);
95    }
96
97    #[test]
98    fn test_edge_with_condition_only() {
99        let from = Uuid::new_v4();
100        let to = Uuid::new_v4();
101        let edge = Edge::new(from, to).with_condition("x > 10".to_string());
102
103        assert_eq!(edge.condition, Some("x > 10".to_string()));
104        assert_eq!(edge.label, None);
105    }
106
107    #[test]
108    fn test_edge_unique_ids() {
109        let from = Uuid::new_v4();
110        let to = Uuid::new_v4();
111
112        let edge1 = Edge::new(from, to);
113        let edge2 = Edge::new(from, to);
114
115        assert_ne!(edge1.id, edge2.id);
116    }
117
118    #[test]
119    fn test_edge_builder_pattern_chaining() {
120        let from = Uuid::new_v4();
121        let to = Uuid::new_v4();
122
123        let edge = Edge::new(from, to)
124            .with_label("test".to_string())
125            .with_condition("true".to_string());
126
127        assert_eq!(edge.label, Some("test".to_string()));
128        assert_eq!(edge.condition, Some("true".to_string()));
129        assert_eq!(edge.from, from);
130        assert_eq!(edge.to, to);
131    }
132
133    #[test]
134    fn test_edge_serialization() {
135        let from = Uuid::new_v4();
136        let to = Uuid::new_v4();
137        let edge = Edge::new(from, to).with_label("success".to_string());
138
139        let json = serde_json::to_string(&edge).unwrap();
140        let deserialized: Edge = serde_json::from_str(&json).unwrap();
141
142        assert_eq!(edge.id, deserialized.id);
143        assert_eq!(edge.from, deserialized.from);
144        assert_eq!(edge.to, deserialized.to);
145        assert_eq!(edge.label, deserialized.label);
146        assert_eq!(edge.condition, deserialized.condition);
147    }
148}