Skip to main content

indodax_cli/output/
table.rs

1use 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}