File size: 3,707 Bytes
7acf89d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
"""
Tests for 3c UniProt search polish:

- reviewed/organism filters are folded into the UniProt query string
- search results carry a `reviewed` flag derived from entryType

Network calls are mocked; these run fully offline.
"""

import pytest
from fastapi import HTTPException

from app.routers import uniprot as uniprot_router
from app.routers.uniprot import UniprotSearchRequest, search_uniprot


class FakeResp:
    def __init__(self, status_code, json_data):
        self.status_code = status_code
        self._json = json_data

    def json(self):
        return self._json


class FakeClient:
    def __init__(self, *args, **kwargs):
        self.calls = []

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        return None

    async def get(self, url, params=None, **kwargs):
        self.calls.append((url, params))
        results = []
        for i in range(params.get("size", 1)):
            results.append({
                "primaryAccession": f"P{i:05d}",
                "proteinDescription": {"recommendedName": {"fullName": {"value": "Test protein"}}},
                "genes": [{"geneName": {"value": "TP53"}}],
                "organism": {"scientificName": "Homo sapiens"},
                "sequence": {"length": 100},
                "entryType": "UniProtKB reviewed (Swiss-Prot)",
            })
        return FakeResp(200, {"results": results})


@pytest.mark.asyncio
async def test_reviewed_and_organism_fold_into_query(monkeypatch):
    fake = FakeClient()
    monkeypatch.setattr(uniprot_router.httpx, "AsyncClient", lambda *a, **k: fake)
    req = UniprotSearchRequest(query="p53", max_results=1, reviewed=True, organism="Homo sapiens")
    res = await search_uniprot(req)
    assert res["count"] == 1
    assert res["results"][0]["reviewed"] is True
    _, params = fake.calls[0]
    assert "AND organism_name:\"Homo sapiens\"" in params["query"]
    assert "AND reviewed:true" in params["query"]


@pytest.mark.asyncio
async def test_no_filters_query_unchanged(monkeypatch):
    fake = FakeClient()
    monkeypatch.setattr(uniprot_router.httpx, "AsyncClient", lambda *a, **k: fake)
    req = UniprotSearchRequest(query="BRCA1")
    res = await search_uniprot(req)
    assert res["results"][0]["reviewed"] is True
    _, params = fake.calls[0]
    assert params["query"] == "BRCA1"


@pytest.mark.asyncio
async def test_reviewed_flag_false_for_trembl(monkeypatch):
    class FakeClientTrEmbl(FakeClient):
        async def get(self, url, params=None, **kwargs):
            self.calls.append((url, params))
            return FakeResp(200, {"results": [{
                "primaryAccession": "A0A1111111",
                "proteinDescription": {},
                "genes": [],
                "organism": {"scientificName": "Unknown"},
                "sequence": {"length": 50},
                "entryType": "UniProtKB unreviewed (TrEMBL)",
            }]})

    fake = FakeClientTrEmbl()
    monkeypatch.setattr(uniprot_router.httpx, "AsyncClient", lambda *a, **k: fake)
    req = UniprotSearchRequest(query="hypothetical")
    res = await search_uniprot(req)
    assert res["results"][0]["reviewed"] is False


@pytest.mark.asyncio
async def test_search_failure_raises_502(monkeypatch):
    class FakeClientFail(FakeClient):
        async def get(self, url, params=None, **kwargs):
            self.calls.append((url, params))
            return FakeResp(500, {})

    fake = FakeClientFail()
    monkeypatch.setattr(uniprot_router.httpx, "AsyncClient", lambda *a, **k: fake)
    with pytest.raises(HTTPException) as exc:
        await search_uniprot(UniprotSearchRequest(query="p53"))
    assert exc.value.status_code == 502