Skip to content

Commit 5e0428b

Browse files
committed
🚢 test: admin auth
1 parent e2a43eb commit 5e0428b

File tree

5 files changed

+211
-69
lines changed

5 files changed

+211
-69
lines changed

app/schemas/auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class PasswordOAuthRequest(OAuthRequest):
2222
str,
2323
Form(
2424
min_length=5,
25-
max_length=30,
25+
max_length=50,
2626
pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
2727
),
2828
]

app/tests/api/v1/admin/__init__.py

Whitespace-only changes.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import pytest
2+
from faker import Faker
3+
from fastapi import status
4+
from fastapi.testclient import TestClient
5+
from loguru import logger
6+
7+
from app.core.configs import configs
8+
from app.schemas.auth import PasswordOAuthReigsterRequest
9+
from app.schemas.users import UserPatchRequest, UserRequest
10+
from app.tests.api.v1.test_auth import MockUser, register_and_log_in
11+
12+
fake = Faker()
13+
14+
15+
def log_in_admin(sync_client: TestClient) -> tuple[MockUser, str]:
16+
admin_user = MockUser(
17+
sync_client=sync_client,
18+
request=PasswordOAuthReigsterRequest(
19+
grant_type="password",
20+
username=configs.ADMIN_EMAIL,
21+
password=configs.ADMIN_PASSWORD,
22+
name=configs.ADMIN_NAME,
23+
),
24+
)
25+
access_token = admin_user.log_in()
26+
return admin_user, access_token
27+
28+
29+
def test_get_user_name(sync_client: TestClient) -> None:
30+
admin_user, admin_access_token = log_in_admin(sync_client)
31+
mock_user, user_access_token = register_and_log_in(sync_client)
32+
response = sync_client.get(
33+
f"{configs.PREFIX}/v1/user/",
34+
headers={"Authorization": f"Bearer {admin_access_token}"},
35+
)
36+
logger.warning(response)
37+
assert response.status_code == status.HTTP_200_OK
38+
data = response.json()["data"]
39+
assert isinstance(data, list)
40+
assert 1 < len(data)
41+
response = sync_client.get(
42+
f"{configs.PREFIX}/v1/user/",
43+
headers={"Authorization": f"Bearer {user_access_token}"},
44+
)
45+
logger.warning(response)
46+
assert response.status_code == status.HTTP_403_FORBIDDEN
47+
response = sync_client.get(
48+
f"{configs.PREFIX}/v1/user/1",
49+
headers={"Authorization": f"Bearer {admin_access_token}"},
50+
)
51+
logger.warning(response)
52+
data = response.json()["data"]
53+
assert data["id"] == 1
54+
assert data["name"] == configs.ADMIN_NAME
55+
assert data["email"] == configs.ADMIN_EMAIL
56+
assert data["oauth"] == "password"
57+
assert response.status_code == status.HTTP_200_OK
58+
response = sync_client.get(
59+
f"{configs.PREFIX}/v1/user/1",
60+
headers={"Authorization": f"Bearer {user_access_token}"},
61+
)
62+
logger.warning(response)
63+
assert response.status_code == status.HTTP_403_FORBIDDEN
64+
65+
66+
def test_patch_user_password(sync_client: TestClient) -> None:
67+
admin_user, admin_access_token = log_in_admin(sync_client)
68+
mock_user, user_access_token = register_and_log_in(sync_client)
69+
request = UserPatchRequest(password=fake.password())
70+
response = sync_client.patch(
71+
f"{configs.PREFIX}/v1/user/{mock_user.get_me(user_access_token)}",
72+
headers={"Authorization": f"Bearer {admin_access_token}"},
73+
json=request.model_dump(),
74+
)
75+
logger.warning(response)
76+
assert response.status_code == status.HTTP_200_OK
77+
with pytest.raises(AssertionError):
78+
mock_user.log_in()
79+
if request.password is None:
80+
raise ValueError
81+
mock_user.request.password = request.password
82+
mock_user.log_in()
83+
84+
85+
def test_put_user(sync_client: TestClient) -> None:
86+
admin_user, admin_access_token = log_in_admin(sync_client)
87+
mock_user, user_access_token = register_and_log_in(sync_client)
88+
request = UserRequest(name=fake.name(), email=fake.email())
89+
response = sync_client.put(
90+
f"{configs.PREFIX}/v1/user/{mock_user.get_me(user_access_token)}",
91+
headers={"Authorization": f"Bearer {admin_access_token}"},
92+
json=request.model_dump(),
93+
)
94+
logger.warning(response)
95+
assert response.status_code == status.HTTP_200_OK
96+
data = response.json()["data"]
97+
assert data["name"] != mock_user.request.name
98+
assert data["email"] != mock_user.request.username
99+
assert data["name"] == request.name
100+
assert data["email"] == request.email
101+
102+
103+
def test_delete_user(sync_client: TestClient) -> None:
104+
admin_user, admin_access_token = log_in_admin(sync_client)
105+
mock_user, user_access_token = register_and_log_in(sync_client)
106+
response = sync_client.delete(
107+
f"{configs.PREFIX}/v1/user/{mock_user.get_me(user_access_token)}",
108+
headers={"Authorization": f"Bearer {admin_access_token}"},
109+
)
110+
logger.warning(response)
111+
assert response.status_code == status.HTTP_200_OK
112+
data = response.json()["data"]
113+
assert data["name"] == mock_user.request.name
114+
assert data["email"] == mock_user.request.username
115+
with pytest.raises(AssertionError):
116+
mock_user.log_in()

app/tests/api/v1/test_auth.py

Lines changed: 80 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,102 @@
1+
from typing import Optional
2+
13
from faker import Faker
24
from fastapi import status
35
from fastapi.testclient import TestClient
46
from loguru import logger
57

68
from app.core.configs import configs
79
from app.models.enums import OAuthProvider, Role
8-
from app.schemas.users import UserPasswordRequest, UserRegisterRequest
10+
from app.schemas.auth import PasswordOAuthReigsterRequest, PasswordOAuthRequest
911

1012
fake = Faker()
1113

1214

13-
def test_register_and_login(sync_client: TestClient):
14-
for _ in range(5):
15-
request, access_token = register_and_login(sync_client)
16-
get_me(sync_client, request, access_token)
17-
response = sync_client.post(
18-
f"{configs.PREFIX}/v1/auth/register/",
19-
json=request.model_dump(),
15+
def get_mock_request() -> PasswordOAuthReigsterRequest:
16+
return PasswordOAuthReigsterRequest(
17+
grant_type="password",
18+
username=fake.email(),
19+
password=fake.password(),
20+
name=fake.name(),
2021
)
21-
assert response.status_code == 409
2222

2323

24-
def get_mock_request() -> UserRegisterRequest:
25-
return UserRegisterRequest(
26-
name=fake.name(), email=fake.email(), password=fake.password()
27-
)
28-
24+
class MockUser:
25+
def __init__(
26+
self,
27+
sync_client: TestClient,
28+
request: Optional[PasswordOAuthReigsterRequest] = None,
29+
) -> None:
30+
self.client = sync_client
31+
self.headers = {
32+
"Content-Type": "application/x-www-form-urlencoded",
33+
"Accept": "application/json",
34+
}
35+
if request:
36+
self.request = request
37+
else:
38+
self.request = get_mock_request()
2939

30-
def register_and_login(sync_client: TestClient) -> tuple[UserRegisterRequest, str]:
31-
request = get_mock_request()
32-
register(sync_client, request)
33-
access_token = log_in(
34-
sync_client, UserPasswordRequest.model_validate(request.model_dump())
35-
)
36-
return request, access_token
40+
def register(self) -> None:
41+
response = self.client.post(
42+
f"{configs.PREFIX}/v1/auth/register/password/",
43+
headers=self.headers,
44+
data=self.request.model_dump(),
45+
)
46+
logger.warning(response)
47+
assert response.status_code == status.HTTP_201_CREATED
48+
data = response.json()["data"]
49+
assert data["name"] == self.request.name
50+
assert data["email"] == self.request.username
3751

52+
def log_in(self) -> str:
53+
request = PasswordOAuthRequest.model_validate(self.request.model_dump())
54+
response = self.client.post(
55+
f"{configs.PREFIX}/v1/auth/token/password/",
56+
headers=self.headers,
57+
data=request.model_dump(),
58+
)
59+
logger.warning(response)
60+
assert response.status_code == status.HTTP_200_OK
61+
data = response.json()
62+
assert "access_token" in data
63+
assert "refresh_token" in data
64+
assert "token_type" in data
65+
assert "expires_in" in data
66+
return data["access_token"]
3867

39-
def register(sync_client: TestClient, request: UserRegisterRequest) -> None:
40-
response = sync_client.post(
41-
f"{configs.PREFIX}/v1/auth/register/",
42-
json=request.model_dump(),
43-
)
44-
logger.warning(response)
45-
assert response.status_code == status.HTTP_201_CREATED
46-
data = response.json()["data"]
47-
assert request.name == data["name"]
48-
assert request.email == data["email"]
68+
def get_me(self, access_token: str) -> int:
69+
logger.warning(access_token)
70+
response = self.client.get(
71+
f"{configs.PREFIX}/v1/auth/me/",
72+
headers={"Authorization": f"Bearer {access_token}"},
73+
)
74+
logger.warning(response)
75+
logger.warning(response.json())
76+
assert response.status_code == status.HTTP_200_OK
77+
data = response.json()["data"]
78+
assert data["oauth"] == OAuthProvider.PASSWORD.value
79+
assert data["role"] == Role.USER.value
80+
assert data["name"] == self.request.name
81+
assert data["email"] == self.request.username
82+
assert data["password"] != self.request.password
83+
return data["id"]
4984

5085

51-
def log_in(sync_client: TestClient, request: UserPasswordRequest) -> str:
52-
response = sync_client.post(
53-
f"{configs.PREFIX}/v1/auth/login/", json=request.model_dump()
54-
)
55-
logger.warning(response)
56-
assert response.status_code == status.HTTP_200_OK
57-
data = response.json()["data"]
58-
return data["access_token"]
86+
def register_and_log_in(sync_client: TestClient) -> tuple[MockUser, str]:
87+
mock_user = MockUser(sync_client=sync_client)
88+
mock_user.register()
89+
access_token = mock_user.log_in()
90+
return mock_user, access_token
5991

6092

61-
def get_me(sync_client: TestClient, request: UserRegisterRequest, access_token: str):
62-
logger.warning(access_token)
63-
response = sync_client.get(
64-
f"{configs.PREFIX}/v1/auth/me/",
65-
headers={"Authorization": f"Bearer {access_token}"},
93+
def test_register_and_log_in(sync_client: TestClient):
94+
for _ in range(5):
95+
mock_user, access_token = register_and_log_in(sync_client)
96+
mock_user.get_me(access_token)
97+
response = sync_client.post(
98+
f"{configs.PREFIX}/v1/auth/register/password/",
99+
headers=mock_user.headers,
100+
data=mock_user.request.model_dump(),
66101
)
67-
logger.warning(response)
68-
logger.warning(response.json())
69-
assert response.status_code == status.HTTP_200_OK
70-
data = response.json()["data"]
71-
assert data["oauth"] == OAuthProvider.PASSWORD.value
72-
assert data["role"] == Role.USER.value
73-
assert data["name"] == request.name
74-
assert data["email"] == request.email
75-
assert data["password"] != request.password
102+
assert response.status_code == 409

app/tests/api/v1/test_users.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
from loguru import logger
66

77
from app.core.configs import configs
8-
from app.schemas.users import UserPasswordRequest, UserPatchRequest, UserRequest
9-
from app.tests.api.v1.test_auth import log_in, register_and_login
8+
from app.schemas.users import UserPatchRequest, UserRequest
9+
from app.tests.api.v1.test_auth import register_and_log_in
1010

1111
fake = Faker()
1212

1313

1414
def test_patch_user_name(sync_client: TestClient) -> None:
15-
schema, access_token = register_and_login(sync_client)
15+
mock_user, access_token = register_and_log_in(sync_client)
1616
request = UserPatchRequest(name=fake.name())
1717
response = sync_client.patch(
1818
f"{configs.PREFIX}/v1/user/",
@@ -22,12 +22,12 @@ def test_patch_user_name(sync_client: TestClient) -> None:
2222
logger.warning(response)
2323
assert response.status_code == status.HTTP_200_OK
2424
data = response.json()["data"]
25-
assert data["name"] != schema.name
25+
assert data["name"] != mock_user.request.name
2626
assert data["name"] == request.name
2727

2828

2929
def test_patch_user_password(sync_client: TestClient) -> None:
30-
schema, access_token = register_and_login(sync_client)
30+
mock_user, access_token = register_and_log_in(sync_client)
3131
request = UserPatchRequest(password=fake.password())
3232
response = sync_client.patch(
3333
f"{configs.PREFIX}/v1/user/",
@@ -37,16 +37,15 @@ def test_patch_user_password(sync_client: TestClient) -> None:
3737
logger.warning(response)
3838
assert response.status_code == status.HTTP_200_OK
3939
with pytest.raises(AssertionError):
40-
log_in(sync_client, UserPasswordRequest.model_validate(schema.model_dump()))
40+
mock_user.log_in()
4141
if request.password is None:
4242
raise ValueError
43-
log_in(
44-
sync_client, UserPasswordRequest(email=schema.email, password=request.password)
45-
)
43+
mock_user.request.password = request.password
44+
mock_user.log_in()
4645

4746

4847
def test_put_user(sync_client: TestClient) -> None:
49-
schema, access_token = register_and_login(sync_client)
48+
mock_user, access_token = register_and_log_in(sync_client)
5049
request = UserRequest(name=fake.name(), email=fake.email())
5150
response = sync_client.put(
5251
f"{configs.PREFIX}/v1/user/",
@@ -56,20 +55,20 @@ def test_put_user(sync_client: TestClient) -> None:
5655
logger.warning(response)
5756
assert response.status_code == status.HTTP_200_OK
5857
data = response.json()["data"]
59-
assert data["name"] != schema.name
60-
assert data["email"] != schema.email
58+
assert data["name"] != mock_user.request.name
59+
assert data["email"] != mock_user.request.username
6160
assert data["name"] == request.name
6261
assert data["email"] == request.email
6362

6463

6564
def test_delete_user(sync_client: TestClient) -> None:
66-
schema, access_token = register_and_login(sync_client)
65+
mock_user, access_token = register_and_log_in(sync_client)
6766
response = sync_client.delete(
6867
f"{configs.PREFIX}/v1/user/",
6968
headers={"Authorization": f"Bearer {access_token}"},
7069
)
7170
logger.warning(response)
7271
assert response.status_code == status.HTTP_200_OK
7372
data = response.json()["data"]
74-
assert data["name"] == schema.name
75-
assert data["email"] == schema.email
73+
assert data["name"] == mock_user.request.name
74+
assert data["email"] == mock_user.request.username

0 commit comments

Comments
 (0)