Skip to content

Commit 3d22371

Browse files
committed
Elementary OpenAPI integration tests
1 parent 2e39274 commit 3d22371

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""Tests the OpenAPI specification that is to be stored in docs/openapi.json."""
2+
3+
import json
4+
from pathlib import Path
5+
6+
import pytest
7+
8+
# Strategy:
9+
# - Load the OpenAPI document from docs/openapi.json
10+
# - Validate critical structure based on the PR diff:
11+
# * openapi version, info, servers
12+
# * presence of paths/methods and key response codes
13+
# * presence and key attributes of important component schemas (enums, required fields)
14+
15+
OPENAPI_FILE = "docs/openapi.json"
16+
17+
18+
def _load_openapi_spec() -> dict:
19+
"""Load OpenAPI specification from configured path."""
20+
path = Path(OPENAPI_FILE)
21+
if path.is_file():
22+
with path.open("r", encoding="utf-8") as f:
23+
return json.load(f)
24+
25+
pytest.fail("OpenAPI spec not found")
26+
return {}
27+
28+
29+
@pytest.fixture(scope="module", name="spec")
30+
def open_api_spec() -> dict:
31+
"""Fixture containing OpenAPI specification represented as a dictionary."""
32+
return _load_openapi_spec()
33+
34+
35+
def test_openapi_top_level_info(spec: dict):
36+
"""Test all top level informations stored in OpenAPI specification."""
37+
assert spec.get("openapi") == "3.1.0"
38+
39+
info = spec.get("info") or {}
40+
assert info.get("title") == "Lightspeed Core Service (LCS) service - OpenAPI"
41+
assert "version" in info
42+
43+
contact = info.get("contact") or {}
44+
assert contact is not None
45+
46+
license_info = info.get("license") or {}
47+
assert license_info.get("name") == "Apache 2.0"
48+
assert "apache.org/licenses" in (license_info.get("url") or "")
49+
50+
51+
def test_servers_section_present(spec: dict):
52+
"""Test the servers section stored in OpenAPI specification."""
53+
servers = spec.get("servers")
54+
assert isinstance(servers, list) and servers, "servers must be a non-empty list"
55+
56+
57+
@pytest.mark.parametrize(
58+
"path,method,expected_codes",
59+
[
60+
("/", "get", {"200"}),
61+
("/v1/info", "get", {"200", "500"}),
62+
("/v1/models", "get", {"200", "503"}),
63+
("/v1/query", "post", {"200", "400", "403", "503", "422"}),
64+
("/v1/streaming_query", "post", {"200", "422"}),
65+
("/v1/config", "get", {"200", "503"}),
66+
("/v1/feedback", "post", {"200", "401", "403", "500", "422"}),
67+
("/v1/feedback/status", "get", {"200"}),
68+
("/v1/feedback/status", "put", {"200", "422"}),
69+
("/v1/conversations", "get", {"200", "503"}),
70+
("/v1/conversations/{conversation_id}", "get", {"200", "404", "503", "422"}),
71+
("/v1/conversations/{conversation_id}", "delete", {"200", "404", "503", "422"}),
72+
("/readiness", "get", {"200", "503"}),
73+
("/liveness", "get", {"200", "503"}),
74+
("/authorized", "post", {"200", "400", "403"}),
75+
("/metrics", "get", {"200"}),
76+
],
77+
)
78+
def test_paths_and_responses_exist(
79+
spec: dict, path: str, method: str, expected_codes: set[str]
80+
):
81+
"""Tests all paths defined in OpenAPI specification."""
82+
paths = spec.get("paths") or {}
83+
assert path in paths, f"Missing path: {path}"
84+
op = (paths[path] or {}).get(method)
85+
assert isinstance(op, dict), f"Missing method {method.upper()} for path {path}"
86+
responses = op.get("responses") or {}
87+
got_codes = set(responses.keys())
88+
for code in expected_codes:
89+
assert (
90+
code in got_codes
91+
), f"Missing response code {code} for {method.upper()} {path}"

0 commit comments

Comments
 (0)