ironflow_cli/output/
pause.rs1use comfy_table::{Cell, CellAlignment, Table};
5use ironflow_sdk::types::{PauseRunResponse, ResumeRunResponse, WorkflowPauseResponse};
6
7use super::{base_table, format_optional_datetime, status_color};
8
9pub fn paused_table(pause: &PauseRunResponse) -> Table {
12 let mut table = base_table();
13 table.set_header(vec![
14 "ID",
15 "Workflow",
16 "Status",
17 "Resumes to",
18 "Sub-runs paused",
19 ]);
20 let resumes_to = pause
21 .resume_status
22 .map_or_else(|| "-".to_string(), |status| status.to_string());
23 table.add_row(vec![
24 Cell::new(pause.id),
25 Cell::new(&pause.workflow_name),
26 Cell::new(pause.status)
27 .fg(status_color(&pause.status))
28 .set_alignment(CellAlignment::Center),
29 Cell::new(resumes_to),
30 Cell::new(pause.paused_descendants.len()),
31 ]);
32 table
33}
34
35pub fn resumed_table(resume: &ResumeRunResponse) -> Table {
37 let mut table = base_table();
38 table.set_header(vec!["ID", "Workflow", "Status", "Sub-runs resumed"]);
39 table.add_row(vec![
40 Cell::new(resume.id),
41 Cell::new(&resume.workflow_name),
42 Cell::new(resume.status)
43 .fg(status_color(&resume.status))
44 .set_alignment(CellAlignment::Center),
45 Cell::new(resume.resumed_descendants.len()),
46 ]);
47 table
48}
49
50pub fn workflow_pause_table(pause: &WorkflowPauseResponse) -> Table {
52 let mut table = base_table();
53 table.set_header(vec!["Workflow", "Paused", "Paused at"]);
54 table.add_row(vec![
55 Cell::new(&pause.workflow_name),
56 Cell::new(if pause.paused_at.is_some() {
57 "yes"
58 } else {
59 "no"
60 }),
61 Cell::new(format_optional_datetime(&pause.paused_at)),
62 ]);
63 table
64}
65
66#[cfg(test)]
67mod tests {
68 use serde_json::{Value, from_value, json};
69 use uuid::Uuid;
70
71 use super::*;
72
73 fn run_fields(id: Uuid, status: &str) -> Value {
74 json!({
75 "id": id,
76 "workflow_name": "deploy",
77 "status": status,
78 "trigger": {"kind": "manual"},
79 "retry_count": 0,
80 "max_retries": 0,
81 "lease_recoveries": 0,
82 "cost_usd": 0.0,
83 "duration_ms": 0,
84 "created_at": "2026-10-06T10:00:00Z",
85 "updated_at": "2026-10-06T10:00:00Z",
86 "created_by": {"kind": "system", "label": "cron"},
87 })
88 }
89
90 fn row_of(output: &str) -> &str {
91 output
92 .lines()
93 .find(|line| line.contains("deploy"))
94 .expect("the row")
95 }
96
97 #[test]
98 fn paused_table_shows_the_resume_target_and_the_sub_runs_paused() {
99 let id = Uuid::now_v7();
100 let mut fields = run_fields(id, "paused");
101 fields["resume_status"] = json!("sleeping");
102 fields["paused_descendants"] = json!([Uuid::now_v7()]);
103 let pause: PauseRunResponse = from_value(fields).expect("a pause response");
104
105 let output = paused_table(&pause).to_string();
106
107 assert!(output.contains("Resumes to"), "{output}");
108 assert!(output.contains(&id.to_string()), "{output}");
109 let row = row_of(&output);
110 assert!(row.contains("sleeping"), "{row}");
111 assert!(row.contains(" 1 "), "{row}");
112 }
113
114 #[test]
115 fn resumed_table_shows_the_sub_runs_resumed() {
116 let id = Uuid::now_v7();
117 let mut fields = run_fields(id, "pending");
118 fields["resumed_descendants"] = json!([Uuid::now_v7(), Uuid::now_v7()]);
119 let resume: ResumeRunResponse = from_value(fields).expect("a resume response");
120
121 let output = resumed_table(&resume).to_string();
122
123 assert!(output.contains("Sub-runs resumed"), "{output}");
124 let row = row_of(&output);
125 assert!(row.contains("pending"), "{row}");
126 assert!(row.contains(" 2 "), "{row}");
127 }
128
129 #[test]
130 fn workflow_pause_table_shows_when_the_workflow_was_paused() {
131 let pause: WorkflowPauseResponse = from_value(json!({
132 "workflow_name": "deploy",
133 "paused_at": "2026-10-06T10:00:00Z",
134 }))
135 .expect("a workflow pause response");
136
137 let output = workflow_pause_table(&pause).to_string();
138
139 let row = row_of(&output);
140 assert!(row.contains("yes"), "{row}");
141 assert!(row.contains("2026-10-06 10:00:00"), "{row}");
142 }
143
144 #[test]
145 fn workflow_pause_table_shows_a_resumed_workflow() {
146 let pause: WorkflowPauseResponse = from_value(json!({
147 "workflow_name": "deploy",
148 }))
149 .expect("a workflow pause response");
150
151 let output = workflow_pause_table(&pause).to_string();
152
153 let row = row_of(&output);
154 assert!(row.contains("no"), "{row}");
155 assert!(row.contains('-'), "{row}");
156 }
157}