use std::fs;
use tempfile::TempDir;
#[test]
fn test_gnostic_ref_rewriting() {
let dir = TempDir::new().unwrap();
let spec_path = dir.path().join("openapi.yaml");
let jsonschema_dir = dir.path().join("jsonschema");
fs::create_dir_all(&jsonschema_dir).unwrap();
let gnostic_ref = concat!("#/$defs/example.catalog.v1.Catalog.schema.strict.", "json");
let yaml = format!(
"openapi: \"3.0.0\"\ninfo:\n title: Test\n version: \"1.0\"\ncomponents:\n schemas:\n Catalog:\n type: object\n properties:\n id:\n $ref: \"{gnostic_ref}\"\n"
);
fs::write(&spec_path, yaml).unwrap();
olai_codegen::enrich_openapi(
&spec_path,
&jsonschema_dir,
false,
None,
&Default::default(),
&Default::default(),
)
.unwrap();
let result = fs::read_to_string(&spec_path).unwrap();
assert!(
result.contains("#/components/schemas/Catalog"),
"expected rewritten ref in output:\n{result}"
);
assert!(
!result.contains("#/$defs/"),
"expected no gnostic refs remaining:\n{result}"
);
}
#[test]
fn test_malformed_root_ref_is_skipped_not_silently_emptied() {
let dir = TempDir::new().unwrap();
let spec_path = dir.path().join("openapi.yaml");
let jsonschema_dir = dir.path().join("jsonschema");
fs::create_dir_all(&jsonschema_dir).unwrap();
let bundle = r#"{
"$ref": "Catalog",
"$defs": {
"Catalog": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 } } }
}
}"#;
fs::write(
jsonschema_dir.join("example.catalog.v1.Catalog.schema.strict.bundle.json"),
bundle,
)
.unwrap();
let yaml = "openapi: \"3.0.0\"\ninfo:\n title: Test\n version: \"1.0\"\ncomponents:\n schemas:\n Catalog:\n type: object\n properties:\n name:\n type: string\n";
fs::write(&spec_path, yaml).unwrap();
olai_codegen::enrich_openapi(
&spec_path,
&jsonschema_dir,
false,
None,
&Default::default(),
&Default::default(),
)
.expect("run should not error on a malformed bundle ref");
let result = fs::read_to_string(&spec_path).unwrap();
assert!(
!result.contains("minLength"),
"malformed bundle should be skipped, not partially applied:\n{result}"
);
}
#[test]
fn test_round_trip_without_jsonschema() {
let dir = TempDir::new().unwrap();
let spec_path = dir.path().join("openapi.yaml");
let jsonschema_dir = dir.path().join("jsonschema");
fs::create_dir_all(&jsonschema_dir).unwrap();
let yaml = r#"
openapi: "3.0.0"
info:
title: Round Trip Test
version: "1.0"
paths:
/catalogs:
get:
summary: List catalogs
responses:
"200":
description: OK
components:
schemas:
Catalog:
type: object
properties:
name:
type: string
"#;
fs::write(&spec_path, yaml).unwrap();
olai_codegen::enrich_openapi(
&spec_path,
&jsonschema_dir,
false,
None,
&Default::default(),
&Default::default(),
)
.unwrap();
let result = fs::read_to_string(&spec_path).unwrap();
let parsed: serde_yaml::Value =
serde_yaml::from_str(&result).expect("output should be valid YAML after round-trip");
assert!(
parsed.get("openapi").is_some(),
"output should retain 'openapi' key"
);
}
#[test]
fn test_schema_rename_rewrites_key_and_refs() {
let dir = TempDir::new().unwrap();
let spec_path = dir.path().join("openapi.yaml");
let jsonschema_dir = dir.path().join("jsonschema");
fs::create_dir_all(&jsonschema_dir).unwrap();
let yaml = concat!(
"openapi: \"3.0.0\"\n",
"info:\n title: Test\n version: \"1.0\"\n",
"components:\n",
" schemas:\n",
" Catalog:\n type: object\n properties:\n name:\n type: string\n",
" Schema:\n type: object\n",
" ListCatalogsResponse:\n type: object\n properties:\n",
" catalogs:\n type: array\n items:\n $ref: \"#/components/schemas/Catalog\"\n",
);
fs::write(&spec_path, yaml).unwrap();
let mut renames = std::collections::BTreeMap::new();
renames.insert("Catalog".to_string(), "CatalogInfo".to_string());
renames.insert("Absent".to_string(), "AbsentInfo".to_string());
olai_codegen::enrich_openapi(
&spec_path,
&jsonschema_dir,
false,
None,
&renames,
&Default::default(),
)
.unwrap();
let parsed: serde_yaml::Value = serde_yaml::from_str(&fs::read_to_string(&spec_path).unwrap())
.expect("valid YAML after rename");
let schemas = parsed
.get("components")
.and_then(|c| c.get("schemas"))
.and_then(|s| s.as_mapping())
.unwrap();
assert!(schemas.contains_key(serde_yaml::Value::String("CatalogInfo".into())));
assert!(!schemas.contains_key(serde_yaml::Value::String("Catalog".into())));
assert!(schemas.contains_key(serde_yaml::Value::String("Schema".into())));
assert!(!schemas.contains_key(serde_yaml::Value::String("AbsentInfo".into())));
let ref_str = parsed
.get("components")
.and_then(|c| c.get("schemas"))
.and_then(|s| s.get("ListCatalogsResponse"))
.and_then(|r| r.get("properties"))
.and_then(|p| p.get("catalogs"))
.and_then(|c| c.get("items"))
.and_then(|i| i.get("$ref"))
.and_then(|r| r.as_str())
.unwrap();
assert_eq!(ref_str, "#/components/schemas/CatalogInfo");
}
#[test]
fn test_schema_override_rebuilds_from_jsonschema() {
let dir = TempDir::new().unwrap();
let spec_path = dir.path().join("openapi.yaml");
let jsonschema_dir = dir.path().join("jsonschema");
fs::create_dir_all(&jsonschema_dir).unwrap();
let bundle = concat!(
r#"{"$ref":"#,
"\"#/$defs/example.schemas.v1.Schema.schema.strict.",
"json\"",
r#","$defs":{"example.schemas.v1.Schema.schema.strict."#,
"json",
r#"":{"type":"object","required":["name","full_name"],"properties":{"#,
r#""name":{"type":"string"},"full_name":{"type":"string"},"catalog_name":{"type":"string"}}}}}"#,
);
fs::write(
jsonschema_dir.join("example.schemas.v1.Schema.schema.strict.bundle.json"),
bundle,
)
.unwrap();
let yaml = concat!(
"openapi: \"3.0.0\"\n",
"info:\n title: Test\n version: \"1.0\"\n",
"components:\n schemas:\n",
" Schema:\n type: object\n properties:\n",
" nullable:\n type: boolean\n",
" discriminator:\n type: string\n",
);
fs::write(&spec_path, yaml).unwrap();
let mut overrides = std::collections::HashSet::new();
overrides.insert("Schema".to_string());
olai_codegen::enrich_openapi(
&spec_path,
&jsonschema_dir,
false,
None,
&Default::default(),
&overrides,
)
.unwrap();
let parsed: serde_yaml::Value =
serde_yaml::from_str(&fs::read_to_string(&spec_path).unwrap()).unwrap();
let props = parsed
.get("components")
.and_then(|c| c.get("schemas"))
.and_then(|s| s.get("Schema"))
.and_then(|s| s.get("properties"))
.and_then(|p| p.as_mapping())
.unwrap();
assert!(props.contains_key(serde_yaml::Value::String("full_name".into())));
assert!(props.contains_key(serde_yaml::Value::String("catalog_name".into())));
assert!(!props.contains_key(serde_yaml::Value::String("discriminator".into())));
assert!(!props.contains_key(serde_yaml::Value::String("nullable".into())));
let schema = parsed
.get("components")
.and_then(|c| c.get("schemas"))
.and_then(|s| s.get("Schema"))
.and_then(|s| s.as_mapping())
.unwrap();
assert!(!schema.contains_key(serde_yaml::Value::String("$schema".into())));
}