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 "cost_usd": 0.0,
82 "duration_ms": 0,
83 "created_at": "2026-10-06T10:00:00Z",
84 "updated_at": "2026-10-06T10:00:00Z",
85 "created_by": {"kind": "system", "label": "cron"},
86 })
87 }
88
89 fn row_of(output: &str) -> &str {
90 output
91 .lines()
92 .find(|line| line.contains("deploy"))
93 .expect("the row")
94 }
95
96 #[test]
97 fn paused_table_shows_the_resume_target_and_the_sub_runs_paused() {
98 let id = Uuid::now_v7();
99 let mut fields = run_fields(id, "paused");
100 fields["resume_status"] = json!("sleeping");
101 fields["paused_descendants"] = json!([Uuid::now_v7()]);
102 let pause: PauseRunResponse = from_value(fields).expect("a pause response");
103
104 let output = paused_table(&pause).to_string();
105
106 assert!(output.contains("Resumes to"), "{output}");
107 assert!(output.contains(&id.to_string()), "{output}");
108 let row = row_of(&output);
109 assert!(row.contains("sleeping"), "{row}");
110 assert!(row.contains(" 1 "), "{row}");
111 }
112
113 #[test]
114 fn resumed_table_shows_the_sub_runs_resumed() {
115 let id = Uuid::now_v7();
116 let mut fields = run_fields(id, "pending");
117 fields["resumed_descendants"] = json!([Uuid::now_v7(), Uuid::now_v7()]);
118 let resume: ResumeRunResponse = from_value(fields).expect("a resume response");
119
120 let output = resumed_table(&resume).to_string();
121
122 assert!(output.contains("Sub-runs resumed"), "{output}");
123 let row = row_of(&output);
124 assert!(row.contains("pending"), "{row}");
125 assert!(row.contains(" 2 "), "{row}");
126 }
127
128 #[test]
129 fn workflow_pause_table_shows_when_the_workflow_was_paused() {
130 let pause: WorkflowPauseResponse = from_value(json!({
131 "workflow_name": "deploy",
132 "paused_at": "2026-10-06T10:00:00Z",
133 }))
134 .expect("a workflow pause response");
135
136 let output = workflow_pause_table(&pause).to_string();
137
138 let row = row_of(&output);
139 assert!(row.contains("yes"), "{row}");
140 assert!(row.contains("2026-10-06 10:00:00"), "{row}");
141 }
142
143 #[test]
144 fn workflow_pause_table_shows_a_resumed_workflow() {
145 let pause: WorkflowPauseResponse = from_value(json!({
146 "workflow_name": "deploy",
147 }))
148 .expect("a workflow pause response");
149
150 let output = workflow_pause_table(&pause).to_string();
151
152 let row = row_of(&output);
153 assert!(row.contains("no"), "{row}");
154 assert!(row.contains('-'), "{row}");
155 }
156}