Skip to content

Commit af61e1e

Browse files
author
Luigi Pellecchia
committed
Add API endpoint test suite and harden plugin presets fetch in frontend
Introduce 16 pytest test modules covering admin operations, user lifecycle, test run configuration, traceability scanner, and specification mapping endpoints. Fix plugin presets fetch in TestRunConfigForm and TestResultsModal to gracefully handle non-OK responses and non-array payloads instead of crashing on malformed data. Signed-off-by: Luigi Pellecchia <lpellecc@redhat.com>
1 parent e8afc83 commit af61e1e

18 files changed

+4050
-6
lines changed
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
"""HTTP tests for AdminResetUserPassword (PUT /admin/reset-user-password)."""
2+
from http import HTTPStatus
3+
4+
import pytest
5+
6+
from db.models.user import UserModel
7+
8+
_ADMIN_RESET_URL = "/admin/reset-user-password"
9+
10+
_UT_ADMIN_USER_NAME = "ut_admin_reset_pw_name"
11+
_UT_ADMIN_USER_EMAIL = "ut_admin_reset_pw_email"
12+
_UT_ADMIN_USER_PASSWORD = "ut_admin_reset_pw_password"
13+
_UT_ADMIN_USER_ROLE = "ADMIN"
14+
15+
_UT_TARGET_USER_NAME = "ut_reset_target_name"
16+
_UT_TARGET_USER_EMAIL = "ut_reset_target_email"
17+
_UT_TARGET_USER_PASSWORD = "ut_reset_target_password"
18+
19+
20+
@pytest.fixture(scope="module")
21+
def ut_admin_user_db(client_db):
22+
ut_admin = UserModel(
23+
_UT_ADMIN_USER_NAME,
24+
_UT_ADMIN_USER_EMAIL,
25+
_UT_ADMIN_USER_PASSWORD,
26+
_UT_ADMIN_USER_ROLE,
27+
)
28+
client_db.session.add(ut_admin)
29+
client_db.session.commit()
30+
yield ut_admin
31+
32+
33+
@pytest.fixture(scope="module")
34+
def ut_target_user_db(client_db):
35+
"""A dedicated user whose password will be reset during tests."""
36+
target = UserModel(
37+
_UT_TARGET_USER_NAME,
38+
_UT_TARGET_USER_EMAIL,
39+
_UT_TARGET_USER_PASSWORD,
40+
"USER",
41+
)
42+
client_db.session.add(target)
43+
client_db.session.commit()
44+
yield target
45+
46+
47+
@pytest.fixture(scope="module")
48+
def admin_authentication(client, ut_admin_user_db):
49+
return client.post(
50+
"/user/login",
51+
json={"email": _UT_ADMIN_USER_EMAIL, "password": _UT_ADMIN_USER_PASSWORD},
52+
)
53+
54+
55+
def _auth_fields(auth_response):
56+
data = auth_response.json
57+
return data["id"], data["token"]
58+
59+
60+
def _put_admin_reset_password(client, user_id, token, target_user_id, new_password):
61+
return client.put(
62+
_ADMIN_RESET_URL,
63+
json={
64+
"user-id": user_id,
65+
"token": token,
66+
"target-user": {"id": target_user_id, "password": new_password},
67+
},
68+
)
69+
70+
71+
def _get_user_by_id(client_db, user_id):
72+
client_db.session.expire_all()
73+
return client_db.session.query(UserModel).filter(UserModel.id == user_id).one()
74+
75+
76+
# -- Success -------------------------------------------------------------------
77+
78+
79+
def test_put_ok_resets_password(
80+
client, admin_authentication, ut_target_user_db, client_db
81+
):
82+
"""Admin can reset another user's password."""
83+
uid, token = _auth_fields(admin_authentication)
84+
target_id = ut_target_user_db.id
85+
86+
response = _put_admin_reset_password(
87+
client, uid, token, target_id, "brand_new_password"
88+
)
89+
assert response.status_code == HTTPStatus.OK
90+
assert response.get_json() is True
91+
92+
updated = _get_user_by_id(client_db, target_id)
93+
assert updated.pwd == "brand_new_password"
94+
95+
_put_admin_reset_password(
96+
client, uid, token, target_id, _UT_TARGET_USER_PASSWORD
97+
)
98+
99+
100+
# -- Bad Request (missing fields) ---------------------------------------------
101+
102+
103+
@pytest.mark.parametrize("missing_field", ["token", "user-id", "target-user"])
104+
def test_put_bad_request_missing_top_level_fields(
105+
client, admin_authentication, ut_reader_user_db, missing_field
106+
):
107+
"""Omitting any top-level mandatory field returns 400."""
108+
uid, token = _auth_fields(admin_authentication)
109+
body = {
110+
"user-id": uid,
111+
"token": token,
112+
"target-user": {"id": ut_reader_user_db.id, "password": "x"},
113+
}
114+
del body[missing_field]
115+
response = client.put(_ADMIN_RESET_URL, json=body)
116+
assert response.status_code == HTTPStatus.BAD_REQUEST
117+
118+
119+
@pytest.mark.parametrize("missing_field", ["id", "password"])
120+
def test_put_bad_request_missing_target_user_fields(
121+
client, admin_authentication, ut_reader_user_db, missing_field
122+
):
123+
"""Omitting a mandatory target-user sub-field returns 400."""
124+
uid, token = _auth_fields(admin_authentication)
125+
target = {"id": ut_reader_user_db.id, "password": "x"}
126+
del target[missing_field]
127+
response = client.put(
128+
_ADMIN_RESET_URL,
129+
json={"user-id": uid, "token": token, "target-user": target},
130+
)
131+
assert response.status_code == HTTPStatus.BAD_REQUEST
132+
133+
134+
# -- Unauthorized --------------------------------------------------------------
135+
136+
137+
def test_put_unauthorized_invalid_token(
138+
client, admin_authentication, ut_reader_user_db
139+
):
140+
"""Invalid token returns 401."""
141+
uid, _ = _auth_fields(admin_authentication)
142+
response = _put_admin_reset_password(
143+
client, uid, "not-a-valid-token", ut_reader_user_db.id, "x"
144+
)
145+
assert response.status_code == HTTPStatus.UNAUTHORIZED
146+
147+
148+
def test_put_unauthorized_non_admin_user(
149+
client, user_authentication, ut_reader_user_db
150+
):
151+
"""A USER-role account cannot reset passwords (only ADMIN can)."""
152+
uid, token = _auth_fields(user_authentication)
153+
response = _put_admin_reset_password(
154+
client, uid, token, ut_reader_user_db.id, "x"
155+
)
156+
assert response.status_code == HTTPStatus.UNAUTHORIZED
157+
158+
159+
def test_put_unauthorized_reader_user(
160+
client, reader_authentication, ut_user_db
161+
):
162+
"""Another USER-role account also cannot reset passwords."""
163+
uid, token = _auth_fields(reader_authentication)
164+
response = _put_admin_reset_password(
165+
client, uid, token, ut_user_db.id, "x"
166+
)
167+
assert response.status_code == HTTPStatus.UNAUTHORIZED
168+
169+
170+
# -- Not Found -----------------------------------------------------------------
171+
172+
173+
def test_put_not_found_target_user(client, admin_authentication):
174+
"""Resetting password of a non-existent user returns 404."""
175+
uid, token = _auth_fields(admin_authentication)
176+
response = _put_admin_reset_password(
177+
client, uid, token, 999_999, "x"
178+
)
179+
assert response.status_code == HTTPStatus.NOT_FOUND

0 commit comments

Comments
 (0)