mirror of
https://github.com/codeflash-ai/codeflash-agent.git
synced 2026-05-04 18:25:19 +00:00
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.
141 lines
3.6 KiB
Python
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()
|