#![cfg(feature = "ddstats")]
mod util;
use ddapi_rs::prelude::ddstats::*;
use ddapi_rs::prelude::DDApi;
use serde_json::Value;
use util::{assert_schema_matches, load_fixture};
#[test]
fn profile_schema_matches() {
assert_schema_matches::<Profile>(&load_fixture("ddstats/profile.json"));
}
#[test]
fn map_schema_matches() {
assert_schema_matches::<Map>(&load_fixture("ddstats/map.json"));
}
const TEST_PLAYERS: &[&str] = &["Cor", "ByFox"];
async fn fetch_and_check<T>(url: &str)
where
T: serde::de::DeserializeOwned + serde::Serialize,
{
fetch_and_check_result::<T>(url)
.await
.unwrap_or_else(|e| panic!("{e}"));
}
async fn fetch_and_check_result<T>(url: &str) -> Result<(), String>
where
T: serde::de::DeserializeOwned + serde::Serialize,
{
let api = DDApi::new();
let mut value: Value = Value::Null;
for attempt in 1..=3 {
match api.generator(url).await {
Ok(v) => {
value = v;
break;
}
Err(e) if attempt < 3 => {
eprintln!("GET {url} failed (attempt {attempt}/3): {e}; retrying");
}
Err(e) => return Err(format!("GET {url} failed: {e}")),
}
}
util::check_no_extra_data::<T>(&value)
}
async fn check_any_player<T, F>(make_url: F)
where
T: serde::de::DeserializeOwned + serde::Serialize,
F: Fn(&str) -> String,
{
let mut failures = Vec::new();
for player in TEST_PLAYERS {
let url = make_url(player);
match fetch_and_check_result::<T>(&url).await {
Ok(()) => return,
Err(e) => failures.push(format!("{url}:\n{e}")),
}
}
assert!(
failures.is_empty(),
"no test player validated against `{}`:\n{}",
std::any::type_name::<T>(),
failures.join("\n\n")
);
}
#[tokio::test]
#[ignore = "requires network; run with `cargo test -- --ignored`"]
async fn player_schema_matches_live() {
check_any_player::<Player, _>(Player::api).await;
}
#[tokio::test]
#[ignore = "requires network; run with `cargo test -- --ignored`"]
async fn maps_schema_matches_live() {
fetch_and_check::<Vec<StatsMap>>(&StatsMap::api()).await;
}
#[tokio::test]
#[ignore = "requires network; run with `cargo test -- --ignored`"]
async fn teero_schema_matches_live() {
check_any_player::<Teero, _>(Teero::api).await;
}
#[tokio::test]
#[ignore = "requires network; run with `cargo test -- --ignored`"]
async fn profile_schema_matches_live() {
check_any_player::<Profile, _>(Profile::api).await;
}
#[tokio::test]
#[ignore = "requires network; run with `cargo test -- --ignored`"]
async fn map_schema_matches_live() {
fetch_and_check::<Map>(&Map::api("Fox")).await;
}