use super::Footer;
#[repr(transparent)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct References(Vec<String>);
impl<T> From<T> for References
where
T: ToString,
{
fn from(value: T) -> Self {
let references: Vec<String> = value
.to_string()
.split(",")
.flat_map(|e| match e.trim() {
"" => None,
e => Some(e.to_string()),
})
.collect();
Self(references)
}
}
impl Footer for References {
fn prefix(&self) -> &str {
"Refs: "
}
fn note(&self) -> &str {
""
}
fn as_footer(&self) -> String {
if self.0.is_empty() {
String::new()
} else {
let footers: Vec<String> = self
.0
.iter()
.map(|r| format!("{}{r}\n", self.prefix()))
.collect();
footers.join("")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_empty() {
let refs = References::default();
assert!(refs.0.is_empty());
}
#[test]
fn from_empty_string() {
assert_eq!(References::from(""), References::default());
}
#[test]
fn from_whitespace_only() {
assert_eq!(References::from(" "), References::default());
}
#[test]
fn from_single_reference() {
let refs = References::from("#123");
assert_eq!(refs.0, vec!["#123".to_string()]);
}
#[test]
fn from_comma_separated() {
let refs = References::from("#123, #456");
assert_eq!(refs.0, vec!["#123".to_string(), "#456".to_string()]);
}
#[test]
fn from_trims_leading_whitespace() {
let refs = References::from(" #123, #456");
assert_eq!(refs.0, vec!["#123".to_string(), "#456".to_string()]);
}
#[test]
fn from_trims_trailing_whitespace() {
let refs = References::from("#123 , #456 ");
assert_eq!(refs.0, vec!["#123".to_string(), "#456".to_string()]);
}
#[test]
fn from_filters_empty_segments() {
let refs = References::from("#123,,, #456");
assert_eq!(refs.0, vec!["#123".to_string(), "#456".to_string()]);
}
#[test]
fn from_owned_string() {
let input = "#123, #456".to_string();
let refs = References::from(input);
assert_eq!(refs.0, vec!["#123".to_string(), "#456".to_string()]);
}
#[test]
fn as_footer_empty() {
let refs = References::default();
assert_eq!(refs.as_footer(), "");
}
#[test]
fn as_footer_single() {
let refs = References::from("#123");
assert_eq!(refs.as_footer(), "Refs: #123\n");
}
#[test]
fn as_footer_multiple() {
let refs = References::from("#123, #456");
assert_eq!(refs.as_footer(), "Refs: #123\nRefs: #456\n");
}
#[test]
fn as_footer_jira_style() {
let refs = References::from("OPS-456, PROJ-789");
assert_eq!(refs.as_footer(), "Refs: OPS-456\nRefs: PROJ-789\n");
}
#[test]
fn footer_prefix() {
let refs = References::default();
assert_eq!(refs.prefix(), "Refs: ");
}
#[test]
fn footer_note() {
let refs = References::default();
assert_eq!(refs.note(), "");
}
#[test]
fn clone_equality() {
let refs = References::from("#123, #456");
let cloned = refs.clone();
assert_eq!(refs, cloned);
}
#[test]
fn debug_output() {
let refs = References::from("#123");
let debug = format!("{:?}", refs);
assert!(debug.contains("References"));
}
#[test]
fn inequality_different_refs() {
let a = References::from("#123");
let b = References::from("#456");
assert_ne!(a, b);
}
#[test]
fn inequality_empty_vs_non_empty() {
let empty = References::default();
let non_empty = References::from("#123");
assert_ne!(empty, non_empty);
}
}