use serde::Serialize;
use tabled::{Table, Tabled};
use super::formatting::{print_formatted, yes_no};
use crate::types::{FieldValue, OutputFormat};
#[derive(Tabled)]
struct FieldValueRow {
#[tabled(rename = "NAME")]
name: String,
#[tabled(rename = "ACTIVE")]
active: String,
#[tabled(rename = "CAN CHANGE TO")]
can_change_to: String,
}
#[expect(clippy::print_stdout)]
pub fn print_field_values(values: &[FieldValue], format: OutputFormat) {
print_formatted(values, format, |values| {
let rows: Vec<FieldValueRow> = values
.iter()
.map(|v| {
let transitions = v
.can_change_to
.as_ref()
.map(|t| {
t.iter()
.map(|s| s.name.as_str())
.collect::<Vec<_>>()
.join(", ")
})
.unwrap_or_default();
FieldValueRow {
name: v.name.clone(),
active: yes_no(v.is_active).into(),
can_change_to: transitions,
}
})
.collect();
println!("{}", Table::new(rows));
});
}
#[derive(Serialize, Tabled)]
struct FieldAliasRow {
#[tabled(rename = "ALIAS")]
alias: &'static str,
#[tabled(rename = "API FIELD NAME")]
api_name: &'static str,
}
#[expect(clippy::print_stdout)]
pub fn print_field_aliases(aliases: &[(&'static str, &'static str)], format: OutputFormat) {
let rows: Vec<FieldAliasRow> = aliases
.iter()
.map(|&(alias, api_name)| FieldAliasRow { alias, api_name })
.collect();
print_formatted(&rows, format, |rows| {
println!("{}", Table::new(rows));
});
}
#[cfg(test)]
#[expect(clippy::unwrap_used)]
mod tests {
use crate::types::{FieldValue, StatusTransition};
#[test]
fn print_field_values_json_empty() {
let values: Vec<FieldValue> = vec![];
let json = serde_json::to_string_pretty(&values).unwrap();
assert_eq!(json, "[]");
}
#[test]
fn print_field_values_json_with_transitions() {
let values = vec![FieldValue {
name: "NEW".into(),
sort_key: 0,
is_active: true,
can_change_to: Some(vec![
StatusTransition {
name: "ASSIGNED".into(),
},
StatusTransition {
name: "RESOLVED".into(),
},
]),
}];
let json = serde_json::to_string_pretty(&values).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed[0]["name"], "NEW");
assert_eq!(parsed[0]["is_active"], true);
let transitions = parsed[0]["can_change_to"].as_array().unwrap();
assert_eq!(transitions.len(), 2);
assert_eq!(transitions[0]["name"], "ASSIGNED");
}
#[test]
fn print_field_values_table_renders_rows() {
use super::FieldValueRow;
use tabled::Table;
let rows = vec![
FieldValueRow {
name: "NEW".into(),
active: "Yes".into(),
can_change_to: "ASSIGNED, RESOLVED".into(),
},
FieldValueRow {
name: "CLOSED".into(),
active: "No".into(),
can_change_to: String::new(),
},
];
let table = Table::new(rows).to_string();
assert!(table.contains("NEW"));
assert!(table.contains("CLOSED"));
assert!(table.contains("Yes"));
assert!(table.contains("No"));
assert!(table.contains("ASSIGNED, RESOLVED"));
assert!(table.contains("NAME"));
assert!(table.contains("ACTIVE"));
assert!(table.contains("CAN CHANGE TO"));
}
#[test]
fn print_field_values_json_active_and_inactive() {
let values = vec![
FieldValue {
name: "NEW".into(),
sort_key: 0,
is_active: true,
can_change_to: Some(vec![StatusTransition {
name: "ASSIGNED".into(),
}]),
},
FieldValue {
name: "CLOSED".into(),
sort_key: 1,
is_active: false,
can_change_to: None,
},
];
let json = serde_json::to_string_pretty(&values).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed[0]["name"], "NEW");
assert_eq!(parsed[0]["is_active"], true);
assert_eq!(parsed[1]["name"], "CLOSED");
assert_eq!(parsed[1]["is_active"], false);
assert!(parsed[1]["can_change_to"].is_null());
}
#[test]
fn print_field_aliases_json_serialization() {
let aliases: &[(&str, &str)] = &[("status", "bug_status"), ("severity", "bug_severity")];
let rows: Vec<super::FieldAliasRow> = aliases
.iter()
.map(|&(alias, api_name)| super::FieldAliasRow { alias, api_name })
.collect();
let json = serde_json::to_string_pretty(&rows).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
let arr = parsed.as_array().unwrap();
assert_eq!(arr.len(), 2);
assert_eq!(arr[0]["alias"], "status");
assert_eq!(arr[0]["api_name"], "bug_status");
assert_eq!(arr[1]["alias"], "severity");
assert_eq!(arr[1]["api_name"], "bug_severity");
}
}