arxplorer / tests /test_papers.py
Subhadeep Mandal
Fresh deploy
54eb2ce
Raw
History Blame Contribute Delete
5.2 kB
import asyncio
from sqlalchemy import select
from src.database.db import session_pool
from src.model import Paper
def build_paper_payload(**overrides):
payload = {
"title": "Attention Is All You Need",
"abstract": "Transformers replace recurrence with attention.",
"authors": "A. Researcher, B. Scientist",
"arxiv_id": "1706.03762",
"pdf_url": "https://example.com/papers/attention.pdf",
"paper_url": "https://arxiv.org/abs/1706.03762",
"github_url": "https://github.com/example/attention",
"topics": "transformers, attention",
"published_date": "2017-06-12",
"institution": "Example Lab",
"date_published": "2017-06-12",
"paper_source": "arxiv",
}
payload.update(overrides)
return payload
def test_list_papers_returns_empty_list(client, create_authenticated_user):
auth_user = create_authenticated_user()
response = client.get("/api/v1/papers/", headers=auth_user["headers"])
assert response.status_code == 200
assert response.json() == []
def test_create_paper_and_fetch_by_id(
client, create_authenticated_user, external_service_spies
):
auth_user = create_authenticated_user()
create_response = client.post(
"/api/v1/papers/",
headers=auth_user["headers"],
json=build_paper_payload(),
)
assert create_response.status_code == 200
created_paper = create_response.json()
assert created_paper["title"] == "Attention Is All You Need"
assert created_paper["thumbnail_url"] == "https://thumbs.example/1.png"
assert external_service_spies["background_index"]
get_response = client.get(
f"/api/v1/papers/{created_paper['id']}",
headers=auth_user["headers"],
)
assert get_response.status_code == 200
assert get_response.json()["arxiv_id"] == "1706.03762"
def test_protected_paper_route_rejects_invalid_token(client):
response = client.get(
"/api/v1/papers/",
headers={"Authorization": "Bearer not-a-real-token"},
)
assert response.status_code == 401
assert response.json()["detail"] == "Could not validate credentials"
def test_create_paper_rejects_duplicate_arxiv_id(client, create_authenticated_user):
first_user = create_authenticated_user()
second_user = create_authenticated_user()
first_response = client.post(
"/api/v1/papers/",
headers=first_user["headers"],
json=build_paper_payload(),
)
assert first_response.status_code == 200
duplicate_response = client.post(
"/api/v1/papers/",
headers=second_user["headers"],
json=build_paper_payload(title="Duplicate title"),
)
assert duplicate_response.status_code == 400
assert duplicate_response.json()["detail"] == "Paper already exists"
def test_thumbnail_generation_failure_is_non_fatal(
client, create_authenticated_user, monkeypatch
):
auth_user = create_authenticated_user()
async def failing_thumbnail(*args, **kwargs):
raise RuntimeError("thumbnail failed")
monkeypatch.setattr(
"src.controller.paper.generate_first_page_thumbnail", failing_thumbnail
)
response = client.post(
"/api/v1/papers/",
headers=auth_user["headers"],
json=build_paper_payload(arxiv_id="2401.00001"),
)
assert response.status_code == 200
assert response.json()["thumbnail_url"] is None
def test_fetching_other_users_paper_returns_404(
client, create_authenticated_user, create_paper_record
):
owner = create_authenticated_user()
stranger = create_authenticated_user()
paper = create_paper_record(user_id=owner["id"], arxiv_id="2401.00002")
response = client.get(
f"/api/v1/papers/{paper['id']}",
headers=stranger["headers"],
)
assert response.status_code == 404
assert response.json()["detail"] == "Paper not found"
def test_delete_paper_is_non_fatal_when_cleanup_fails(
client, create_authenticated_user, create_paper_record, monkeypatch
):
auth_user = create_authenticated_user()
paper = create_paper_record(user_id=auth_user["id"], arxiv_id="2401.00003")
async def failing_cleanup(arxiv_ids):
raise RuntimeError("cleanup failed")
monkeypatch.setattr(
"src.controller.paper.IngestionEngine.delete_paper_using_paper_ids",
failing_cleanup,
)
response = client.delete(
f"/api/v1/papers/{paper['id']}",
headers=auth_user["headers"],
)
assert response.status_code == 204
async def _load_paper():
async with session_pool() as session:
return (
await session.execute(select(Paper).where(Paper.id == paper["id"]))
).scalar_one_or_none()
assert asyncio.run(_load_paper()) is None
def test_bulk_delete_returns_404_for_missing_papers(client, create_authenticated_user):
auth_user = create_authenticated_user()
response = client.delete(
"/api/v1/papers/bulk?paper_ids=999&paper_ids=1000",
headers=auth_user["headers"],
)
assert response.status_code == 404
assert "Papers not found" in response.json()["detail"]