174 lines
6.0 KiB
Python
174 lines
6.0 KiB
Python
"""Unit tests for the spec parser module."""
|
|
import pytest
|
|
import tempfile
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from api_testgen.core import SpecParser
|
|
from api_testgen.core.exceptions import InvalidOpenAPISpecError, UnsupportedVersionError
|
|
|
|
|
|
class TestSpecParser:
|
|
"""Tests for SpecParser class."""
|
|
|
|
def test_load_valid_openapi_30_spec(self, temp_spec_file):
|
|
"""Test loading a valid OpenAPI 3.0 specification."""
|
|
parser = SpecParser(temp_spec_file)
|
|
spec = parser.load()
|
|
|
|
assert spec is not None
|
|
assert parser.version == "3.0.0"
|
|
assert parser.base_path == ""
|
|
assert len(parser.servers) == 1
|
|
|
|
def test_load_valid_json_spec(self, temp_json_spec_file):
|
|
"""Test loading a valid JSON OpenAPI specification."""
|
|
parser = SpecParser(temp_json_spec_file)
|
|
spec = parser.load()
|
|
|
|
assert spec is not None
|
|
assert parser.version == "3.0.0"
|
|
|
|
def test_get_info(self, temp_spec_file):
|
|
"""Test extracting API info from spec."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
info = parser.get_info()
|
|
|
|
assert info["title"] == "Test Pet Store API"
|
|
assert info["version"] == "1.0.0"
|
|
assert "sample" in info["description"].lower()
|
|
|
|
def test_get_paths(self, temp_spec_file):
|
|
"""Test extracting paths from spec."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
paths = parser.get_paths()
|
|
|
|
assert "/pets" in paths
|
|
assert "/pets/{petId}" in paths
|
|
|
|
def test_get_endpoints(self, temp_spec_file):
|
|
"""Test extracting endpoints from spec."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
endpoints = parser.get_endpoints()
|
|
|
|
assert len(endpoints) == 4
|
|
assert any(e["method"] == "get" and e["path"] == "/pets" for e in endpoints)
|
|
assert any(e["method"] == "post" and e["path"] == "/pets" for e in endpoints)
|
|
assert any(e["method"] == "get" and e["path"] == "/pets/{petId}" for e in endpoints)
|
|
assert any(e["method"] == "delete" and e["path"] == "/pets/{petId}" for e in endpoints)
|
|
|
|
def test_get_security_schemes(self, temp_spec_file):
|
|
"""Test extracting security schemes from spec."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
schemes = parser.get_security_schemes()
|
|
|
|
assert "ApiKeyAuth" in schemes
|
|
assert "BearerAuth" in schemes
|
|
assert schemes["ApiKeyAuth"]["type"] == "apiKey"
|
|
assert schemes["BearerAuth"]["type"] == "http"
|
|
assert schemes["BearerAuth"]["scheme"] == "bearer"
|
|
|
|
def test_get_definitions(self, temp_spec_file):
|
|
"""Test extracting schema definitions from spec."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
definitions = parser.get_definitions()
|
|
|
|
assert "Pet" in definitions
|
|
assert definitions["Pet"]["type"] == "object"
|
|
|
|
def test_endpoint_with_parameters(self, temp_spec_file):
|
|
"""Test endpoint parameter extraction."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
endpoints = parser.get_endpoints()
|
|
|
|
pets_endpoint = next(e for e in endpoints if e["path"] == "/pets" and e["method"] == "get")
|
|
|
|
assert len(pets_endpoint["parameters"]) == 2
|
|
assert any(p["name"] == "limit" and p["in"] == "query" for p in pets_endpoint["parameters"])
|
|
assert any(p["name"] == "status" and p["in"] == "query" for p in pets_endpoint["parameters"])
|
|
|
|
def test_endpoint_with_path_parameters(self, temp_spec_file):
|
|
"""Test path parameter extraction."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
endpoints = parser.get_endpoints()
|
|
|
|
pet_endpoint = next(e for e in endpoints if e["path"] == "/pets/{petId}" and e["method"] == "get")
|
|
|
|
assert len(pet_endpoint["parameters"]) == 1
|
|
param = pet_endpoint["parameters"][0]
|
|
assert param["name"] == "petId"
|
|
assert param["in"] == "path"
|
|
assert param["required"] is True
|
|
|
|
def test_endpoint_with_request_body(self, temp_spec_file):
|
|
"""Test request body extraction for OpenAPI 3.0."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
endpoints = parser.get_endpoints()
|
|
|
|
create_endpoint = next(e for e in endpoints if e["path"] == "/pets" and e["method"] == "post")
|
|
|
|
assert create_endpoint["request_body"] is not None
|
|
assert create_endpoint["request_body"]["required"] is True
|
|
|
|
def test_endpoint_with_responses(self, temp_spec_file):
|
|
"""Test response extraction."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
endpoints = parser.get_endpoints()
|
|
|
|
pets_endpoint = next(e for e in endpoints if e["path"] == "/pets" and e["method"] == "get")
|
|
|
|
assert "200" in pets_endpoint["responses"]
|
|
assert pets_endpoint["responses"]["200"]["description"] == "A list of pets"
|
|
|
|
def test_to_dict(self, temp_spec_file):
|
|
"""Test dictionary representation of parsed spec."""
|
|
parser = SpecParser(temp_spec_file)
|
|
parser.load()
|
|
|
|
spec_dict = parser.to_dict()
|
|
|
|
assert "version" in spec_dict
|
|
assert "info" in spec_dict
|
|
assert "paths" in spec_dict
|
|
assert "endpoints" in spec_dict
|
|
assert "security_schemes" in spec_dict
|
|
assert "definitions" in spec_dict
|
|
|
|
def test_nonexistent_file_raises_error(self):
|
|
"""Test that nonexistent file raises InvalidOpenAPISpecError."""
|
|
parser = SpecParser("/nonexistent/path/spec.yaml")
|
|
|
|
with pytest.raises(InvalidOpenAPISpecError):
|
|
parser.load()
|
|
|
|
def test_invalid_yaml_raises_error(self):
|
|
"""Test that invalid YAML raises InvalidOpenAPISpecError."""
|
|
with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f:
|
|
f.write("invalid: yaml: content: [[[")
|
|
f.flush()
|
|
|
|
parser = SpecParser(Path(f.name))
|
|
|
|
with pytest.raises(InvalidOpenAPISpecError):
|
|
parser.load()
|
|
|
|
Path(f.name).unlink()
|