mirror of
https://github.com/bellingcat/auto-archiver-api.git
synced 2026-06-12 21:48:35 +03:00
Format and lint the tests directory (#58)
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import json
|
||||
from http import HTTPStatus
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from app.shared import schemas
|
||||
from app.shared.db import worker_crud
|
||||
from app.shared.schemas import ArchiveCreate, TaskResult
|
||||
from app.web.config import ALLOW_ANY_EMAIL
|
||||
|
||||
@@ -13,7 +16,9 @@ def test_archive_url_unauthenticated(client, test_no_auth):
|
||||
@patch("app.web.endpoints.url.celery", return_value=MagicMock())
|
||||
def test_archive_url(m_celery, m2, client_with_auth):
|
||||
m_signature = MagicMock()
|
||||
m_signature.apply_async.return_value = TaskResult(id="123-456-789", status="PENDING", result="")
|
||||
m_signature.apply_async.return_value = TaskResult(
|
||||
id="123-456-789", status="PENDING", result=""
|
||||
)
|
||||
m_celery.signature.return_value = m_signature
|
||||
|
||||
m_user_state = MagicMock()
|
||||
@@ -21,62 +26,98 @@ def test_archive_url(m_celery, m2, client_with_auth):
|
||||
|
||||
# url is too short
|
||||
response = client_with_auth.post("/url/archive", json={"url": "bad"})
|
||||
assert response.status_code == 422
|
||||
assert response.json()["detail"][0]["msg"] == 'String should have at least 5 characters'
|
||||
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
|
||||
assert (
|
||||
response.json()["detail"][0]["msg"]
|
||||
== "String should have at least 5 characters"
|
||||
)
|
||||
m_celery.signature.assert_not_called()
|
||||
|
||||
# url is invalid
|
||||
response = client_with_auth.post("/url/archive", json={"url": "example.com"})
|
||||
assert response.status_code == 400
|
||||
response = client_with_auth.post(
|
||||
"/url/archive", json={"url": "example.com"}
|
||||
)
|
||||
assert response.status_code == HTTPStatus.BAD_REQUEST
|
||||
assert response.json()["detail"] == "Invalid URL received."
|
||||
|
||||
# valid request
|
||||
m_user_state.has_quota_max_monthly_urls.return_value = True
|
||||
m_user_state.has_quota_max_monthly_mbs.return_value = True
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com"})
|
||||
assert response.status_code == 201
|
||||
assert response.json() == {'id': '123-456-789'}
|
||||
response = client_with_auth.post(
|
||||
"/url/archive", json={"url": "https://example.com"}
|
||||
)
|
||||
assert response.status_code == HTTPStatus.CREATED
|
||||
assert response.json() == {"id": "123-456-789"}
|
||||
m_celery.signature.assert_called_once()
|
||||
m_signature.apply_async.assert_called_once()
|
||||
called_val = m_celery.signature.call_args
|
||||
assert called_val[0][0] == "create_archive_task"
|
||||
assert json.loads(called_val[1]['args'][0]) == {"id": None, "url": "https://example.com", "result": None, "public": False, "author_id": "rick@example.com", "group_id": "default", "tags": None, "sheet_id": None, "store_until": None, "urls": None}
|
||||
assert json.loads(called_val[1]["args"][0]) == {
|
||||
"id": None,
|
||||
"url": "https://example.com",
|
||||
"result": None,
|
||||
"public": False,
|
||||
"author_id": "rick@example.com",
|
||||
"group_id": "default",
|
||||
"tags": None,
|
||||
"sheet_id": None,
|
||||
"store_until": None,
|
||||
"urls": None,
|
||||
}
|
||||
m_user_state.has_quota_max_monthly_urls.assert_called_once()
|
||||
m_user_state.has_quota_max_monthly_mbs.assert_called_once()
|
||||
m_user_state.in_group.assert_called_once_with("default")
|
||||
|
||||
# user is not in group
|
||||
m_user_state.in_group.return_value = False
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com", "group_id": "new-group"})
|
||||
assert response.status_code == 403
|
||||
assert response.json()["detail"] == "User does not have access to this group."
|
||||
response = client_with_auth.post(
|
||||
"/url/archive",
|
||||
json={"url": "https://example.com", "group_id": "new-group"},
|
||||
)
|
||||
assert response.status_code == HTTPStatus.FORBIDDEN
|
||||
assert (
|
||||
response.json()["detail"] == "User does not have access to this group."
|
||||
)
|
||||
m_user_state.in_group.assert_called_with("new-group")
|
||||
|
||||
# user is in group
|
||||
m_user_state.in_group.return_value = True
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com", "group_id": "spaceship"})
|
||||
assert response.status_code == 201
|
||||
assert response.json() == {'id': '123-456-789'}
|
||||
response = client_with_auth.post(
|
||||
"/url/archive",
|
||||
json={"url": "https://example.com", "group_id": "spaceship"},
|
||||
)
|
||||
assert response.status_code == HTTPStatus.CREATED
|
||||
assert response.json() == {"id": "123-456-789"}
|
||||
assert m_celery.signature.call_count == 2
|
||||
assert m_signature.apply_async.call_count == 2
|
||||
called_val = m_celery.signature.call_args
|
||||
assert json.loads(called_val[1]['args'][0])["group_id"] == "spaceship"
|
||||
assert json.loads(called_val[1]["args"][0])["group_id"] == "spaceship"
|
||||
m_user_state.in_group.assert_called_with("spaceship")
|
||||
|
||||
# user is over monthly URL quota
|
||||
m_user_state.has_quota_max_monthly_urls.return_value = False
|
||||
m_user_state.has_quota_max_monthly_mbs.return_value = True
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com", "group_id": "spaceship"})
|
||||
assert response.status_code == 429
|
||||
assert response.json()["detail"] == "User has reached their monthly URL quota."
|
||||
response = client_with_auth.post(
|
||||
"/url/archive",
|
||||
json={"url": "https://example.com", "group_id": "spaceship"},
|
||||
)
|
||||
assert response.status_code == HTTPStatus.TOO_MANY_REQUESTS
|
||||
assert (
|
||||
response.json()["detail"] == "User has reached their monthly URL quota."
|
||||
)
|
||||
m_user_state.has_quota_max_monthly_urls.assert_called_with("spaceship")
|
||||
|
||||
# user is over monthly MB quota
|
||||
m_user_state.has_quota_max_monthly_urls.return_value = True
|
||||
m_user_state.has_quota_max_monthly_mbs.return_value = False
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com", "group_id": "spacesuit"})
|
||||
assert response.status_code == 429
|
||||
assert response.json()["detail"] == "User has reached their monthly MB quota."
|
||||
response = client_with_auth.post(
|
||||
"/url/archive",
|
||||
json={"url": "https://example.com", "group_id": "spacesuit"},
|
||||
)
|
||||
assert response.status_code == HTTPStatus.TOO_MANY_REQUESTS
|
||||
assert (
|
||||
response.json()["detail"] == "User has reached their monthly MB quota."
|
||||
)
|
||||
m_user_state.has_quota_max_monthly_mbs.assert_called_with("spacesuit")
|
||||
assert m_celery.signature.call_count == 2
|
||||
assert m_signature.apply_async.call_count == 2
|
||||
@@ -89,40 +130,77 @@ def test_archive_url_quotas(m1, client_with_auth):
|
||||
|
||||
# misses on monthly URLs quota
|
||||
m_user_state.has_quota_max_monthly_urls.return_value = False
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com"})
|
||||
assert response.status_code == 429
|
||||
assert response.json()["detail"] == "User has reached their monthly URL quota."
|
||||
response = client_with_auth.post(
|
||||
"/url/archive", json={"url": "https://example.com"}
|
||||
)
|
||||
assert response.status_code == HTTPStatus.TOO_MANY_REQUESTS
|
||||
assert (
|
||||
response.json()["detail"] == "User has reached their monthly URL quota."
|
||||
)
|
||||
m_user_state.has_quota_max_monthly_urls.assert_called_once()
|
||||
|
||||
# misses on monthly MBs quota
|
||||
m_user_state.has_quota_max_monthly_urls.return_value = True
|
||||
m_user_state.has_quota_max_monthly_mbs.return_value = False
|
||||
response = client_with_auth.post("/url/archive", json={"url": "https://example.com"})
|
||||
assert response.status_code == 429
|
||||
assert response.json()["detail"] == "User has reached their monthly MB quota."
|
||||
response = client_with_auth.post(
|
||||
"/url/archive", json={"url": "https://example.com"}
|
||||
)
|
||||
assert response.status_code == HTTPStatus.TOO_MANY_REQUESTS
|
||||
assert (
|
||||
response.json()["detail"] == "User has reached their monthly MB quota."
|
||||
)
|
||||
m_user_state.has_quota_max_monthly_mbs.assert_called_once()
|
||||
|
||||
|
||||
@patch("app.web.endpoints.url.celery", return_value=MagicMock())
|
||||
def test_archive_url_with_api_token(m_celery, client_with_token):
|
||||
m_signature = MagicMock()
|
||||
m_signature.apply_async.return_value = TaskResult(id="123-456-789", status="PENDING", result="")
|
||||
m_signature.apply_async.return_value = TaskResult(
|
||||
id="123-456-789", status="PENDING", result=""
|
||||
)
|
||||
m_celery.signature.return_value = m_signature
|
||||
response = client_with_token.post("/url/archive", json={"url": "https://example.com", "author_id": "someone@example.com"})
|
||||
assert response.status_code == 201
|
||||
assert response.json() == {'id': '123-456-789'}
|
||||
response = client_with_token.post(
|
||||
"/url/archive",
|
||||
json={"url": "https://example.com", "author_id": "someone@example.com"},
|
||||
)
|
||||
assert response.status_code == HTTPStatus.CREATED
|
||||
assert response.json() == {"id": "123-456-789"}
|
||||
m_celery.signature.assert_called_once()
|
||||
m_signature.apply_async.assert_called_once()
|
||||
called_val = m_celery.signature.call_args
|
||||
assert called_val[0][0] == "create_archive_task"
|
||||
assert json.loads(called_val[1]['args'][0]) == {"id": None, "url": "https://example.com", "result": None, "public": False, "author_id": "someone@example.com", "group_id": "default", "tags": None, "sheet_id": None, "store_until": None, "urls": None}
|
||||
assert json.loads(called_val[1]["args"][0]) == {
|
||||
"id": None,
|
||||
"url": "https://example.com",
|
||||
"result": None,
|
||||
"public": False,
|
||||
"author_id": "someone@example.com",
|
||||
"group_id": "default",
|
||||
"tags": None,
|
||||
"sheet_id": None,
|
||||
"store_until": None,
|
||||
"urls": None,
|
||||
}
|
||||
|
||||
# missing id should use ALLOW_ANY_EMAIL
|
||||
response = client_with_token.post("/url/archive", json={"url": "https://example.com", "author_id": None})
|
||||
assert response.status_code == 201
|
||||
response = client_with_token.post(
|
||||
"/url/archive", json={"url": "https://example.com", "author_id": None}
|
||||
)
|
||||
assert response.status_code == HTTPStatus.CREATED
|
||||
called_val = m_celery.signature.call_args
|
||||
assert called_val[0][0] == "create_archive_task"
|
||||
assert json.loads(called_val[1]['args'][0]) == {"id": None, "url": "https://example.com", "result": None, "public": False, "author_id": ALLOW_ANY_EMAIL, "group_id": "default", "tags": None, "sheet_id": None, "store_until": None, "urls": None}
|
||||
assert json.loads(called_val[1]["args"][0]) == {
|
||||
"id": None,
|
||||
"url": "https://example.com",
|
||||
"result": None,
|
||||
"public": False,
|
||||
"author_id": ALLOW_ANY_EMAIL,
|
||||
"group_id": "default",
|
||||
"tags": None,
|
||||
"sheet_id": None,
|
||||
"store_until": None,
|
||||
"urls": None,
|
||||
}
|
||||
|
||||
|
||||
def test_search_by_url_unauthenticated(client, test_no_auth):
|
||||
@@ -132,46 +210,67 @@ def test_search_by_url_unauthenticated(client, test_no_auth):
|
||||
def test_search_by_url(client_with_auth, client_with_token, db_session):
|
||||
# tests the search endpoint, including through some db data for the endpoint params
|
||||
response = client_with_auth.get("/url/search")
|
||||
assert response.status_code == 422
|
||||
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
|
||||
assert response.json()["detail"][0]["msg"] == "Field required"
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com")
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json() == []
|
||||
|
||||
from app.shared import schemas
|
||||
from app.shared.db import worker_crud
|
||||
for i in range(11):
|
||||
worker_crud.create_archive(db_session, ArchiveCreate(id=f"url-456-{i}", url="https://example.com" if i < 10 else "https://something-else.com", result={}, public=True, author_id="rick@example.com"), [], [])
|
||||
worker_crud.create_archive(
|
||||
db_session,
|
||||
ArchiveCreate(
|
||||
id=f"url-456-{i}",
|
||||
url="https://example.com"
|
||||
if i < 10
|
||||
else "https://something-else.com",
|
||||
result={},
|
||||
public=True,
|
||||
author_id="rick@example.com",
|
||||
),
|
||||
[],
|
||||
[],
|
||||
)
|
||||
# NB: this insertion is too fast for the ordering to be correct as they are within the same second
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com")
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert len(j := response.json()) == 10
|
||||
assert "url-456-0" in [i["id"] for i in j]
|
||||
assert "url-456-9" in [i["id"] for i in j]
|
||||
assert "url-456-10" not in [i["id"] for i in j]
|
||||
assert j[0].keys() == schemas.ArchiveResult.model_fields.keys()
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com&limit=5")
|
||||
assert response.status_code == 200
|
||||
response = client_with_auth.get(
|
||||
"/url/search?url=https://example.com&limit=5"
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert len(response.json()) == 5
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com&skip=5&limit=2")
|
||||
assert response.status_code == 200
|
||||
response = client_with_auth.get(
|
||||
"/url/search?url=https://example.com&skip=5&limit=2"
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert len(response.json()) == 2
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com&archived_before=2010-01-01")
|
||||
assert response.status_code == 200
|
||||
response = client_with_auth.get(
|
||||
"/url/search?url=https://example.com&archived_before=2010-01-01"
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert len(response.json()) == 0
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com&archived_after=2010-01-01")
|
||||
assert response.status_code == 200
|
||||
response = client_with_auth.get(
|
||||
"/url/search?url=https://example.com&archived_after=2010-01-01"
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert len(response.json()) == 10
|
||||
|
||||
# API token will also work
|
||||
response = client_with_token.get("/url/search?url=https://example.com&archived_after=2010-01-01")
|
||||
assert response.status_code == 200
|
||||
response = client_with_token.get(
|
||||
"/url/search?url=https://example.com&archived_after=2010-01-01"
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert len(response.json()) == 10
|
||||
|
||||
|
||||
@@ -181,7 +280,7 @@ def test_search_no_read_access(mock_user_state, client_with_auth):
|
||||
mock_user_state.return_value.read_public = False
|
||||
|
||||
response = client_with_auth.get("/url/search?url=https://example.com")
|
||||
assert response.status_code == 403
|
||||
assert response.status_code == HTTPStatus.FORBIDDEN
|
||||
assert response.json() == {"detail": "User does not have read access."}
|
||||
|
||||
|
||||
@@ -191,12 +290,22 @@ def test_delete_task_unauthenticated(client, test_no_auth):
|
||||
|
||||
def test_delete_task(client_with_auth, db_session):
|
||||
response = client_with_auth.delete("/url/delete-123-456-789")
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json() == {"id": "delete-123-456-789", "deleted": False}
|
||||
|
||||
from app.shared.db import worker_crud
|
||||
worker_crud.create_archive(db_session, ArchiveCreate(id="delete-123-456-789", url="https://example.com", result={}, public=True, author_id="morty@example.com"), [], [])
|
||||
worker_crud.create_archive(
|
||||
db_session,
|
||||
ArchiveCreate(
|
||||
id="delete-123-456-789",
|
||||
url="https://example.com",
|
||||
result={},
|
||||
public=True,
|
||||
author_id="morty@example.com",
|
||||
),
|
||||
[],
|
||||
[],
|
||||
)
|
||||
|
||||
response = client_with_auth.delete("/url/delete-123-456-789")
|
||||
assert response.status_code == 200
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json() == {"id": "delete-123-456-789", "deleted": True}
|
||||
|
||||
Reference in New Issue
Block a user