use kshana::suite::Suite;
fn two_scenario_suite() -> Suite {
let src = include_str!("fixtures/suite-min.toml");
kshana::suite::parse_suite(src).expect("fixture suite parses")
}
fn fixtures_dir() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures")
}
#[test]
fn html_names_both_scenarios_and_renders_a_comparison_table() {
let suite = two_scenario_suite();
let out = kshana::study::run_suite(&suite, &fixtures_dir()).expect("study runs");
assert!(
out.html.contains("Holdover comparison study"),
"study title missing from HTML"
);
assert!(
out.html.contains("Space optical-lattice"),
"first scenario label missing from comparison HTML"
);
assert!(
out.html.contains("clock-holdover-labsr"),
"second scenario fallback label missing from comparison HTML"
);
assert!(out.html.contains("<table"), "no comparison table in HTML");
assert!(out.html.contains("Holdover"), "FoM row label missing");
assert!(
out.summary.contains("2 scenarios"),
"summary should report the scenario count: {}",
out.summary
);
}
#[test]
fn a_validation_tier_tag_is_rendered() {
let suite = two_scenario_suite();
let out = kshana::study::run_suite(&suite, &fixtures_dir()).expect("study runs");
assert!(
out.html.contains("MODELLED") || out.html.contains("VALIDATED"),
"no VALIDATED/MODELLED validation tag in the comparison HTML"
);
assert!(
out.html.contains("MODELLED"),
"the modelled holdover tier tag must be present (honesty intact)"
);
}
#[test]
fn per_scenario_foms_match_running_the_scenario_alone() {
let suite = two_scenario_suite();
let out = kshana::study::run_suite(&suite, &fixtures_dir()).expect("study runs");
let study: serde_json::Value = serde_json::from_str(&out.json).expect("study json parses");
let scenarios = study["scenarios"]
.as_array()
.expect("study json has a scenarios array");
assert_eq!(scenarios.len(), 2);
for (i, entry) in suite.scenarios.iter().enumerate() {
let path = fixtures_dir().join(&entry.path);
let src = std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("read {}: {e}", path.display()));
let alone = kshana::api::run_toml(&src).expect("scenario runs alone");
let alone_json: serde_json::Value =
serde_json::from_str(&alone.json).expect("alone json parses");
assert_eq!(
scenarios[i]["scenario_hash"], alone_json["scenario_hash"],
"scenario_hash drift for entry {i}"
);
assert_eq!(
scenarios[i]["foms"]["quantum"], alone_json["quantum"]["fom"],
"quantum FoM drift for entry {i}"
);
assert_eq!(
scenarios[i]["foms"]["classical"], alone_json["classical"]["fom"],
"classical FoM drift for entry {i}"
);
}
}
#[test]
fn run_suite_is_pure_and_repeatable() {
let suite = two_scenario_suite();
let a = kshana::study::run_suite(&suite, &fixtures_dir()).expect("first run");
let b = kshana::study::run_suite(&suite, &fixtures_dir()).expect("second run");
assert_eq!(a.json, b.json, "study json is not deterministic");
assert_eq!(a.html, b.html, "study html is not deterministic");
}