Skip to content

Commit

Permalink
tests: Improve citation screening api tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bdewilde committed May 14, 2024
1 parent a9dd10c commit de0d81c
Showing 1 changed file with 155 additions and 51 deletions.
206 changes: 155 additions & 51 deletions tests/api/test_citation_screenings.py
Original file line number Diff line number Diff line change
@@ -1,86 +1,190 @@
import flask
import pytest

from colandr.apis import auth

from .. import helpers


# TODO: figure out why cli seed command errors when screening records have "id" fields


@pytest.mark.usefixtures("db_session")
class TestCitationScreeningsResource:
@pytest.mark.parametrize(
["id_", "params", "status_code", "num_exp"],
["current_user_id", "study_id", "params", "exp_data"],
[
(1, None, 200, 1),
(4, None, 200, 2),
(1, {"fields": "id,review_id"}, 200, 1),
(1, {"fields": "status"}, 200, 1),
(999, None, 404, 0),
(
1,
1,
None,
[
{
"user_id": 2,
"review_id": 1,
"citation_id": 1,
"status": "included",
}
],
),
(
2,
4,
None,
[
{
"user_id": 2,
"review_id": 2,
"citation_id": 4,
"status": "included",
},
{
"user_id": 3,
"review_id": 2,
"citation_id": 4,
"status": "included",
},
],
),
(
3,
3,
{"fields": "id,review_id,citation_id"},
[{"review_id": 1, "citation_id": 3}],
),
],
)
def test_get(
self, id_, params, status_code, num_exp, app, client, admin_headers, seed_data
self, current_user_id, study_id, params, exp_data, app, client, db_session
):
with app.test_request_context():
url = flask.url_for(
"citation_screenings_citation_screenings_resource",
id=id_,
id=study_id,
**(params or {}),
)
response = client.get(url, headers=admin_headers)
with app.app_context():
with helpers.set_current_user(current_user_id, db_session) as current_user:
headers = auth.pack_header_for_user(current_user)
response = client.get(url, headers=headers)
assert response.status_code == 200
data = response.json
assert isinstance(data, list)
for item, exp_item in zip(data, exp_data):
assert "id" in item
assert {k: v for k, v in item.items() if k in exp_item} == exp_item

@pytest.mark.parametrize(
["current_user_id", "study_id", "params", "status_code"],
[
(1, 999, None, 404),
(4, 1, None, 403),
],
)
def test_get_errors(
self, current_user_id, study_id, params, status_code, app, client, db_session
):
with app.test_request_context():
url = flask.url_for(
"citation_screenings_citation_screenings_resource",
id=study_id,
**(params or {}),
)
with app.app_context():
with helpers.set_current_user(current_user_id, db_session) as current_user:
response = client.get(
url, headers=auth.pack_header_for_user(current_user)
)
assert response.status_code == status_code
if 200 <= status_code < 300:
records = response.json
seed_data = seed_data["screenings"][id_ - 1]
fields = None if params is None else params["fields"].split(",")
# if fields is not None and "id" not in fields:
# fields.append("id")
assert isinstance(records, list) and len(records) == num_exp
for record in records:
# TODO: figure out what to do with these checks below
# assert "id" in record
# assert record["study_id"] == id_
for field in ["review_id", "status"]:
if fields is None or field in fields:
assert record[field] == seed_data.get(field)
if fields:
assert sorted(record.keys()) == sorted(fields)

@pytest.mark.parametrize(
["id_", "data", "status_code"],
["current_user_id", "study_id", "data"],
[
(3, {"user_id": 2, "status": "included"}, 200),
(1, 3, {"user_id": 2, "status": "included"}),
(
4,
{
"user_id": 3,
"status": "excluded",
"exclude_reasons": ["REASON3"],
},
200,
2,
1,
{"user_id": 2, "status": "excluded", "exclude_reasons": ["REASON3"]},
),
(999, {"status": "included"}, 422),
],
)
def test_put(self, id_, data, status_code, app, client, admin_headers):
def test_put(self, current_user_id, study_id, data, app, client, db_session):
with app.test_request_context():
url = flask.url_for(
"citation_screenings_citation_screenings_resource", id=id_
"citation_screenings_citation_screenings_resource", id=study_id
)
response = client.put(url, json=data, headers=admin_headers)
with app.app_context():
with helpers.set_current_user(current_user_id, db_session) as current_user:
headers = auth.pack_header_for_user(current_user)
response = client.put(url, json=data, headers=headers)
assert response.status_code == 200
obs_data = response.json
assert "id" in obs_data and obs_data["id"] == study_id
assert {k: v for k, v in obs_data.items() if k in data} == data

@pytest.mark.parametrize(
["current_user_id", "study_id", "data", "status_code"],
[
(1, 1, {"user_id": 2}, 422),
(1, 1, {"user_id": 2, "status": "excluded"}, 400),
(1, 999, {"user_id": 1, "status": "included"}, 404),
],
)
def test_put_errors(
self, current_user_id, study_id, data, status_code, app, client, db_session
):
with app.test_request_context():
url = flask.url_for(
"citation_screenings_citation_screenings_resource", id=study_id
)
with app.app_context():
with helpers.set_current_user(current_user_id, db_session) as current_user:
response = client.put(
url, json=data, headers=auth.pack_header_for_user(current_user)
)
assert response.status_code == status_code
if 200 <= status_code < 300:
data = response.json
for key, val in data.items():
assert data.get(key) == val

@pytest.mark.parametrize("id_", [1, 2])
def test_delete(self, id_, app, client, admin_headers):
@pytest.mark.parametrize(
["current_user_id", "study_id"],
[
(2, 1),
(3, 4),
],
)
def test_delete(self, current_user_id, study_id, app, client, db_session):
with app.test_request_context():
url = flask.url_for(
"citation_screenings_citation_screenings_resource", id=study_id
)
with app.app_context():
with helpers.set_current_user(current_user_id, db_session) as current_user:
headers = auth.pack_header_for_user(current_user)
response = client.delete(url, headers=headers)
assert response.status_code == 204
assert not any(
item["user_id"] == current_user_id
for item in client.get(url, headers=headers).json
) # not found!

@pytest.mark.parametrize(
["current_user_id", "study_id", "status_code"],
[
(1, 999, 404), # only existing screenings can be deleted
(4, 1, 403), # only reviewers can delete their own screenings
],
)
def test_delete_errors(
self, current_user_id, study_id, status_code, app, client, db_session
):
with app.test_request_context():
url = flask.url_for(
"citation_screenings_citation_screenings_resource", id=id_
"citation_screenings_citation_screenings_resource", id=study_id
)
response = client.delete(url, headers=admin_headers)
# NOTE: this operation is currently only allowed for the screener themself
assert response.status_code == 403
# get_response = client.get(url, headers=admin_headers)
# assert get_response.status_code == 404 # not found!
with app.app_context():
with helpers.set_current_user(current_user_id, db_session) as current_user:
headers = auth.pack_header_for_user(current_user)
response = client.delete(url, headers=headers)
assert response.status_code == status_code

@pytest.mark.parametrize(
["citation_id", "data", "status_code"],
Expand Down Expand Up @@ -117,7 +221,7 @@ class TestCitationsScreeningsResource:
["params", "num_exp"],
[
({"citation_id": 1}, 1),
({"user_id": 2}, 3),
({"user_id": 2}, 4),
({"review_id": 2}, 2),
({"review_id": 2, "user_id": 3}, 1),
],
Expand Down

0 comments on commit de0d81c

Please sign in to comment.