# tests/test_openapi_expander.py import json from copy import deepcopy import pytest from utils.openapi_expander import ( add_biz_restrictions, resolve_allOf, resolve_ref, resolve_refs, unwrap_refs, ) # create a sample swagger 2.0 file SAMPLE_SWAGGER = { "swagger": "2.0", "info": {"title": "Sample API", "version": "1.0.0"}, "paths": { "/user": { "get": { "responses": { "200": { "description": "Successful response", "schema": {"$ref": "#/definitions/User"}, } } } } }, "definitions": { "User": { "type": "object", "properties": { "id": {"type": "integer"}, "name": {"type": "string"}, "address": {"$ref": "#/definitions/Address"}, }, }, "Address": { "type": "object", "properties": {"street": {"type": "string"}, "city": {"type": "string"}}, }, "ExtendedUser": { "allOf": [ {"$ref": "#/definitions/User"}, {"type": "object", "properties": {"email": {"type": "string"}}}, ] }, "v1beta1ClusterStorageNodeSetting": { "type": "object", "properties": { "storageSizeGi": { "type": "integer", "format": "int32", "description": "The storage size of the node in Gi.", }, "nodeSpecKey": { "type": "string", "description": "The node spec key.", }, }, }, "v1beta1UpdateClusterRequestStorageNodeSetting": { "type": "object", "properties": { "storageSizeGi": { "type": "integer", "format": "int32", "description": "The storage size of the node in Gi.", }, "nodeSpecKey": { "type": "string", "description": "The node spec key.", }, }, }, "v1beta1ClusterTidbNodeSetting": { "type": "object", "properties": { "nodeSpecKey": { "type": "string", "description": "The node spec key.", } }, }, "v1beta1UpdateClusterRequestTidbNodeSetting": { "type": "object", "properties": { "nodeSpecKey": { "type": "string", "description": "The node spec key.", } }, }, }, } @pytest.fixture def sample_swagger_file(tmp_path): file_path = tmp_path / "sample_swagger.json" with open(file_path, "w") as f: json.dump(SAMPLE_SWAGGER, f) return str(file_path) def test_resolve_ref(): result = resolve_ref(SAMPLE_SWAGGER, "#/definitions/User") assert result == SAMPLE_SWAGGER["definitions"]["User"] def test_resolve_refs(): result = resolve_refs(SAMPLE_SWAGGER, SAMPLE_SWAGGER) assert "swagger" in result assert "info" in result assert "paths" in result assert "definitions" in result user_path = result["paths"]["/user"]["get"]["responses"]["200"]["schema"] assert "properties" in user_path assert "id" in user_path["properties"] assert "name" in user_path["properties"] assert "address" in user_path["properties"] assert "street" in user_path["properties"]["address"]["properties"] assert "city" in user_path["properties"]["address"]["properties"] assert "User" in result["definitions"] assert "Address" in result["definitions"] assert "ExtendedUser" in result["definitions"] extended_user = result["definitions"]["ExtendedUser"] assert "allOf" in extended_user assert len(extended_user["allOf"]) == 2 assert "properties" in extended_user["allOf"][0] assert "properties" in extended_user["allOf"][1] assert "email" in extended_user["allOf"][1]["properties"] def test_resolve_allOf(): extended_user = resolve_refs(SAMPLE_SWAGGER, SAMPLE_SWAGGER)["definitions"][ "ExtendedUser" ] result = resolve_allOf(extended_user) assert "allOf" not in result assert "properties" in result assert "email" in result["properties"] assert "name" in result["properties"] assert "address" in result["properties"] def test_unwrap_refs(sample_swagger_file): # result = unwrap_refs(sample_swagger_file) result = unwrap_refs(SAMPLE_SWAGGER) assert "definitions" in result assert "User" in result["definitions"] assert "address" in result["definitions"]["User"]["properties"] assert ( "street" in result["definitions"]["User"]["properties"]["address"]["properties"] ) assert "ExtendedUser" in result["definitions"] assert "email" in result["definitions"]["ExtendedUser"]["properties"] assert "name" in result["definitions"]["ExtendedUser"]["properties"] def mock_merge_node_specs(): return { "STORAGE": { "storageSizeGi": {"max": 1000, "min": 10}, "nodeSpecKey": ["storage.small", "storage.medium", "storage.large"], }, "TIDB": {"nodeSpecKey": ["tidb.small", "tidb.medium", "tidb.large"]}, } @pytest.fixture def mock_spec(): return { "definitions": { "v1beta1ClusterStorageNodeSetting": { "properties": {"storageSizeGi": {}, "nodeSpecKey": {}} }, "v1beta1UpdateClusterRequestStorageNodeSetting": { "properties": {"storageSizeGi": {}, "nodeSpecKey": {}} }, "v1beta1ClusterTidbNodeSetting": {"properties": {"nodeSpecKey": {}}}, "v1beta1UpdateClusterRequestTidbNodeSetting": { "properties": {"nodeSpecKey": {}} }, "v1beta1AdvancedModifyDedicatedClusterRequestTidbNodeSetting": { "properties": {"nodeSpecKey": {}} }, } } def test_add_biz_restrictions(mock_spec, monkeypatch): monkeypatch.setattr( "utils.openapi_expander.merge_node_specs", mock_merge_node_specs ) # 运行原始实现 spec = deepcopy(mock_spec) result = add_biz_restrictions(spec) # 可以添加更详细的断言来检查特定的变化 assert ( result["definitions"]["v1beta1ClusterStorageNodeSetting"]["properties"][ "storageSizeGi" ]["maximum"] == 1000 ) assert ( result["definitions"]["v1beta1ClusterStorageNodeSetting"]["properties"][ "storageSizeGi" ]["minimum"] == 10 ) assert result["definitions"]["v1beta1ClusterStorageNodeSetting"]["properties"][ "nodeSpecKey" ]["enum"] == ["storage.small", "storage.medium", "storage.large"] assert result["definitions"]["v1beta1ClusterTidbNodeSetting"]["properties"][ "nodeSpecKey" ]["enum"] == ["tidb.small", "tidb.medium", "tidb.large"]