|
4 | 4 |
|
5 | 5 | from apcore_toolkit.openapi import ( |
6 | 6 | _deep_resolve_refs, |
| 7 | + deep_resolve_refs, |
7 | 8 | extract_input_schema, |
8 | 9 | extract_output_schema, |
9 | 10 | resolve_ref, |
@@ -168,6 +169,101 @@ def test_no_mutation_of_original(self) -> None: |
168 | 169 | assert OPENAPI_DOC["components"]["schemas"]["Address"]["properties"] == original_props |
169 | 170 |
|
170 | 171 |
|
| 172 | +class TestDeepResolveRefsPublic: |
| 173 | + """Tests for the public deep_resolve_refs wrapper.""" |
| 174 | + |
| 175 | + def test_top_level_ref(self) -> None: |
| 176 | + schema = {"$ref": "#/components/schemas/User"} |
| 177 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 178 | + assert result["type"] == "object" |
| 179 | + assert "id" in result["properties"] |
| 180 | + assert "name" in result["properties"] |
| 181 | + |
| 182 | + def test_nested_ref_in_properties(self) -> None: |
| 183 | + schema = { |
| 184 | + "type": "object", |
| 185 | + "properties": { |
| 186 | + "address": {"$ref": "#/components/schemas/Address"}, |
| 187 | + }, |
| 188 | + } |
| 189 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 190 | + assert result["properties"]["address"]["type"] == "object" |
| 191 | + assert "street" in result["properties"]["address"]["properties"] |
| 192 | + |
| 193 | + def test_ref_in_allof(self) -> None: |
| 194 | + schema = { |
| 195 | + "allOf": [ |
| 196 | + {"$ref": "#/components/schemas/User"}, |
| 197 | + {"type": "object", "properties": {"extra": {"type": "boolean"}}}, |
| 198 | + ] |
| 199 | + } |
| 200 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 201 | + assert result["allOf"][0]["type"] == "object" |
| 202 | + assert "id" in result["allOf"][0]["properties"] |
| 203 | + |
| 204 | + def test_ref_in_anyof(self) -> None: |
| 205 | + schema = { |
| 206 | + "anyOf": [ |
| 207 | + {"$ref": "#/components/schemas/User"}, |
| 208 | + {"$ref": "#/components/schemas/Address"}, |
| 209 | + ] |
| 210 | + } |
| 211 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 212 | + assert "name" in result["anyOf"][0]["properties"] |
| 213 | + assert "street" in result["anyOf"][1]["properties"] |
| 214 | + |
| 215 | + def test_ref_in_oneof(self) -> None: |
| 216 | + schema = { |
| 217 | + "oneOf": [ |
| 218 | + {"$ref": "#/components/schemas/User"}, |
| 219 | + {"$ref": "#/components/schemas/Address"}, |
| 220 | + ] |
| 221 | + } |
| 222 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 223 | + assert result["oneOf"][0]["type"] == "object" |
| 224 | + assert "name" in result["oneOf"][0]["properties"] |
| 225 | + assert "city" in result["oneOf"][1]["properties"] |
| 226 | + |
| 227 | + def test_ref_in_array_items(self) -> None: |
| 228 | + schema = {"type": "array", "items": {"$ref": "#/components/schemas/User"}} |
| 229 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 230 | + assert result["items"]["type"] == "object" |
| 231 | + assert "id" in result["items"]["properties"] |
| 232 | + |
| 233 | + def test_deeply_nested_ref(self) -> None: |
| 234 | + result = deep_resolve_refs({"$ref": "#/components/schemas/UserWithAddress"}, OPENAPI_DOC) |
| 235 | + assert result["properties"]["address"]["type"] == "object" |
| 236 | + assert "street" in result["properties"]["address"]["properties"] |
| 237 | + |
| 238 | + def test_circular_ref_depth_limit(self) -> None: |
| 239 | + result = deep_resolve_refs({"$ref": "#/components/schemas/SelfRef"}, OPENAPI_DOC) |
| 240 | + assert result["type"] == "object" |
| 241 | + assert "child" in result["properties"] |
| 242 | + |
| 243 | + def test_no_mutation_of_original(self) -> None: |
| 244 | + original_address = OPENAPI_DOC["components"]["schemas"]["Address"] |
| 245 | + original_props = dict(original_address.get("properties", {})) |
| 246 | + deep_resolve_refs({"$ref": "#/components/schemas/UserWithAddress"}, OPENAPI_DOC) |
| 247 | + assert OPENAPI_DOC["components"]["schemas"]["Address"]["properties"] == original_props |
| 248 | + |
| 249 | + def test_custom_depth_parameter(self) -> None: |
| 250 | + """Passing depth=17 should short-circuit immediately.""" |
| 251 | + schema = {"$ref": "#/components/schemas/User"} |
| 252 | + result = deep_resolve_refs(schema, OPENAPI_DOC, depth=17) |
| 253 | + # Should return the unresolved schema since depth > 16 |
| 254 | + assert "$ref" in result |
| 255 | + |
| 256 | + def test_plain_schema_no_refs(self) -> None: |
| 257 | + schema = {"type": "string", "description": "A simple string"} |
| 258 | + result = deep_resolve_refs(schema, OPENAPI_DOC) |
| 259 | + assert result == {"type": "string", "description": "A simple string"} |
| 260 | + |
| 261 | + def test_importable_from_package(self) -> None: |
| 262 | + from apcore_toolkit import deep_resolve_refs as public_fn |
| 263 | + |
| 264 | + assert callable(public_fn) |
| 265 | + |
| 266 | + |
171 | 267 | class TestExtractInputSchema: |
172 | 268 | def test_query_and_path_params(self) -> None: |
173 | 269 | operation = { |
|
0 commit comments