From ad759e1ca956ff18b29533826077720066456627 Mon Sep 17 00:00:00 2001 From: Philipp Hofer Date: Wed, 29 Oct 2025 11:55:14 +0100 Subject: [PATCH] add tests for broadcasts --- src/fetch/broadcast.rs | 91 ++++++++++++++++++++++++++++++------------ src/fetch/overview.rs | 5 ++- 2 files changed, 69 insertions(+), 27 deletions(-) diff --git a/src/fetch/broadcast.rs b/src/fetch/broadcast.rs index d762486..d444d0d 100644 --- a/src/fetch/broadcast.rs +++ b/src/fetch/broadcast.rs @@ -1,22 +1,44 @@ use crate::Backend; use chrono::DateTime; -use serde_json::Value; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +struct InferenceStream { + #[serde(rename = "loopStreamId")] + pub loop_stream_id: String, + #[serde(rename = "start")] + pub start_timestamp: i64, +} + +#[derive(Debug, Serialize, Deserialize)] +struct InferenceData { + pub title: String, + pub streams: Vec, +} impl Backend { pub(crate) async fn get_broadcast( &self, url: String, ) -> Result, Box> { - let data: Value = match self { - Backend::Prod => reqwest::get(&url).await?.json().await?, + let data: InferenceData = match self { + Backend::Prod => reqwest::get(&url).await?.json::().await?, + #[cfg(test)] - Backend::Test => todo!(), + Backend::Test => InferenceData { + title: "test-title".into(), + streams: vec![InferenceStream { + loop_stream_id: "test.mp3".into(), + start_timestamp: 1761734636000, + }], + }, }; + Broadcast::from_data(url, data).await } } -#[derive(Clone)] +#[derive(Debug, Clone)] pub(crate) struct Broadcast { pub(crate) url: String, pub(crate) media_url: String, @@ -27,32 +49,23 @@ pub(crate) struct Broadcast { impl Broadcast { async fn from_data( url: String, - data: Value, + data: InferenceData, ) -> Result, Box> { - let Some(streams) = data["streams"].as_array() else { - return Err(String::from("No 'streams' found").into()); - }; - if streams.is_empty() { + if data.streams.is_empty() { return Ok(None); } - assert_eq!(streams.len(), 1); + assert_eq!(data.streams.len(), 1); + let stream = &data.streams[0]; - let Some(id) = streams[0]["loopStreamId"].as_str() else { - return Err(String::from("No 'loopStreamId' found").into()); - }; - let media_url = format!("https://loopstream01.apa.at/?channel=oe1&shoutcast=0&id={id}"); + let media_url = format!( + "https://loopstream01.apa.at/?channel=oe1&shoutcast=0&id={}", + stream.loop_stream_id + ); - let Some(title) = data["title"].as_str() else { - return Err(format!("{url} has no title").into()); - }; - - let Some(timestamp) = data["start"].as_number() else { - return Err(format!("{url} has no start").into()); - }; - let Some(timestamp) = DateTime::from_timestamp(timestamp.as_i64().unwrap() / 1000, 0) - else { + let Some(timestamp) = DateTime::from_timestamp(stream.start_timestamp / 1000, 0) else { return Err(format!( - "broadcastDay in {url} not in a valid format (unix timestamp): {timestamp}" + "broadcastDay in {url} not in a valid format (unix timestamp): {}", + stream.start_timestamp ) .into()); }; @@ -60,7 +73,7 @@ impl Broadcast { Ok(Some(Self { url, media_url, - title: title.into(), + title: data.title, timestamp, })) } @@ -71,3 +84,29 @@ impl PartialEq for Broadcast { self.url == other.url } } + +#[cfg(test)] +mod tests { + use crate::Backend; + use chrono::{TimeZone, Utc}; + + #[tokio::test] + async fn happy() { + let backend = Backend::Test; + let actual = backend + .get_broadcast("test-url".into()) + .await + .unwrap() + .unwrap(); + assert_eq!(&actual.url, "test-url"); + assert_eq!( + &actual.media_url, + "https://loopstream01.apa.at/?channel=oe1&shoutcast=0&id=test.mp3" + ); + assert_eq!(&actual.title, "test-title"); + assert_eq!( + actual.timestamp, + Utc.with_ymd_and_hms(2025, 10, 29, 10, 43, 56).unwrap() + ); + } +} diff --git a/src/fetch/overview.rs b/src/fetch/overview.rs index 895b402..4a4c970 100644 --- a/src/fetch/overview.rs +++ b/src/fetch/overview.rs @@ -89,7 +89,10 @@ mod tests { #[tokio::test] async fn filter_result() { let backend = Backend::Test; - let actual = backend.get_broadcasts(&["test-href".into()]).await.unwrap(); + let actual = backend + .get_broadcasts(&["test-title".into()]) + .await + .unwrap(); assert_eq!(actual, vec!["test-href"]); } }