#![allow(clippy::unwrap_used, clippy::expect_used)]
use std::io::Write as _;
use super::*;
const CATEGORIES: &[&str] = &[
"performance",
"security",
"federation",
"complexity",
"caching",
"indexing",
];
fn analyse(name: &str, json: &str) -> serde_json::Value {
let path = std::env::temp_dir().join(format!("fraiseql-analyze-{name}.json"));
let mut f = std::fs::File::create(&path).unwrap();
f.write_all(json.as_bytes()).unwrap();
drop(f);
let result = run(path.to_str().unwrap()).expect("analyze a valid compiled schema");
let value = serde_json::to_value(&result).unwrap();
std::fs::remove_file(&path).ok();
value["data"].clone()
}
fn compiled_schema(controls_enabled: Option<bool>) -> String {
use fraiseql_core::schema::{SecurityConfig, TypeDefinition};
let mut schema = CompiledSchema {
types: vec![TypeDefinition::new("User", "v_user")],
..CompiledSchema::default()
};
if let Some(enabled) = controls_enabled {
let security = SecurityConfig {
rate_limiting: Some(fraiseql_core::schema::RateLimitingSecurityConfig {
enabled,
..Default::default()
}),
enterprise: Some(fraiseql_core::schema::EnterpriseSecurityConfig {
audit_logging_enabled: enabled,
..Default::default()
}),
error_sanitization: Some(fraiseql_core::schema::ErrorSanitizationConfig {
enabled,
..Default::default()
}),
..SecurityConfig::default()
};
schema.security = Some(security);
}
serde_json::to_string(&schema).unwrap()
}
#[test]
fn two_schemas_with_different_security_postures_report_differently() {
let secure = analyse("secure", &compiled_schema(Some(true)));
let insecure = analyse("insecure", &compiled_schema(Some(false)));
assert_ne!(
secure["recommendations"], insecure["recommendations"],
"a schema with security controls off must not report the same as one with them on"
);
assert!(
secure["summary"]["health_score"].as_u64() > insecure["summary"]["health_score"].as_u64(),
"the health score must fall when controls are disabled; it used to be pinned at 100 \
for every possible input"
);
}
#[test]
fn a_schema_with_controls_disabled_never_claims_they_are_active() {
let data = analyse("claims", &compiled_schema(Some(false)));
let text = serde_json::to_string(&data["recommendations"]).unwrap();
for claim in [
"Rate limiting configured and active",
"Audit logging enabled for compliance",
] {
assert!(
!text.contains(claim),
"the report asserts {claim:?} about a schema that disables it"
);
}
assert!(text.contains("disabled"), "the report must say the controls are off: {text}");
}
#[test]
fn every_disabled_control_is_a_warning() {
let data = analyse("warnings", &compiled_schema(Some(false)));
assert!(
data["summary"]["warnings"].as_u64().unwrap() >= 3,
"three disabled controls must produce at least three warnings"
);
}
#[test]
fn an_enabled_schema_scores_higher_than_one_that_configures_nothing() {
let bare = analyse("bare", &compiled_schema(None));
let secure = analyse("secure2", &compiled_schema(Some(true)));
assert!(secure["summary"]["health_score"].as_u64() > bare["summary"]["health_score"].as_u64());
}
#[test]
fn the_report_matches_the_published_output_contract() {
let data = analyse("contract", &compiled_schema(Some(true)));
let recs = data["recommendations"].as_array().expect("recommendations array");
assert!(!recs.is_empty());
for rec in recs {
for key in ["category", "severity", "message", "suggestion"] {
assert!(rec.get(key).is_some(), "recommendation missing {key}: {rec}");
}
let category = rec["category"].as_str().unwrap();
assert!(CATEGORIES.contains(&category), "{category:?} is outside the published enum");
}
}
#[test]
fn an_empty_schema_does_not_score_full_marks() {
let data = analyse("empty", "{}");
assert!(
data["summary"]["health_score"].as_u64().unwrap() < 100,
"a schema declaring nothing at all cannot be in perfect health"
);
assert!(data["summary"]["warnings"].as_u64().unwrap() > 0);
}
#[test]
fn malformed_json_is_refused() {
let path = std::env::temp_dir().join("fraiseql-analyze-malformed.json");
std::fs::write(&path, b"{not json").unwrap();
let result = run(path.to_str().unwrap());
std::fs::remove_file(&path).ok();
assert!(result.is_err());
}
#[test]
#[ignore = "writes tests/fixtures/analyze_compiled_schema.json; run explicitly"]
fn emit_integration_fixture() {
let json = compiled_schema(Some(true));
let pretty: serde_json::Value = serde_json::from_str(&json).unwrap();
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/analyze_compiled_schema.json");
std::fs::write(path, serde_json::to_string_pretty(&pretty).unwrap() + "\n").unwrap();
}