codeflash-agent/packages/github-app/tests/conftest.py
Kevin Turcios e41a1bf56a Fix conftest collision between codeflash-api and github-app test suites
Both packages had tests/__init__.py, creating competing `tests`
packages under --import-mode=importlib. Remove both __init__.py files
and change github-app imports from `from tests.helpers` to
`from helpers` via sys.path insertion in conftest.py.
2026-04-23 03:33:58 -05:00

141 lines
3.6 KiB
Python

"""Shared test fixtures for codeflash-service."""
from __future__ import annotations
import os
import sys
from pathlib import Path
from unittest.mock import MagicMock
import httpx
import pytest
import stamina
sys.path.insert(0, str(Path(__file__).resolve().parent))
from helpers import FAKE_RSA_PEM, WEBHOOK_SECRET, sign_payload # noqa: E402
__all__ = ["FAKE_RSA_PEM", "WEBHOOK_SECRET", "sign_payload"]
@pytest.fixture(autouse=True, scope="session")
def set_env():
"""Set required env vars so Config() can be instantiated."""
os.environ.setdefault("GITHUB_APP_ID", "12345")
os.environ.setdefault("GITHUB_PRIVATE_KEY", FAKE_RSA_PEM)
os.environ.setdefault("GITHUB_WEBHOOK_SECRET", WEBHOOK_SECRET)
@pytest.fixture(autouse=True, scope="session")
def deactivate_retries():
"""Disable stamina retries for fast tests."""
stamina.set_active(False)
@pytest.fixture(autouse=True)
def clear_token_cache():
"""Clear the installation token cache between tests."""
from github_app.auth import token_cache
token_cache.clear()
@pytest.fixture()
def mock_config():
"""A mock Config with all required fields."""
cfg = MagicMock()
cfg.app_id = 12345
cfg.private_key = FAKE_RSA_PEM
cfg.webhook_secret = WEBHOOK_SECRET
cfg.claude_cli = "claude"
cfg.claude_model = "claude-sonnet-4-6"
cfg.plugin_dir = Path("/tmp/plugins")
cfg.codex_cli = "codex"
cfg.codex_model = "gpt-5.4"
cfg.lead_backend = "claude"
cfg.cli_for_backend = lambda name: {
"claude": cfg.claude_cli,
"codex": cfg.codex_cli,
}[name]
cfg.model_for_backend = lambda name: {
"claude": cfg.claude_model,
"codex": cfg.codex_model,
}[name]
cfg.host = "0.0.0.0"
cfg.port = 8000
cfg.workspace_dir = Path("/tmp/codeflash-workspaces")
return cfg
@pytest.fixture()
def pr_payload():
"""Minimal pull_request webhook payload."""
return {
"action": "opened",
"pull_request": {
"number": 42,
"title": "Test PR",
"head": {"ref": "feature-branch"},
"base": {"ref": "main"},
},
"repository": {
"name": "test-repo",
"owner": {"login": "test-owner"},
"default_branch": "main",
},
"installation": {"id": 99},
}
@pytest.fixture()
def issue_payload():
"""Minimal issues webhook payload."""
return {
"action": "opened",
"issue": {
"number": 7,
"title": "Bug: something broken",
"body": "Steps to reproduce...",
"labels": [],
},
"repository": {
"name": "test-repo",
"owner": {"login": "test-owner"},
"default_branch": "main",
},
"installation": {"id": 99},
}
@pytest.fixture()
def push_payload():
"""Minimal push webhook payload."""
return {
"ref": "refs/heads/main",
"after": "abc123",
"repository": {
"name": "test-repo",
"owner": {"login": "test-owner"},
"default_branch": "main",
},
"installation": {"id": 99},
}
@pytest.fixture()
async def async_client(mock_config):
"""ASGI test client with app state pre-populated."""
from github_app.app import app
mock_http = httpx.AsyncClient()
app.state.config = mock_config
app.state.http_client = mock_http
app.state.running_tasks = set()
async with httpx.AsyncClient(
transport=httpx.ASGITransport(app=app),
base_url="http://test",
) as client:
yield client
await mock_http.aclose()