use chrono::{DateTime, Utc}; use rss2email_lib::{ xml::{error::ParserError, parse_web_feed}, Blog, Post, }; use pretty_assertions::assert_eq; fn read_file(dir_name: &str, file_name: &str) -> String { use std::fs; use std::path::PathBuf; let mut file_path = PathBuf::from("test-data"); file_path.push(dir_name); file_path.push(file_name); fs::read_to_string(file_path).expect("Cannot read feed ") } fn read_rss(file_name: &str) -> String { read_file("rss-feeds", file_name) } fn read_atom(file_name: &str) -> String { read_file("atom-feeds", file_name) } fn post_date(value: &str) -> DateTime { value .parse::>() .unwrap_or_else(|_| panic!("Invalid date {value}")) } #[test] fn test_parse_brief_single_entry_atom() { let content = read_atom("brief-single-entry.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); assert_eq!( blog, Blog { title: "Example Feed".into(), most_recent_pub_date: post_date("2003-12-13T18:30:02+00:00"), posts: vec![Post { title: "Atom-Powered Robots Run Amok".into(), link: "http://example.org/2003/12/13/atom03".into(), description: Some("Some text.".into()), pub_date: post_date("2003-12-13T18:30:02+00:00"), }], } ); } #[test] fn test_parse_complex_single_entry_atom() { let content = read_atom("complex-single-entry.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); // The chosen link is the .../2005/04/02/atom because it is the first in the list assert_eq!( blog, Blog { title: "dive into mark".into(), most_recent_pub_date: post_date("2003-12-13T08:29:29-04:00"), posts: vec![Post { title: "Atom draft-07 snapshot".into(), link: "http://example.org/2005/04/02/atom".into(), description: None, pub_date: post_date("2003-12-13T08:29:29-04:00"), }], } ); } #[test] fn test_parse_atom_without_entry() { let content = read_atom("no-entries.xml"); let result = parse_web_feed(&content); assert!(result.is_err()); let is_empty_feed_error = match result.expect_err("Should error") { ParserError::Parse(p) => p.contains("Empty feed"), ParserError::Date(_) => false, }; assert!(is_empty_feed_error); } #[test] fn test_parse_atom_with_many_entries() { let content = read_atom("multi-entries.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); let first_date = post_date("2022-09-18T21:00:00+00:00"); let second_date = post_date("2022-10-21T21:10:00+00:00"); assert_eq!( blog, Blog { title: "Multi-Entries Feed".into(), most_recent_pub_date: second_date, posts: vec![ Post { title: "First title".into(), link: "http://awesome.com/link1.html".into(), description: Some("First content".into()), pub_date: first_date, }, Post { title: "Second title".into(), link: "http://com.net/why-not.html".into(), description: None, pub_date: second_date, } ], } ); } #[test] fn test_parse_atom_text_with_html_tags() { let content = read_atom("entry-with-html.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); let date = post_date("2022-09-18T21:00:00+00:00"); assert_eq!( blog, Blog { title: "Multi-Entries Feed".into(), most_recent_pub_date: date, posts: vec![Post { title: "Star City".into(), link: "http://link.com".into(), description: Some( "How did it work? Details here" .into() ), pub_date: date, }], } ); } // Ignored: // - multiple feeds in a single document #[test] fn test_parse_rss_data() { let content = read_rss("self-rss.xml"); let _blog = parse_web_feed(&content).expect("Parsed content"); } #[test] fn test_parse_rss_0_91() { let content = read_rss("sample-0_91.xml"); let result = parse_web_feed(&content); assert!(result.is_err()); } #[test] fn test_parse_rss_0_92() { let content = read_rss("sample-0_92.xml"); let result = parse_web_feed(&content); assert!(result.is_err()); } #[test] fn test_parse_rss_2() { let content = read_rss("sample-2.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); assert_eq!( blog, Blog { title: "Liftoff News".into(), most_recent_pub_date: post_date("2003-06-10T04:00:00+00:00"), posts: vec![Post { title: "Star City".into(), link:"http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp".into(), description: Some("How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's Star City".into(), link: "http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp".into(), description: Some( "How did it work? Details here" .into() ), pub_date: post_date("2003-06-03T09:39:21+00:00"), }], } ); } #[test] fn test_parse_rss_without_items() { let content = read_rss("v2-without-items.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); assert_eq!( blog, Blog { title: "NoNews".into(), most_recent_pub_date: post_date("2003-06-10T04:00:00+00:00"), posts: vec![] } ); } /// Tests that entries without links are correctly ignored /// Not having a link means that there is no place to redirect to to read the story #[test] fn test_parse_rss_entry_without_link() { let content = read_rss("v2-without-link.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); assert_eq!( blog, Blog { title: "Liftoff News".into(), most_recent_pub_date: post_date("2003-06-10T04:00:00+00:00"), posts: vec![ Post { title: "Star City".into(), link: "http://abc.com".into(), description: None, pub_date: post_date("2003-06-03T09:39:21+00:00"), }, Post { title: "Planet City".into(), link: "http://def.com".into(), description: Some("def".into()), pub_date: post_date("2003-06-03T09:39:21+00:00"), } ], } ); } #[test] fn test_parse_rss_entry_without_title_and_short_description() { let content = read_rss("v2-without-title-short-desc.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); assert_eq!( blog, Blog { title: "Liftoff News".into(), most_recent_pub_date: post_date("2003-06-10T04:00:00+00:00"), posts: vec![Post { title: "Liftoff at Star City".into(), link: "http://liftoff.msfc.nasa.gov".into(), description: None, pub_date: post_date("2003-06-03T09:39:21+00:00"), }], } ); } #[test] fn test_parse_rss_entry_without_title_and_long_description() { let content = read_rss("v2-without-title-long-desc.xml"); let blog = parse_web_feed(&content).expect("Parsed content"); assert_eq!( blog, Blog { title: "Liftoff News".into(), most_recent_pub_date: post_date("2003-06-10T04:00:00+00:00"), posts: vec![Post { title: "How do Americans get ready to work with Russians a...".into(), link: "http://liftoff.msfc.nasa.gov".into(), description: Some( "How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's Star City." .into() ), pub_date: post_date("2003-06-03T09:39:21+00:00"), }], } ); }