indodax_cli/output/
table.rs1use super::CommandOutput;
2use comfy_table::presets::UTF8_FULL;
3use comfy_table::{Cell, Color, ContentArrangement, Table};
4
5pub fn render(output: &CommandOutput) -> String {
6 if output.headers.is_empty() && output.rows.is_empty() {
7 if let Some(ref addendum) = output.addendum {
8 return addendum.clone();
9 }
10 return serde_json::to_string_pretty(&output.data).unwrap_or_default();
11 }
12
13 let mut table = Table::new();
14 table
15 .load_preset(UTF8_FULL)
16 .set_content_arrangement(ContentArrangement::Dynamic)
17 .set_header(
18 output
19 .headers
20 .iter()
21 .map(|h| Cell::new(h).fg(Color::Cyan))
22 .collect::<Vec<_>>(),
23 );
24
25 for row in &output.rows {
26 table.add_row(row.iter().map(Cell::new).collect::<Vec<_>>());
27 }
28
29 let mut result = table.to_string();
30
31 if let Some(ref addendum) = output.addendum {
32 result.push('\n');
33 result.push_str(addendum);
34 }
35
36 if !output.warnings.is_empty() {
37 result.push('\n');
38 for warning in &output.warnings {
39 result.push_str(&format!("\nWarning: {}", warning));
40 }
41 }
42
43 result
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use serde_json::json;
50
51 #[test]
52 fn test_render_with_headers_and_rows() {
53 let output = CommandOutput {
54 data: json!({}),
55 headers: vec!["Col1".into(), "Col2".into()],
56 rows: vec![
57 vec!["a".into(), "b".into()],
58 vec!["c".into(), "d".into()],
59 ],
60 format: super::super::OutputFormat::Table,
61 addendum: None,
62 warnings: vec![],
63 suppress_final_output: false,
64 };
65
66 let rendered = render(&output);
67 assert!(rendered.contains("Col1"));
68 assert!(rendered.contains("Col2"));
69 assert!(rendered.contains("a"));
70 assert!(rendered.contains("b"));
71 }
72
73 #[test]
74 fn test_render_empty_headers_and_rows() {
75 let output = CommandOutput {
76 data: json!({"fallback": "data"}),
77 headers: vec![],
78 rows: vec![],
79 format: super::super::OutputFormat::Table,
80 addendum: None,
81 warnings: vec![],
82 suppress_final_output: false,
83 };
84
85 let rendered = render(&output);
86 assert!(rendered.contains("fallback") || rendered.contains("data") || rendered.contains("{}"));
87 }
88
89 #[test]
90 fn test_render_with_addendum() {
91 let output = CommandOutput {
92 data: json!({}),
93 headers: vec!["H".into()],
94 rows: vec![vec!["v".into()]],
95 format: super::super::OutputFormat::Table,
96 addendum: Some("Extra info here".into()),
97 warnings: vec![],
98 suppress_final_output: false,
99 };
100
101 let rendered = render(&output);
102 assert!(rendered.contains("Extra info here"));
103 }
104
105 #[test]
106 fn test_render_no_addendum() {
107 let output = CommandOutput {
108 data: json!({}),
109 headers: vec!["H".into()],
110 rows: vec![vec!["v".into()]],
111 format: super::super::OutputFormat::Table,
112 addendum: None,
113 warnings: vec![],
114 suppress_final_output: false,
115 };
116
117 let rendered = render(&output);
118 assert!(!rendered.ends_with('\n') || !rendered.trim().is_empty());
119 }
120}