use super::CommandOutput;
use comfy_table::presets::UTF8_FULL;
use comfy_table::{Cell, Color, ContentArrangement, Table};
pub fn render(output: &CommandOutput) -> String {
if output.headers.is_empty() && output.rows.is_empty() {
if let Some(ref addendum) = output.addendum {
return addendum.clone();
}
return serde_json::to_string_pretty(&output.data).unwrap_or_default();
}
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_header(
output
.headers
.iter()
.map(|h| Cell::new(h).fg(Color::Cyan))
.collect::<Vec<_>>(),
);
for row in &output.rows {
table.add_row(row.iter().map(Cell::new).collect::<Vec<_>>());
}
let mut result = table.to_string();
if let Some(ref addendum) = output.addendum {
result.push('\n');
result.push_str(addendum);
}
if !output.warnings.is_empty() {
result.push('\n');
for warning in &output.warnings {
result.push_str(&format!("\nWarning: {}", warning));
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_render_with_headers_and_rows() {
let output = CommandOutput {
data: json!({}),
headers: vec!["Col1".into(), "Col2".into()],
rows: vec![
vec!["a".into(), "b".into()],
vec!["c".into(), "d".into()],
],
format: super::super::OutputFormat::Table,
addendum: None,
warnings: vec![],
suppress_final_output: false,
};
let rendered = render(&output);
assert!(rendered.contains("Col1"));
assert!(rendered.contains("Col2"));
assert!(rendered.contains("a"));
assert!(rendered.contains("b"));
}
#[test]
fn test_render_empty_headers_and_rows() {
let output = CommandOutput {
data: json!({"fallback": "data"}),
headers: vec![],
rows: vec![],
format: super::super::OutputFormat::Table,
addendum: None,
warnings: vec![],
suppress_final_output: false,
};
let rendered = render(&output);
assert!(rendered.contains("fallback") || rendered.contains("data") || rendered.contains("{}"));
}
#[test]
fn test_render_with_addendum() {
let output = CommandOutput {
data: json!({}),
headers: vec!["H".into()],
rows: vec![vec!["v".into()]],
format: super::super::OutputFormat::Table,
addendum: Some("Extra info here".into()),
warnings: vec![],
suppress_final_output: false,
};
let rendered = render(&output);
assert!(rendered.contains("Extra info here"));
}
#[test]
fn test_render_no_addendum() {
let output = CommandOutput {
data: json!({}),
headers: vec!["H".into()],
rows: vec![vec!["v".into()]],
format: super::super::OutputFormat::Table,
addendum: None,
warnings: vec![],
suppress_final_output: false,
};
let rendered = render(&output);
assert!(!rendered.ends_with('\n') || !rendered.trim().is_empty());
}
}