From a5445bdb6ed52dae0f3377e57d45e2c7ce1082af Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Fri, 30 Jan 2026 03:41:48 +0000 Subject: [PATCH] Initial commit: Add OpenAPI Mock Server project --- .tests/test_spec_parser.py | 174 +++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 .tests/test_spec_parser.py diff --git a/.tests/test_spec_parser.py b/.tests/test_spec_parser.py new file mode 100644 index 0000000..e285553 --- /dev/null +++ b/.tests/test_spec_parser.py @@ -0,0 +1,174 @@ +"""Tests for the OpenAPI spec parser module.""" + +import tempfile +import yaml +import pytest + +from openapi_mock.core.spec_parser import ( + load_spec, + extract_paths, + extract_schemas, + extract_path_params, + get_operation_id, + extract_security_schemes, + get_response_schema, + get_spec_version, + is_openapi_3, + SpecNotFoundError, + SpecValidationError, +) + + +class TestLoadSpec: + """Tests for load_spec function.""" + + def test_load_valid_spec(self, temp_spec_file, sample_openapi_spec): + """Test loading a valid OpenAPI specification.""" + spec = load_spec(temp_spec_file) + assert spec["info"]["title"] == "Test API" + assert spec["info"]["version"] == "1.0.0" + assert spec["openapi"] == "3.0.0" + + def test_load_nonexistent_file(self): + """Test loading a non-existent file raises error.""" + with pytest.raises(SpecNotFoundError): + load_spec("/nonexistent/path/spec.yaml") + + def test_load_invalid_yaml(self, invalid_yaml_file): + """Test loading invalid YAML raises error.""" + with pytest.raises(Exception): # Could be various YAML errors + load_spec(invalid_yaml_file) + + def test_load_swagger_2_spec(self, tmp_path): + """Test loading a Swagger 2.0 specification.""" + swagger_spec = { + "swagger": "2.0", + "info": {"title": "Test", "version": "1.0"}, + "paths": {} + } + spec_path = tmp_path / "swagger.yaml" + with open(spec_path, "w") as f: + yaml.dump(swagger_spec, f) + + spec = load_spec(str(spec_path)) + assert spec["swagger"] == "2.0" + + +class TestExtractPaths: + """Tests for extract_paths function.""" + + def test_extract_paths(self, sample_openapi_spec): + """Test extracting paths from spec.""" + paths = extract_paths(sample_openapi_spec) + assert "/users" in paths + assert "/users/{userId}" in paths + + def test_extract_paths_empty(self): + """Test extracting paths from spec with no paths.""" + spec = {"openapi": "3.0.0", "info": {"title": "Test", "version": "1.0"}, "paths": {}} + paths = extract_paths(spec) + assert paths == {} + + def test_extract_paths_missing(self): + """Test extracting paths when paths key is missing.""" + spec = {"openapi": "3.0.0", "info": {"title": "Test", "version": "1.0"}} + paths = extract_paths(spec) + assert paths == {} + + +class TestExtractSchemas: + """Tests for extract_schemas function.""" + + def test_extract_schemas(self, sample_openapi_spec): + """Test extracting schemas from spec.""" + schemas = extract_schemas(sample_openapi_spec) + assert "User" in schemas + assert schemas["User"]["type"] == "object" + + def test_extract_schemas_swagger(self, swagger_2_spec): + """Test extracting schemas from Swagger 2.0 spec.""" + schemas = extract_schemas(swagger_2_spec) + assert "Pet" in schemas + + def test_extract_schemas_missing(self): + """Test extracting schemas when components are missing.""" + spec = {"openapi": "3.0.0", "info": {"title": "Test", "version": "1.0"}, "paths": {}} + schemas = extract_schemas(spec) + assert schemas == {} + + +class TestExtractPathParams: + """Tests for extract_path_params function.""" + + def test_extract_single_param(self): + """Test extracting a single path parameter.""" + params = extract_path_params("/users/{id}") + assert params == ["id"] + + def test_extract_multiple_params(self): + """Test extracting multiple path parameters.""" + params = extract_path_params("/users/{userId}/posts/{postId}") + assert params == ["userId", "postId"] + + def test_extract_no_params(self): + """Test extracting parameters from path with none.""" + params = extract_path_params("/users") + assert params == [] + + def test_extract_nested_brace_in_pattern(self): + """Test extracting parameters handles edge cases.""" + params = extract_path_params("/api/{version}/users/{id}") + assert params == ["version", "id"] + + +class TestGetOperationId: + """Tests for get_operation_id function.""" + + def test_get_operation_id_simple(self): + """Test generating operation ID for simple path.""" + op_id = get_operation_id("/users", "get") + assert op_id == "get_users" + + def test_get_operation_id_with_params(self): + """Test generating operation ID for path with parameters.""" + op_id = get_operation_id("/users/{id}", "get") + assert op_id == "get_users__id_" + + def test_get_operation_id_nested(self): + """Test generating operation ID for nested path.""" + op_id = get_operation_id("/api/v1/users", "post") + assert op_id == "post_api_v1_users" + + +class TestGetResponseSchema: + """Tests for get_response_schema function.""" + + def test_get_response_schema(self, sample_openapi_spec): + """Test getting response schema for an operation.""" + schema = get_response_schema(sample_openapi_spec, "/users", "get") + assert schema is not None + assert schema["type"] == "array" + assert schema["items"]["$ref"] == "#/components/schemas/User" + + def test_get_response_schema_missing(self): + """Test getting response schema for non-existent operation.""" + spec = {"openapi": "3.0.0", "info": {"title": "Test", "version": "1.0"}, "paths": {}} + schema = get_response_schema(spec, "/nonexistent", "get") + assert schema is None + + +class TestSpecVersion: + """Tests for version detection functions.""" + + def test_get_spec_version(self, sample_openapi_spec): + """Test getting OpenAPI version.""" + version = get_spec_version(sample_openapi_spec) + assert version == "3.0.0" + + def test_is_openapi_3_true(self, sample_openapi_spec): + """Test OpenAPI 3.x detection.""" + assert is_openapi_3(sample_openapi_spec) is True + + def test_is_openapi_3_false(self, swagger_2_spec): + """Test Swagger 2.0 detection.""" + assert is_openapi_3(swagger_2_spec) is False