pinto/backlog/
workflow.rs1use super::Status;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Workflow {
8 columns: Vec<Status>,
9}
10
11impl Workflow {
12 pub fn new(columns: impl IntoIterator<Item = Status>) -> Self {
14 Self {
15 columns: columns.into_iter().collect(),
16 }
17 }
18
19 #[must_use]
21 pub fn columns(&self) -> &[Status] {
22 &self.columns
23 }
24
25 #[must_use]
27 pub fn default_status(&self) -> Option<&Status> {
28 self.columns.first()
29 }
30
31 #[must_use]
33 pub fn contains(&self, status: &Status) -> bool {
34 self.columns.contains(status)
35 }
36
37 #[must_use]
41 pub fn can_transition(&self, from: &Status, to: &Status) -> bool {
42 self.contains(from) && self.contains(to)
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 fn workflow() -> Workflow {
51 Workflow::new(
52 ["todo", "in-progress", "review", "done"]
53 .into_iter()
54 .map(Status::new),
55 )
56 }
57
58 #[test]
59 fn workflow_default_status_is_first_column() {
60 assert_eq!(workflow().default_status(), Some(&Status::new("todo")));
61 }
62
63 #[test]
64 fn workflow_allows_transition_between_known_columns() {
65 let wf = workflow();
66 assert!(wf.can_transition(&Status::new("todo"), &Status::new("done")));
67 assert!(wf.can_transition(&Status::new("review"), &Status::new("in-progress")));
68 }
69
70 #[test]
71 fn workflow_rejects_transition_to_unknown_column() {
72 let wf = workflow();
73 assert!(!wf.can_transition(&Status::new("todo"), &Status::new("archived")));
74 assert!(!wf.can_transition(&Status::new("backlog"), &Status::new("done")));
75 }
76}