use cargo_fresh::package::sparse_index::fetch_latest;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
fn client() -> reqwest::Client {
reqwest::Client::builder()
.user_agent("cargo-fresh-test")
.timeout(std::time::Duration::from_secs(5))
.build()
.unwrap()
}
#[tokio::test]
async fn success_returns_parsed_versions() {
let server = MockServer::start().await;
let body = r#"{"name":"ripgrep","vers":"13.0.0","yanked":false}
{"name":"ripgrep","vers":"14.1.1","yanked":false}
"#;
Mock::given(method("GET"))
.and(path("/ri/pg/ripgrep"))
.respond_with(ResponseTemplate::new(200).set_body_string(body))
.expect(1)
.mount(&server)
.await;
let v = fetch_latest(&client(), &server.uri(), "ripgrep").await.unwrap();
assert_eq!(v.stable.as_deref(), Some("14.1.1"));
}
#[tokio::test]
async fn not_found_is_not_retried() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/ca/rg/cargo-nonexistent"))
.respond_with(ResponseTemplate::new(404))
.expect(1) .mount(&server)
.await;
let err = fetch_latest(&client(), &server.uri(), "cargo-nonexistent")
.await
.unwrap_err();
assert!(err.to_string().contains("404"), "err = {err}");
}
#[tokio::test]
async fn server_error_is_retried_once_then_fails() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/ri/pg/ripgrep"))
.respond_with(ResponseTemplate::new(503))
.expect(2) .mount(&server)
.await;
let err = fetch_latest(&client(), &server.uri(), "ripgrep").await.unwrap_err();
assert!(err.to_string().contains("503"), "err = {err}");
}
#[tokio::test]
async fn server_error_then_success_recovers() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/ri/pg/ripgrep"))
.respond_with(ResponseTemplate::new(503))
.up_to_n_times(1)
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/ri/pg/ripgrep"))
.respond_with(
ResponseTemplate::new(200)
.set_body_string(r#"{"name":"ripgrep","vers":"14.0.0","yanked":false}"#),
)
.mount(&server)
.await;
let v = fetch_latest(&client(), &server.uri(), "ripgrep").await.unwrap();
assert_eq!(v.stable.as_deref(), Some("14.0.0"));
}
#[tokio::test]
async fn empty_body_returns_empty_versions() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/ca/rg/cargo-fresh"))
.respond_with(ResponseTemplate::new(200).set_body_string(""))
.expect(1)
.mount(&server)
.await;
let v = fetch_latest(&client(), &server.uri(), "cargo-fresh").await.unwrap();
assert!(v.stable.is_none() && v.prerelease.is_none());
}