Skip to content

Commit 07e9a1a

Browse files
committed
feat: Add unit tests and small fixes to security
1 parent 929f36c commit 07e9a1a

File tree

12 files changed

+1709
-2
lines changed

12 files changed

+1709
-2
lines changed

asknews_sdk/api/stories.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def get_story(
135135
max_articles: int = 5,
136136
reddit: int = 0,
137137
citation_method: Literal["brackets", "urls", "none"] = "brackets",
138+
condense_auxillary_updates: bool = False,
138139
) -> StoryResponse:
139140
"""
140141
Get a single news story given the ID.
@@ -151,6 +152,10 @@ def get_story(
151152
:type max_articles: int
152153
:param reddit: Amount of reddit threads to include per update.
153154
:type reddit: int
155+
:param citation_method: The citation method.
156+
:type citation_method: Literal["brackets", "urls", "none"]
157+
:param condense_auxillary_updates: Whether to condense auxillary updates.
158+
:type condense_auxillary_updates: bool
154159
:return: The story response.
155160
:rtype: StoryResponse
156161
"""
@@ -163,6 +168,7 @@ def get_story(
163168
"max_articles": max_articles,
164169
"reddit": reddit,
165170
"citation_method": citation_method,
171+
"condense_auxillary_updates": condense_auxillary_updates,
166172
},
167173
params={"story_id": story_id},
168174
accept=[(StoryResponse.__content_type__, 1.0)],

asknews_sdk/security.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,11 @@ def sync_auth_flow(self, request: Request) -> Generator[Request, Response, None]
146146

147147
yield self.inject_headers(request)
148148

149-
if self._token_save_hook and inspect.isfunction(self._token_save_hook):
149+
if (
150+
self._token_save_hook
151+
and inspect.isfunction(self._token_save_hook)
152+
and not inspect.iscoroutinefunction(self._token_save_hook)
153+
):
150154
with self._token_lock:
151155
self._token_save_hook(self.token.token_info)
152156

poetry.lock

Lines changed: 39 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ pre-commit = "^3.3.2"
2626
gitlint = "^0.19.1"
2727
commitizen = "^3.25.0"
2828
respx = "^0.21.1"
29+
polyfactory = "^2.16.0"
2930

3031
[tool.ruff]
3132
line-length = 100
33+
exclude = ["tests"]
3234

3335
[tool.ruff.lint]
3436
select = ["E", "W", "F", "I", "C", "B"]

tests/api/test_analytics.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from datetime import datetime, timedelta
2+
from urllib.parse import parse_qs
3+
4+
import pytest
5+
from polyfactory.factories.pydantic_factory import ModelFactory
6+
from respx import MockRouter
7+
8+
from asknews_sdk.api.analytics import AnalyticsAPI, AsyncAnalyticsAPI
9+
from asknews_sdk.client import APIClient, AsyncAPIClient
10+
from asknews_sdk.dto.sentiment import FinanceResponse
11+
12+
13+
class MockFinanceResponse(ModelFactory[FinanceResponse]):
14+
...
15+
16+
17+
@pytest.fixture
18+
def sync_analytics_api(sync_api_client: APIClient):
19+
return AnalyticsAPI(sync_api_client)
20+
21+
22+
@pytest.fixture
23+
def async_analytics_api(async_api_client: AsyncAPIClient):
24+
return AsyncAnalyticsAPI(async_api_client)
25+
26+
27+
def test_sync_analytics_api_get_asset_sentiment(
28+
sync_analytics_api: AnalyticsAPI, response_mock: MockRouter
29+
):
30+
asset = "bitcoin"
31+
date_from = datetime.now() - timedelta(days=1)
32+
date_to = datetime.now()
33+
mock_response = MockFinanceResponse.build()
34+
35+
response_mock.get("/v1/analytics/finance/sentiment").respond(content=mock_response.model_dump_json())
36+
37+
response = sync_analytics_api.get_asset_sentiment(asset, date_from=date_from, date_to=date_to)
38+
39+
assert isinstance(response, FinanceResponse)
40+
assert response.__content_type__ == mock_response.__content_type__
41+
assert response.model_dump() == mock_response.model_dump()
42+
43+
assert parse_qs(response_mock.calls.last.request.url.query.decode()) == {
44+
"asset": [asset],
45+
"metric": ["news_positive"], # Default value
46+
"date_from": [date_from.isoformat()],
47+
"date_to": [date_to.isoformat()],
48+
}
49+
50+
51+
async def test_async_analytics_api_get_asset_sentiment(
52+
async_analytics_api: AsyncAnalyticsAPI, response_mock: MockRouter
53+
):
54+
asset = "bitcoin"
55+
date_from = datetime.now() - timedelta(days=1)
56+
date_to = datetime.now()
57+
mock_response = MockFinanceResponse.build()
58+
59+
response_mock.get("/v1/analytics/finance/sentiment").respond(content=mock_response.model_dump_json())
60+
61+
response = await async_analytics_api.get_asset_sentiment(
62+
asset, date_from=date_from, date_to=date_to
63+
)
64+
65+
assert isinstance(response, FinanceResponse)
66+
assert response.__content_type__ == mock_response.__content_type__
67+
assert response.model_dump() == mock_response.model_dump()
68+
69+
assert parse_qs(response_mock.calls.last.request.url.query.decode()) == {
70+
"asset": [asset],
71+
"metric": ["news_positive"], # Default value
72+
"date_from": [date_from.isoformat()],
73+
"date_to": [date_to.isoformat()],
74+
}

0 commit comments

Comments
 (0)