Adds an end-to-end integration test that runs the real pipeline against live YouTube Atom feeds, verifying the merged feed is newest-first across channels.
69 lines
2.4 KiB
Rust
69 lines
2.4 KiB
Rust
//! End-to-end check of the real pipeline: Takeout CSV -> live Atom feeds ->
|
|
//! SQLite -> feed query. Hits the network, so it is ignored by default.
|
|
//! Run with: cargo test --test pipeline -- --ignored --nocapture
|
|
|
|
use flighttube_lib::{db::Db, feed, models::FeedFilter, takeout};
|
|
|
|
const CSV: &str = include_str!("fixtures/subscriptions.csv");
|
|
|
|
#[tokio::test]
|
|
#[ignore]
|
|
async fn full_pipeline_against_live_feeds() {
|
|
let channels = takeout::parse_csv(CSV).expect("CSV should parse");
|
|
println!("parsed {} channels", channels.len());
|
|
assert!(channels.len() >= 10);
|
|
|
|
let mut db = Db::open_in_memory_pub().expect("db");
|
|
db.upsert_channels(&channels).unwrap();
|
|
|
|
let http = reqwest::Client::builder()
|
|
.user_agent("FlightTube/0.1 (+desktop)")
|
|
.timeout(std::time::Duration::from_secs(20))
|
|
.build()
|
|
.unwrap();
|
|
|
|
let mut total = 0;
|
|
for c in &channels {
|
|
match feed::fetch_channel(&http, &c.id).await {
|
|
Ok(v) => {
|
|
println!(" {:<30} {} videos", c.title, v.len());
|
|
total += v.len();
|
|
db.upsert_videos(&v).unwrap();
|
|
}
|
|
Err(e) => println!(" {:<30} FAILED: {e}", c.title),
|
|
}
|
|
}
|
|
assert!(total > 50, "expected a real feed, got {total} videos");
|
|
|
|
let all = db.list_feed(&FeedFilter::default()).unwrap();
|
|
println!("\nfeed rows: {}", all.len());
|
|
|
|
// The whole point: newest first, across all channels.
|
|
for w in all.windows(2) {
|
|
assert!(w[0].published >= w[1].published, "feed must be newest-first");
|
|
}
|
|
println!("top 5 newest across all subscriptions:");
|
|
for item in all.iter().take(5) {
|
|
println!(
|
|
" [{}] {} — {}",
|
|
item.channel_title,
|
|
item.title.chars().take(60).collect::<String>(),
|
|
item.published
|
|
);
|
|
}
|
|
|
|
let no_shorts = db
|
|
.list_feed(&FeedFilter { hide_shorts: true, ..Default::default() })
|
|
.unwrap();
|
|
println!("\nwith shorts hidden: {} (was {})", no_shorts.len(), all.len());
|
|
assert!(no_shorts.len() <= all.len());
|
|
assert!(no_shorts.iter().all(|i| !i.is_short));
|
|
|
|
// Nothing is downloaded, so the offline view must be empty.
|
|
let offline = db
|
|
.list_feed(&FeedFilter { downloaded_only: true, ..Default::default() })
|
|
.unwrap();
|
|
assert_eq!(offline.len(), 0, "nothing downloaded yet");
|
|
println!("offline view with no downloads: {} rows (correct)", offline.len());
|
|
}
|