Files
pmomusic/pmoparadise/tests/integration_tests.rs

221 lines
6.5 KiB
Rust

//! Integration tests for pmoparadise
use pmoparadise::{Block, RadioParadiseClient};
use serde_json::json;
use wiremock::matchers::{method, path, query_param};
use wiremock::{Mock, MockServer, ResponseTemplate};
/// Create a mock Block JSON response
fn mock_block_json(event: u64, end_event: u64) -> serde_json::Value {
json!({
"event": event,
"end_event": end_event,
"length": 900000,
"url": format!("https://apps.radioparadise.com/blocks/chan/0/4/{}-{}.flac", event, end_event),
"image_base": "https://img.radioparadise.com/covers/l/",
"song": {
"0": {
"artist": "Miles Davis",
"title": "So What",
"album": "Kind of Blue",
"year": 1959,
"elapsed": 0,
"duration": 540000,
"cover": "B00000I0JF.jpg",
"rating": 9.2
},
"1": {
"artist": "John Coltrane",
"title": "Giant Steps",
"album": "Giant Steps",
"year": 1960,
"elapsed": 540000,
"duration": 360000,
"cover": "B000002I4U.jpg",
"rating": 9.5
}
}
})
}
#[tokio::test]
async fn test_get_current_block() {
// Start mock server
let mock_server = MockServer::start().await;
// Setup mock response
Mock::given(method("GET"))
.and(path("/api/get_block"))
.and(query_param("bitrate", "4"))
.and(query_param("info", "true"))
.respond_with(ResponseTemplate::new(200).set_body_json(mock_block_json(1234, 5678)))
.mount(&mock_server)
.await;
// Create client with mock server URL
let client = RadioParadiseClient::builder()
.api_base(format!("{}/api", mock_server.uri()))
.build()
.await
.unwrap();
// Test get_block
let block = client.get_block(None).await.unwrap();
assert_eq!(block.event, 1234);
assert_eq!(block.end_event, 5678);
assert_eq!(block.length, 900000);
assert_eq!(block.song_count(), 2);
// Check songs
let songs = block.songs_ordered();
assert_eq!(songs.len(), 2);
assert_eq!(songs[0].1.artist, "Miles Davis");
assert_eq!(songs[1].1.artist, "John Coltrane");
}
#[tokio::test]
async fn test_get_specific_block() {
let mock_server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/api/get_block"))
.and(query_param("bitrate", "4"))
.and(query_param("info", "true"))
.and(query_param("event", "5678"))
.respond_with(ResponseTemplate::new(200).set_body_json(mock_block_json(5678, 9012)))
.mount(&mock_server)
.await;
let client = RadioParadiseClient::builder()
.api_base(format!("{}/api", mock_server.uri()))
.build()
.await
.unwrap();
let block = client.get_block(Some(5678)).await.unwrap();
assert_eq!(block.event, 5678);
assert_eq!(block.end_event, 9012);
}
#[tokio::test]
async fn test_now_playing() {
let mock_server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/api/get_block"))
.respond_with(ResponseTemplate::new(200).set_body_json(mock_block_json(1234, 5678)))
.mount(&mock_server)
.await;
let client = RadioParadiseClient::builder()
.api_base(format!("{}/api", mock_server.uri()))
.build()
.await
.unwrap();
let now_playing = client.now_playing().await.unwrap();
assert_eq!(now_playing.block.event, 1234);
assert_eq!(now_playing.current_song_index, Some(0));
assert!(now_playing.current_song.is_some());
if let Some(song) = &now_playing.current_song {
assert_eq!(song.artist, "Miles Davis");
assert_eq!(song.title, "So What");
}
}
#[tokio::test]
async fn test_prefetch_next() {
let mock_server = MockServer::start().await;
// First block
Mock::given(method("GET"))
.and(query_param("event", "1234"))
.respond_with(ResponseTemplate::new(200).set_body_json(mock_block_json(1234, 5678)))
.mount(&mock_server)
.await;
// Next block
Mock::given(method("GET"))
.and(query_param("event", "5678"))
.respond_with(ResponseTemplate::new(200).set_body_json(mock_block_json(5678, 9012)))
.mount(&mock_server)
.await;
let mut client = RadioParadiseClient::builder()
.api_base(format!("{}/api", mock_server.uri()))
.build()
.await
.unwrap();
let current_block = client.get_block(Some(1234)).await.unwrap();
assert_eq!(current_block.end_event, 5678);
client.prefetch_next(&current_block).await.unwrap();
let next_url = client.next_block_url().unwrap();
assert!(next_url.contains("5678-9012.flac"));
}
#[tokio::test]
async fn test_block_parse_url_events() {
let json = mock_block_json(1234, 5678);
let block: Block = serde_json::from_value(json).unwrap();
let (start, end) = block.parse_url_events().unwrap();
assert_eq!(start, 1234);
assert_eq!(end, 5678);
}
#[tokio::test]
async fn test_song_timing() {
let json = mock_block_json(1234, 5678);
let block: Block = serde_json::from_value(json).unwrap();
// Find song at 0ms (should be first song)
let (idx, song) = block.song_at_timestamp(0).unwrap();
assert_eq!(idx, 0);
assert_eq!(song.title, "So What");
// Find song at 600000ms (should be second song)
let (idx, song) = block.song_at_timestamp(600000).unwrap();
assert_eq!(idx, 1);
assert_eq!(song.title, "Giant Steps");
// Timestamp beyond block
assert!(block.song_at_timestamp(1000000).is_none());
}
#[tokio::test]
async fn test_song_cover_url() {
let json = mock_block_json(1234, 5678);
let block: Block = serde_json::from_value(json).unwrap();
let song = block.get_song(0).unwrap();
let cover_url = block.cover_url(song.cover.as_ref().unwrap()).unwrap();
assert_eq!(
cover_url,
"https://img.radioparadise.com/covers/l/B00000I0JF.jpg"
);
}
#[cfg(feature = "per-track")]
#[tokio::test]
async fn test_track_position_seconds() {
let client = RadioParadiseClient::new().await.unwrap();
let json = mock_block_json(1234, 5678);
let block: Block = serde_json::from_value(json).unwrap();
let (start, duration) = client.track_position_seconds(&block, 0).unwrap();
assert_eq!(start, 0.0);
assert_eq!(duration, 540.0);
let (start, duration) = client.track_position_seconds(&block, 1).unwrap();
assert_eq!(start, 540.0);
assert_eq!(duration, 360.0);
}