#![cfg(feature = "all-devices")]
use std::collections::HashMap;
fn count_methods_from_yaml() -> HashMap<String, usize> {
let yaml_str =
std::fs::read_to_string("tests/fixtures/AlpacaDeviceAPI_v1.yaml").expect("vendored YAML");
let yaml: serde_yaml::Value = serde_yaml::from_str(&yaml_str).expect("valid YAML");
let paths = yaml["paths"].as_mapping().expect("paths object");
let mut counts: HashMap<String, usize> = HashMap::new();
for (path_key, path_value) in paths {
let path = path_key.as_str().unwrap_or("");
let segments: Vec<&str> = path.trim_start_matches('/').split('/').collect();
if segments.len() < 3 {
continue;
}
let device_type = segments[0];
if device_type == "{device_type}" {
let method_count = path_value.as_mapping().map_or(0, |m| {
m.keys()
.filter(|k| {
let s = k.as_str().unwrap_or("");
s == "get" || s == "put"
})
.count()
});
*counts.entry("common".to_string()).or_insert(0) += method_count;
continue;
}
let method_count = path_value.as_mapping().map_or(0, |m| {
m.keys()
.filter(|k| {
let s = k.as_str().unwrap_or("");
s == "get" || s == "put"
})
.count()
});
*counts.entry(device_type.to_string()).or_insert(0) += method_count;
}
counts
}
#[test]
fn method_counts_match_official_spec() {
let counts = count_methods_from_yaml();
let device_types = [
"camera",
"covercalibrator",
"dome",
"filterwheel",
"focuser",
"observingconditions",
"rotator",
"safetymonitor",
"switch",
"telescope",
];
for dt in &device_types {
assert!(
counts.contains_key(*dt),
"Missing device type in YAML: {dt}"
);
}
assert!(
counts.contains_key("common"),
"Missing common methods in YAML"
);
let common_count = counts["common"];
assert!(
common_count >= 15,
"Expected at least 15 common methods, got {common_count}"
);
println!("Method counts from official ASCOM OpenAPI spec:");
println!(" Common: {common_count}");
for dt in &device_types {
let c = counts.get(*dt).unwrap_or(&0);
println!(" {dt}: {c}");
}
assert_eq!(
counts["safetymonitor"], 1,
"SafetyMonitor should have exactly 1 device-specific method (issafe GET)"
);
assert!(
counts["camera"] > 40,
"Camera should have 40+ device-specific methods, got {}",
counts["camera"]
);
assert!(
counts["telescope"] > 50,
"Telescope should have 50+ device-specific methods, got {}",
counts["telescope"]
);
}
#[test]
fn response_schema_pascal_case_fields() {
let yaml_str =
std::fs::read_to_string("tests/fixtures/AlpacaDeviceAPI_v1.yaml").expect("vendored YAML");
assert!(yaml_str.contains("ClientTransactionID"));
assert!(yaml_str.contains("ServerTransactionID"));
assert!(yaml_str.contains("ErrorNumber"));
assert!(yaml_str.contains("ErrorMessage"));
let resp = ascom_alpaca_core::types::AlpacaResponse::ok(true);
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("ClientTransactionID"));
assert!(json.contains("ServerTransactionID"));
assert!(json.contains("ErrorNumber"));
assert!(json.contains("ErrorMessage"));
}
#[test]
fn management_api_structure() {
let yaml_str = std::fs::read_to_string("tests/fixtures/AlpacaManagementAPI_v1.yaml")
.expect("vendored management YAML");
let yaml: serde_yaml::Value = serde_yaml::from_str(&yaml_str).expect("valid YAML");
let paths = yaml["paths"].as_mapping().expect("paths object");
let expected_paths = [
"/management/apiversions",
"/management/v1/description",
"/management/v1/configureddevices",
];
for expected in &expected_paths {
assert!(
paths.keys().any(|k| k.as_str() == Some(expected)),
"Missing management path: {expected}"
);
}
}