-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest_oauth.py
More file actions
97 lines (85 loc) · 3.02 KB
/
Copy pathtest_oauth.py
File metadata and controls
97 lines (85 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from urllib.parse import urlparse, parse_qs
import pytest
import respx
import httpx
from fastapi import FastAPI
from fastapi.testclient import TestClient
from githubapp import GitHubApp
@pytest.fixture
def app_with_oauth():
app = FastAPI()
gh = GitHubApp(
app,
oauth_client_id="client-id",
oauth_client_secret="client-secret",
oauth_redirect_uri="http://localhost/callback",
oauth_session_secret="test-session-secret",
)
# Return both for potential future assertions
return app, gh
def test_oauth_login_returns_auth_url(app_with_oauth):
app, _ = app_with_oauth
with TestClient(app) as client:
resp = client.get("/auth/github/login")
assert resp.status_code == 200
data = resp.json()
assert "auth_url" in data
# Validate core params present
url = data["auth_url"]
parsed = urlparse(url)
qs = parse_qs(parsed.query)
assert qs.get("client_id") == ["client-id"]
assert "state" in qs and len(qs["state"][0]) > 0
@respx.mock
def test_oauth_callback_and_user(app_with_oauth):
app, gh = app_with_oauth
with TestClient(app) as client:
# 1) Get state from login
login = client.get("/auth/github/login")
state = parse_qs(urlparse(login.json()["auth_url"]).query)["state"][0]
# 2) Mock GitHub endpoints used by OAuth
token_route = respx.post("https://github.com/login/oauth/access_token").mock(
return_value=httpx.Response(
200,
json={
"access_token": "token123",
"token_type": "bearer",
"scope": "user:email read:user",
},
)
)
user_route = respx.get("https://api.github.com/user").mock(
return_value=httpx.Response(
200,
json={
"id": 42,
"login": "octocat",
"name": "The Octocat",
"email": "octo@example.com",
"avatar_url": "https://avatars.github.com/u/42",
},
)
)
emails_route = respx.get("https://api.github.com/user/emails").mock(
return_value=httpx.Response(
200, json=[{"email": "octo@example.com", "primary": True}]
)
)
# 3) Do callback
cb = client.get("/auth/github/callback", params={"code": "abc", "state": state})
assert cb.status_code == 200
body = cb.json()
assert body["user"]["login"] == "octocat"
assert "session_token" in body
# Ensure mocks were hit
assert token_route.called
assert user_route.called
assert emails_route.called
# 4) Use the session token to call /user
token = body["session_token"]
me = client.get(
"/auth/github/user", headers={"Authorization": f"Bearer {token}"}
)
assert me.status_code == 200
claims = me.json()
assert claims["login"] == "octocat"