Intermediate commit

This commit is contained in:
Justin Visser 2026-02-26 16:09:57 +01:00
parent 0e9e49df16
commit 3d4cfeff1a
65 changed files with 5507 additions and 333 deletions

View file

@ -0,0 +1,126 @@
from __future__ import annotations
from types import SimpleNamespace
import pytest
from app.services.domains.arxiv import application as arxiv_application
from app.services.domains.arxiv import gateway as arxiv_gateway
from app.services.domains.arxiv.types import ArxivEntry, ArxivFeed, ArxivOpenSearchMeta
from app.settings import settings
def _item(*, title: str = "A Test Paper", scholar_label: str = "Ada Lovelace") -> SimpleNamespace:
return SimpleNamespace(title=title, scholar_label=scholar_label)
def test_get_arxiv_gateway_returns_cached_instance() -> None:
previous = arxiv_gateway.set_arxiv_gateway(None)
try:
first = arxiv_gateway.get_arxiv_gateway()
second = arxiv_gateway.get_arxiv_gateway()
assert first is second
finally:
arxiv_gateway.set_arxiv_gateway(previous)
@pytest.mark.asyncio
async def test_application_discover_uses_gateway_override() -> None:
class FakeGateway:
def __init__(self) -> None:
self.calls: list[tuple[object, str | None, float | None]] = []
async def discover_arxiv_id_for_publication(
self,
*,
item,
request_email: str | None = None,
timeout_seconds: float | None = None,
max_results: int | None = None,
) -> str | None:
self.calls.append((item, request_email, timeout_seconds))
return "1234.5678"
fake_gateway = FakeGateway()
previous = arxiv_gateway.set_arxiv_gateway(fake_gateway)
try:
result = await arxiv_application.discover_arxiv_id_for_publication(
item=_item(),
request_email="user@example.com",
timeout_seconds=7.0,
)
assert result == "1234.5678"
assert fake_gateway.calls
assert fake_gateway.calls[0][1] == "user@example.com"
assert fake_gateway.calls[0][2] == 7.0
finally:
arxiv_gateway.set_arxiv_gateway(previous)
@pytest.mark.asyncio
async def test_http_gateway_returns_none_when_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
class FakeClient:
def __init__(self) -> None:
self.calls = 0
async def search(self, **kwargs):
self.calls += 1
return ArxivFeed()
previous_enabled = bool(settings.arxiv_enabled)
fake_client = FakeClient()
object.__setattr__(settings, "arxiv_enabled", False)
try:
gateway = arxiv_gateway.HttpArxivGateway(client=fake_client)
result = await gateway.discover_arxiv_id_for_publication(item=_item())
assert result is None
assert fake_client.calls == 0
finally:
object.__setattr__(settings, "arxiv_enabled", previous_enabled)
@pytest.mark.asyncio
async def test_http_gateway_uses_client_search_for_discovery() -> None:
class FakeClient:
def __init__(self) -> None:
self.calls: list[dict] = []
async def search(self, **kwargs):
self.calls.append(kwargs)
return ArxivFeed(
entries=[
ArxivEntry(
entry_id_url="https://arxiv.org/abs/1234.5678v1",
arxiv_id="1234.5678v1",
title="Paper",
summary="",
published=None,
updated=None,
)
],
opensearch=ArxivOpenSearchMeta(total_results=1, start_index=0, items_per_page=1),
)
fake_client = FakeClient()
gateway = arxiv_gateway.HttpArxivGateway(client=fake_client)
result = await gateway.discover_arxiv_id_for_publication(
item=_item(title="My Paper", scholar_label="Ada Lovelace"),
request_email="user@example.com",
timeout_seconds=2.0,
max_results=4,
)
assert result == "1234.5678v1"
assert fake_client.calls
first_call = fake_client.calls[0]
assert first_call["query"] == 'ti:"My Paper" AND au:"lovelace"'
assert first_call["request_email"] == "user@example.com"
assert first_call["timeout_seconds"] == 2.0
assert first_call["max_results"] == 4
def test_build_arxiv_query_normalizes_noisy_mojibake_title() -> None:
noisy = " Graph–Neural Networks Survey "
clean = "Graph Neural Networks Survey"
assert arxiv_gateway.build_arxiv_query(noisy, None) == arxiv_gateway.build_arxiv_query(clean, None)