|
9 | 9 |
|
10 | 10 | mod inheritance_tests; |
11 | 11 |
|
12 | | -use gts::{GtsConfig, GtsEntity, GtsId, GtsInstanceId, GtsSchema}; |
| 12 | +use gts::{GtsConfig, GtsEntity, GtsId, GtsInstanceId, GtsSchema, GtsTypeId}; |
13 | 13 | use gts_macros::{gts_id, struct_to_gts_schema}; |
14 | 14 | /// Event Topic (Stream) definition for testing GTS schema generation. |
15 | 15 | /// Inspired by examples/examples/events/schemas/gts.x.core.events.topic.v1~.schema.json |
@@ -55,6 +55,25 @@ pub struct ProductV1 { |
55 | 55 | pub warehouse_location: String, |
56 | 56 | } |
57 | 57 |
|
| 58 | +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)] |
| 59 | +pub struct NestedGtsIds { |
| 60 | + pub type_id: GtsTypeId, |
| 61 | + pub instance_id: GtsInstanceId, |
| 62 | +} |
| 63 | + |
| 64 | +#[derive(Debug, Clone)] |
| 65 | +#[struct_to_gts_schema( |
| 66 | + dir_path = "schemas", |
| 67 | + base = true, |
| 68 | + type_id = gts_id!("x.test.entities.nested_ids.v1~"), |
| 69 | + description = "Entity whose retained definition contains GTS ID references", |
| 70 | + properties = "id,nested" |
| 71 | +)] |
| 72 | +pub struct NestedGtsIdsV1 { |
| 73 | + pub id: GtsInstanceId, |
| 74 | + pub nested: NestedGtsIds, |
| 75 | +} |
| 76 | + |
58 | 77 | // ============================================================================= |
59 | 78 | // Tests for 3.a) GTS_SCHEMA_JSON - JSON Schema with proper $id |
60 | 79 | // ============================================================================= |
@@ -140,6 +159,45 @@ fn test_schema_json_is_valid_json() { |
140 | 159 | assert_eq!(product_schema["type"], "object"); |
141 | 160 | } |
142 | 161 |
|
| 162 | +#[test] |
| 163 | +fn test_gts_id_refs_are_inlined_inside_retained_definitions() { |
| 164 | + fn contains_gts_id_ref(value: &serde_json::Value) -> bool { |
| 165 | + match value { |
| 166 | + serde_json::Value::Object(object) => { |
| 167 | + let is_gts_id_ref = object |
| 168 | + .get("$ref") |
| 169 | + .and_then(serde_json::Value::as_str) |
| 170 | + .is_some_and(|reference| { |
| 171 | + reference.ends_with("/GtsInstanceId") |
| 172 | + || reference.ends_with("/GtsTypeId") |
| 173 | + || reference.ends_with("/GtsSchemaId") |
| 174 | + }); |
| 175 | + is_gts_id_ref || object.values().any(contains_gts_id_ref) |
| 176 | + } |
| 177 | + serde_json::Value::Array(values) => values.iter().any(contains_gts_id_ref), |
| 178 | + _ => false, |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + let schema = NestedGtsIdsV1::gts_schema_with_refs(); |
| 183 | + assert!( |
| 184 | + schema["definitions"]["NestedGtsIds"].is_object(), |
| 185 | + "the nested definition must remain reachable" |
| 186 | + ); |
| 187 | + assert!( |
| 188 | + !contains_gts_id_ref(&schema), |
| 189 | + "generated schema contains a dangling GTS-ID definition reference: {schema}" |
| 190 | + ); |
| 191 | + |
| 192 | + let mut store = gts::GtsStore::new(); |
| 193 | + store |
| 194 | + .register_schema(NestedGtsIdsV1::TYPE_ID, &schema) |
| 195 | + .expect("generated schema should register"); |
| 196 | + store |
| 197 | + .validate_schema(NestedGtsIdsV1::TYPE_ID) |
| 198 | + .expect("generated schema should have no unresolved local references"); |
| 199 | +} |
| 200 | + |
143 | 201 | #[test] |
144 | 202 | fn test_schema_json_required_fields() { |
145 | 203 | let topic_schema: serde_json::Value = |
|
0 commit comments