use std::collections::HashMap;
use serde::Deserialize;
use crate::error::FetcherError;
#[allow(dead_code, reason = "consumed by resolver in Task 18")]
#[derive(Debug, Deserialize)]
pub(crate) struct KnownGoodVersionsResponse {
pub versions: Vec<VersionEntry>,
}
#[allow(dead_code, reason = "consumed by resolver in Task 18")]
#[derive(Debug, Deserialize)]
pub(crate) struct VersionEntry {
pub version: String,
pub revision: String,
pub downloads: Downloads,
}
#[allow(dead_code, reason = "consumed by resolver in Task 18")]
#[derive(Debug, Deserialize)]
pub(crate) struct Downloads {
pub chrome: Vec<Download>,
}
#[allow(dead_code, reason = "consumed by resolver in Task 18")]
#[derive(Debug, Deserialize)]
pub(crate) struct Download {
pub platform: String,
pub url: String,
}
#[expect(dead_code, reason = "consumed by resolver in Task 18")]
pub(crate) async fn fetch_manifest() -> Result<KnownGoodVersionsResponse, FetcherError> {
fetch_manifest_from(
"https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json",
)
.await
}
pub(crate) async fn fetch_manifest_from(
url: &str,
) -> Result<KnownGoodVersionsResponse, FetcherError> {
let resp = reqwest::get(url).await?;
let text = resp.text().await?;
let parsed: KnownGoodVersionsResponse = serde_json::from_str(&text)?;
Ok(parsed)
}
#[derive(Debug, Deserialize)]
pub(crate) struct ChannelsResponse {
pub channels: HashMap<String, ChannelEntry>,
}
#[allow(
dead_code,
reason = "revision not consumed by the resolver yet, same as VersionEntry"
)]
#[derive(Debug, Deserialize)]
pub(crate) struct ChannelEntry {
pub version: String,
pub revision: String,
pub downloads: Downloads,
}
pub(crate) async fn fetch_channels_manifest_from(
url: &str,
) -> Result<ChannelsResponse, FetcherError> {
let resp = reqwest::get(url).await?;
let text = resp.text().await?;
let parsed: ChannelsResponse = serde_json::from_str(&text)?;
Ok(parsed)
}
#[cfg(test)]
#[allow(clippy::panic, clippy::unwrap_used)]
mod tests {
use super::*;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
const FIXTURE_JSON: &str = r#"{"versions":[{"version":"120.0.6099.234","revision":"1234","downloads":{"chrome":[{"platform":"linux64","url":"https://example.com/chrome-linux64.zip"},{"platform":"mac-x64","url":"https://example.com/chrome-mac-x64.zip"}]}}]}"#;
#[tokio::test]
async fn parses_known_good_versions_from_stub_server() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/known-good-versions.json"))
.respond_with(ResponseTemplate::new(200).set_body_string(FIXTURE_JSON))
.mount(&server)
.await;
let url = format!("{}/known-good-versions.json", server.uri());
let manifest = fetch_manifest_from(&url).await.unwrap();
assert_eq!(manifest.versions.len(), 1);
let v = &manifest.versions[0];
assert_eq!(v.version, "120.0.6099.234");
assert_eq!(v.revision, "1234");
assert_eq!(v.downloads.chrome.len(), 2);
assert_eq!(v.downloads.chrome[0].platform, "linux64");
assert_eq!(
v.downloads.chrome[0].url,
"https://example.com/chrome-linux64.zip"
);
assert_eq!(v.downloads.chrome[1].platform, "mac-x64");
assert_eq!(
v.downloads.chrome[1].url,
"https://example.com/chrome-mac-x64.zip"
);
}
}