2026-09-15 07:26:00 +00:00
|
|
|
/// Trims a feed URL entered by the user, returning `None` when it's blank
|
|
|
|
|
/// so the submit handler can bail out before making a request.
|
|
|
|
|
pub fn normalize_feed_url(input: &str) -> Option<String> {
|
|
|
|
|
let trimmed = input.trim();
|
|
|
|
|
if trimmed.is_empty() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
Some(trimmed.to_string())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Success message shown after a feed subscription pulls in new articles.
|
|
|
|
|
pub fn subscribed_message(article_count: usize) -> String {
|
|
|
|
|
format!("Subscribed — pulled in {article_count} article(s).")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn blank_input_normalizes_to_none() {
|
|
|
|
|
assert_eq!(normalize_feed_url(""), None);
|
|
|
|
|
assert_eq!(normalize_feed_url(" "), None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn surrounding_whitespace_is_trimmed() {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
normalize_feed_url(" https://example.com/feed.xml "),
|
|
|
|
|
Some("https://example.com/feed.xml".to_string())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn message_reports_the_article_count() {
|
2026-09-15 07:42:08 +00:00
|
|
|
assert_eq!(
|
|
|
|
|
subscribed_message(0),
|
|
|
|
|
"Subscribed — pulled in 0 article(s)."
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
subscribed_message(3),
|
|
|
|
|
"Subscribed — pulled in 3 article(s)."
|
|
|
|
|
);
|
2026-09-15 07:26:00 +00:00
|
|
|
}
|
|
|
|
|
}
|