226 lines
7.2 KiB
Python
226 lines
7.2 KiB
Python
|
|
import pytest
|
|
|
|
from src.core.models import Schema
|
|
from src.core.parser import OpenAPIParser
|
|
|
|
VALID_OPENAPI_SPEC = {
|
|
"openapi": "3.0.3",
|
|
"info": {
|
|
"title": "Test API",
|
|
"version": "1.0.0",
|
|
"description": "A test API"
|
|
},
|
|
"servers": [
|
|
{"url": "https://api.example.com/v1", "description": "Production"}
|
|
],
|
|
"paths": {
|
|
"/users": {
|
|
"get": {
|
|
"summary": "List users",
|
|
"description": "Get a list of all users",
|
|
"tags": ["Users"],
|
|
"parameters": [
|
|
{
|
|
"name": "limit", "in": "query", "schema": {"type": "integer"},
|
|
"required": False
|
|
},
|
|
{
|
|
"name": "offset", "in": "query", "schema": {"type": "integer"},
|
|
"required": False
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {"description": "Success"},
|
|
"400": {"description": "Bad Request"}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Create user",
|
|
"description": "Create a new user",
|
|
"tags": ["Users"],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
"email": {"type": "string", "format": "email"}
|
|
},
|
|
"required": ["name", "email"]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"201": {"description": "Created"}
|
|
}
|
|
}
|
|
},
|
|
"/users/{id}": {
|
|
"get": {
|
|
"summary": "Get user",
|
|
"description": "Get a user by ID",
|
|
"tags": ["Users"],
|
|
"parameters": [
|
|
{"name": "id", "in": "path", "required": True, "schema": {"type": "string"}}
|
|
],
|
|
"responses": {
|
|
"200": {"description": "Success"},
|
|
"404": {"description": "Not Found"}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"schemas": {
|
|
"User": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {"type": "string"},
|
|
"name": {"type": "string"},
|
|
"email": {"type": "string", "format": "email"}
|
|
},
|
|
"required": ["id", "name", "email"]
|
|
},
|
|
"Error": {
|
|
"type": "object",
|
|
"properties": {
|
|
"code": {"type": "integer"},
|
|
"message": {"type": "string"}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class TestOpenAPIParser:
|
|
def test_parse_valid_spec(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
assert spec.info.title == "Test API"
|
|
assert spec.info.version == "1.0.0"
|
|
assert spec.openapi == "3.0.3"
|
|
|
|
def test_parse_paths(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
assert "/users" in spec.paths
|
|
assert "/users/{id}" in spec.paths
|
|
|
|
def test_parse_operations(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
users_path = spec.paths["/users"]
|
|
assert users_path.get is not None
|
|
assert users_path.post is not None
|
|
assert users_path.get.summary == "List users"
|
|
|
|
def test_parse_parameters(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
users_path = spec.paths["/users"]
|
|
get_op = users_path.get
|
|
assert get_op is not None
|
|
params = get_op.parameters or []
|
|
assert len(params) == 2
|
|
param_names = [p.name for p in params]
|
|
assert "limit" in param_names
|
|
assert "offset" in param_names
|
|
|
|
def test_parse_request_body(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
users_path = spec.paths["/users"]
|
|
post_op = users_path.post
|
|
assert post_op is not None
|
|
assert post_op.request_body is not None
|
|
|
|
def test_parse_responses(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
users_path = spec.paths["/users"]
|
|
get_op = users_path.get
|
|
assert get_op is not None
|
|
assert "200" in get_op.responses
|
|
assert "400" in get_op.responses
|
|
|
|
def test_parse_components(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
assert spec.components is not None
|
|
assert "User" in (spec.components.schemas or {})
|
|
assert "Error" in (spec.components.schemas or {})
|
|
|
|
def test_parse_servers(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
assert spec.servers is not None
|
|
assert len(spec.servers) == 1
|
|
assert spec.servers[0].url == "https://api.example.com/v1"
|
|
|
|
def test_parse_tags(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
spec = parser.parse()
|
|
users_path = spec.paths["/users"]
|
|
get_op = users_path.get
|
|
assert get_op is not None
|
|
assert "Users" in (get_op.tags or [])
|
|
|
|
def test_validation_valid_spec(self):
|
|
parser = OpenAPIParser(VALID_OPENAPI_SPEC)
|
|
errors = parser.validate()
|
|
assert len(errors) == 0
|
|
|
|
def test_validation_invalid_spec(self):
|
|
invalid_spec = {"openapi": "3.0.0", "info": {}}
|
|
parser = OpenAPIParser(invalid_spec)
|
|
errors = parser.validate()
|
|
assert len(errors) > 0
|
|
|
|
|
|
class TestSchemaParsing:
|
|
def test_parse_string_schema(self):
|
|
schema_data = {"type": "string", "format": "email", "description": "User email"}
|
|
schema = Schema(**schema_data)
|
|
assert schema.type == "string"
|
|
assert schema.format == "email"
|
|
|
|
def test_parse_object_schema(self):
|
|
schema_data = {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
"age": {"type": "integer"}
|
|
},
|
|
"required": ["name"]
|
|
}
|
|
schema = Schema(**schema_data)
|
|
assert schema.type == "object"
|
|
assert schema.properties is not None
|
|
assert "name" in schema.properties
|
|
|
|
def test_parse_array_schema(self):
|
|
schema_data = {
|
|
"type": "array",
|
|
"items": {"type": "string"}
|
|
}
|
|
schema = Schema(**schema_data)
|
|
assert schema.type == "array"
|
|
assert schema.items is not None
|
|
|
|
def test_parse_enum_schema(self):
|
|
schema_data = {
|
|
"type": "string",
|
|
"enum": ["active", "inactive", "pending"]
|
|
}
|
|
schema = Schema(**schema_data)
|
|
assert schema.enum is not None
|
|
assert len(schema.enum) == 3
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|