use pushkin_core::manifest::{Manifest, ManifestError};
const MINIMAL: &str = r#"
version = 1
canonical = "json-schema-2020-12"
authoring = "zod"
[[contracts]]
name = "user"
source = "contracts/user.zod.ts"
emit = ["zod", "pydantic", "rust", "sql"]
[[mappings]]
glob = "app/api/**/*.ts"
contracts = ["user"]
require = "boundary-validation"
[gates]
suppression_comments = "deny"
protected_paths = ["pushkin.toml", ".claude/settings.json", "schemas/**"]
"#;
#[test]
fn parses_minimal_manifest() {
let manifest = Manifest::parse(MINIMAL).unwrap();
assert_eq!(manifest.version, 1);
assert_eq!(manifest.contracts.len(), 1);
assert_eq!(manifest.contracts[0].name.as_str(), "user");
assert_eq!(manifest.mappings.len(), 1);
assert_eq!(manifest.gates.protected_paths.len(), 3);
}
#[test]
fn rejects_unknown_key_with_candidates() {
let bad = MINIMAL.replace("suppression_comments", "supression_comments");
let err = Manifest::parse(&bad).unwrap_err();
let message = err.to_string();
assert!(
message.contains("supression_comments") || message.contains("unknown field"),
"error must name the unknown key: {message}"
);
assert!(
message.contains("suppression_comments"),
"error must suggest the valid key (candidates, spec conduct 4.4): {message}"
);
}
#[test]
fn rejects_unsupported_version() {
let bad = MINIMAL.replace("version = 1", "version = 99");
let err = Manifest::parse(&bad).unwrap_err();
assert!(matches!(
err,
ManifestError::UnsupportedVersion { found: 99, .. }
));
}
#[test]
fn mapping_glob_resolves_to_contract() {
let manifest = Manifest::parse(MINIMAL).unwrap();
let hit = manifest.mapping_for("app/api/users/route.ts");
assert!(hit.is_some());
let mapping = hit.unwrap();
assert_eq!(mapping.contracts[0].as_str(), "user");
assert!(manifest.mapping_for("docs/notes.md").is_none());
}
#[test]
fn protected_paths_parsed() {
let manifest = Manifest::parse(MINIMAL).unwrap();
assert!(manifest.is_protected("pushkin.toml"));
assert!(manifest.is_protected(".claude/settings.json"));
assert!(manifest.is_protected("schemas/user.schema.json"));
assert!(!manifest.is_protected("src/lib.rs"));
}
#[test]
fn rejects_mapping_to_undeclared_contract() {
let bad = MINIMAL.replace(r#"contracts = ["user"]"#, r#"contracts = ["usr"]"#);
let err = Manifest::parse(&bad).unwrap_err();
let message = err.to_string();
assert!(
message.contains("usr") && message.contains("user"),
"ambiguity/miss errors carry candidates (spec 7.1): {message}"
);
}