"""GitHubClient (0.24.0, P1): same protocol as GiteaClient, GitHub wire shape underneath. Driven through MockTransport.""" import httpx import pytest from app.github_client import GitHubClient def make_client(handler) -> GitHubClient: return GitHubClient( base_url="https://api.github.com", token="ghp_test", cache_ttl=0, transport=httpx.MockTransport(handler), ) async def test_auth_header_is_bearer(): seen = {} def handler(request): seen["auth"] = request.headers.get("authorization") seen["accept"] = request.headers.get("accept") return httpx.Response(200, json={"login": "octocat"}) client = make_client(handler) user = await client.get_user() assert user["login"] == "octocat" assert seen["auth"] == "Bearer ghp_test" assert "application/vnd.github+json" in seen["accept"] async def test_pagination_follows_link_headers(): def handler(request): if "page=2" in str(request.url): return httpx.Response(200, json=[{"full_name": "a/deux"}]) return httpx.Response( 200, json=[{"full_name": "a/un"}], headers={ "Link": '; rel="next"' }, ) client = make_client(handler) repos = await client._fetch_search_repos() assert [r["full_name"] for r in repos] == ["a/un", "a/deux"] async def test_labels_are_addressed_by_name(): seen = {} def handler(request): if request.method == "GET" and request.url.path.endswith("/labels"): return httpx.Response( 200, json=[{"id": 991, "name": "kanban:todo", "color": "3b82f6"}] ) if request.method == "POST": seen["body"] = request.content.decode() return httpx.Response(200, json=[]) raise AssertionError(request.url) client = make_client(handler) label = await client.ensure_label("a", "b", "kanban:todo", "3b82f6") assert label["id"] == "kanban:todo" # name, not GitHub's numeric id await client.add_issue_label("a", "b", 7, label["id"]) assert '"kanban:todo"' in seen["body"] async def test_search_issues_normalizes_repository(): def handler(request): assert "is%3Aissue" in str(request.url) or "is:issue" in str(request.url) return httpx.Response( 200, json={ "items": [ { "number": 3, "title": "T", "repository_url": "https://api.github.com/repos/a/b", } ] }, ) client = make_client(handler) issues = await client.search_issues(q="mot", state="open") assert issues[0]["repository"]["full_name"] == "a/b" async def test_set_archived_uses_patch(): seen = {} def handler(request): seen["method"] = request.method seen["body"] = request.content.decode() return httpx.Response(200, json={"archived": True}) client = make_client(handler) await client.set_archived("a", "b", True) assert seen["method"] == "PATCH" assert '"archived": true' in seen["body"] or '"archived":true' in seen["body"] async def test_starred_roundtrip(): seen = {} def handler(request): seen["method"] = request.method seen["path"] = request.url.path return httpx.Response(204) client = make_client(handler) await client.set_starred("a", "b", True) assert seen["method"] == "PUT" assert seen["path"] == "/user/starred/a/b"