Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

157 lines
5.1 KiB
Python

"""
Tests for HTTP API example scripts.
Validates that the example scripts under examples/api_usage/http/ exist,
are syntactically valid Python, and define the expected entry points.
The actual API functionality exercised by these examples is already covered
by test_rest_api.py and test_endpoints_health.py via the Flask test client.
"""
import ast
from pathlib import Path
import pytest
# Root of the repository
REPO_ROOT = Path(__file__).parent.parent.parent
EXAMPLES_DIR = REPO_ROOT / "examples" / "api_usage" / "http"
# All example scripts that should be tested — single source of truth
EXAMPLE_SCRIPTS = [
"simple_working_example.py",
"advanced/http_api_examples.py",
"advanced/simple_http_example.py",
]
def _parse_example(relative_path: str) -> tuple[Path, str, ast.Module]:
"""Read and parse an example file, failing if it doesn't exist.
Returns (path, source_text, ast_tree).
"""
path = EXAMPLES_DIR / relative_path
if not path.is_file():
pytest.fail(f"Example not found: {path}")
source = path.read_text(encoding="utf-8")
tree = ast.parse(source, filename=str(path))
return path, source, tree
def _has_main_guard(tree: ast.Module) -> bool:
"""Check if an AST contains an ``if __name__ == '__main__':`` guard."""
for node in ast.walk(tree):
if not isinstance(node, ast.If):
continue
test = node.test
if not isinstance(test, ast.Compare):
continue
if len(test.ops) != 1 or not isinstance(test.ops[0], ast.Eq):
continue
# Match both orderings:
# __name__ == "__main__"
# "__main__" == __name__
left = test.left
comparators = test.comparators
if len(comparators) != 1:
continue
right = comparators[0]
if (
isinstance(left, ast.Name)
and left.id == "__name__"
and isinstance(right, ast.Constant)
and right.value == "__main__"
) or (
isinstance(right, ast.Name)
and right.id == "__name__"
and isinstance(left, ast.Constant)
and left.value == "__main__"
):
return True
return False
class TestHttpExamplesExist:
"""Verify that expected HTTP example files are present."""
def test_examples_directory_exists(self):
assert EXAMPLES_DIR.is_dir(), (
f"Examples directory not found: {EXAMPLES_DIR}"
)
@pytest.mark.parametrize("relative_path", EXAMPLE_SCRIPTS)
def test_example_file_exists(self, relative_path):
path = EXAMPLES_DIR / relative_path
assert path.is_file(), f"Missing example: {path}"
class TestHttpExamplesSyntax:
"""Verify that example scripts are syntactically valid Python."""
@pytest.mark.parametrize("relative_path", EXAMPLE_SCRIPTS)
def test_example_parses(self, relative_path):
"""Each example file must be valid Python (no syntax errors)."""
_path, _source, tree = _parse_example(relative_path)
assert tree is not None
@pytest.mark.parametrize("relative_path", EXAMPLE_SCRIPTS)
def test_example_has_main_function(self, relative_path):
"""Each example script should define a main() function."""
_path, _source, tree = _parse_example(relative_path)
function_names = [
node.name
for node in ast.walk(tree)
if isinstance(node, ast.FunctionDef)
]
assert "main" in function_names, (
f"{relative_path} should define a main() function"
)
@pytest.mark.parametrize("relative_path", EXAMPLE_SCRIPTS)
def test_example_has_main_guard(self, relative_path):
"""Each example script should have an if __name__ == '__main__' guard."""
_path, _source, tree = _parse_example(relative_path)
assert _has_main_guard(tree), (
f"{relative_path} should have an if __name__ == '__main__' guard"
)
class TestAdvancedExampleStructure:
"""Verify the advanced example defines expected helper classes/functions."""
def test_ldr_client_class_defined(self):
"""The advanced example should define an LDRClient class."""
_path, _source, tree = _parse_example("advanced/http_api_examples.py")
class_names = [
node.name
for node in ast.walk(tree)
if isinstance(node, ast.ClassDef)
]
assert "LDRClient" in class_names, (
"Advanced example should define LDRClient class"
)
def test_example_functions_defined(self):
"""The advanced example should define the documented example functions."""
_path, _source, tree = _parse_example("advanced/http_api_examples.py")
function_names = {
node.name
for node in ast.walk(tree)
if isinstance(node, ast.FunctionDef)
}
expected_examples = [
"example_quick_research",
"example_settings_management",
"example_research_history",
]
for fn in expected_examples:
assert fn in function_names, (
f"Advanced example should define {fn}()"
)