crabidy/soundclouddy/tests/live.rs

76 lines
2.4 KiB
Rust

//! Live validation against the real SoundCloud API. `#[ignore]`d so it never
//! runs in CI or hits the network by default; run it deliberately with
//!
//! ```sh
//! cargo test -p soundclouddy --test live -- --ignored --nocapture
//! # optional: SOUNDCLOUD_CLIENT_ID=<id> to skip the scrape,
//! # SOUNDCLOUD_OAUTH=<token> to also exercise the personal calls.
//! ```
//!
//! It exercises the real endpoints end-to-end (scrape client_id → search →
//! resolve stream URL) so the `ScApi` DTOs and the `client_id` scrape are
//! confirmed against the live shapes — the drift risk called out in
//! architecture/soundcloud-provider.md.
use std::time::Duration;
use soundclouddy::api::{Sc, ScApi};
fn api() -> ScApi {
ScApi::new(
std::env::var("SOUNDCLOUD_CLIENT_ID").ok(),
None,
std::env::var("SOUNDCLOUD_OAUTH").ok(),
Duration::from_secs(30),
)
.expect("client builds")
}
#[tokio::test]
#[ignore = "hits the real SoundCloud API (scrapes a client_id)"]
async fn live_scrape_search_and_stream() {
let api = api();
// Scrapes a client_id if none was provided; a failure here means the
// scrape parsers need updating against the current soundcloud.com.
api.ensure_ready().await.expect("obtain a client_id");
println!(
"client_id acquired: {}",
api.cached_client_id().await.is_some()
);
let tracks = api
.search_tracks("boards of canada", 5)
.await
.expect("search decodes");
assert!(!tracks.is_empty(), "search returns tracks");
let first = &tracks[0];
println!(
"first track: {}{} ({})",
first.artist, first.title, first.id
);
// Resolve a playable HLS media URL for it.
let url = api
.resolve_stream_url(&first.id)
.await
.expect("stream url resolves");
assert!(
url.contains(".m3u8"),
"stream URL is an HLS playlist: {url}"
);
println!("stream url resolves to an m3u8 (len {})", url.len());
}
#[tokio::test]
#[ignore = "hits the real SoundCloud API; requires SOUNDCLOUD_OAUTH"]
async fn live_personal_likes() {
if std::env::var("SOUNDCLOUD_OAUTH").is_err() {
eprintln!("SOUNDCLOUD_OAUTH unset — skipping personal test");
return;
}
let api = api();
api.ensure_ready().await.expect("client_id");
let likes = api.my_likes(5).await.expect("likes decode");
println!("liked tracks: {}", likes.len());
}