codeflash-agent/packages/github-app/tests/test_auth.py
Kevin Turcios 3ee9c22c8e
fix: resolve all ruff lint errors across repo (#38)
* fix: resolve all ruff lint errors across repo

Auto-fixed 31 errors (unused imports, formatting, simplifications).
Manually fixed 14 remaining:
- EXE001: removed shebangs from non-executable bench scripts
- C417: replaced map(lambda) with generator expression
- C901/PLR0915: extracted _write_and_instrument_tests from generate_ai_tests
- C901/PLR0912: extracted _parse_toml_addopts and _ini_section_name from modify_addopts
- RUF001/RUF002: replaced ambiguous Unicode chars (en dash, multiplication sign)
- FBT002: made boolean params keyword-only in report functions
- E402: moved `import re` to top of file in security reports

* fix: resolve pre-existing mypy errors across packages

- _testgen.py: annotate `generated` as `str` to avoid no-any-return
- _test_runner.py: use str() for TimeoutExpired stdout/stderr (bytes|str),
  remove unused type: ignore on proc.kill()
- _candidate_eval.py: annotate `speedup` as `float` to avoid no-any-return
  from lazy-loaded performance_gain
2026-04-23 10:22:42 -05:00

87 lines
2.2 KiB
Python

"""Tests for GitHub App authentication."""
from __future__ import annotations
import httpx
import jwt as pyjwt
import respx
from helpers import WEBHOOK_SECRET
from github_app.auth import (
generate_jwt,
get_installation_token,
verify_signature,
)
def test_generate_jwt_structure(mock_config):
token = generate_jwt(mock_config)
# Should be a 3-part JWT.
parts = token.split(".")
assert len(parts) == 3
def test_generate_jwt_claims(mock_config):
token = generate_jwt(mock_config)
claims = pyjwt.decode(
token,
options={"verify_signature": False},
algorithms=["RS256"],
)
# PyJWT requires iss as string; Config.app_id is int, converted in generate_jwt.
assert claims["iss"] == "12345"
assert "iat" in claims
assert "exp" in claims
# 660 = 600s expiry + 60s backdate.
assert claims["exp"] - claims["iat"] == 660
def test_verify_signature_valid():
payload = b"test payload"
import hashlib
import hmac
sig = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256,
).hexdigest()
assert verify_signature(payload, f"sha256={sig}", WEBHOOK_SECRET)
def test_verify_signature_invalid():
assert not verify_signature(b"payload", "sha256=wrong", WEBHOOK_SECRET)
def test_verify_signature_bad_prefix():
assert not verify_signature(b"payload", "md5=abc", WEBHOOK_SECRET)
@respx.mock
async def test_get_installation_token_fetches(mock_config):
respx.post(
"https://api.github.com/app/installations/99/access_tokens",
).respond(json={"token": "ghs_test123"})
async with httpx.AsyncClient() as client:
token = await get_installation_token(
mock_config,
99,
client=client,
)
assert token == "ghs_test123"
@respx.mock
async def test_get_installationtoken_caches(mock_config):
route = respx.post(
"https://api.github.com/app/installations/99/access_tokens",
).respond(json={"token": "ghs_cached"})
async with httpx.AsyncClient() as client:
t1 = await get_installation_token(mock_config, 99, client=client)
t2 = await get_installation_token(mock_config, 99, client=client)
assert t1 == t2 == "ghs_cached"
assert route.call_count == 1