Skip to content

Commit

Permalink
Merge pull request #1 from dunderrrrrr/pytest
Browse files Browse the repository at this point in the history
Add pytest and workflow
  • Loading branch information
dunderrrrrr authored Jul 18, 2024
2 parents 83e7a60 + 714fa0a commit be6a6ad
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 14 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Push
on: [push]

jobs:
pytest:
strategy:
fail-fast: false
matrix:
python-version: [3.12]
poetry-version: [1.8.3]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Run image
uses: abatilo/[email protected]
with:
poetry-version: ${{ matrix.poetry-version }}
- name: Install dependencies
run: poetry install
- name: Run tests
run: poetry run pytest
ruff:
strategy:
fail-fast: false
matrix:
python-version: [3.12]
poetry-version: [1.8.3]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Run image
uses: abatilo/[email protected]
with:
poetry-version: ${{ matrix.poetry-version }}
- name: Install dependencies
run: poetry install
- name: Check ruff
run: poetry run ruff check .
13 changes: 6 additions & 7 deletions blocket_api/blocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ class Region(Enum):
BASE_URL = "https://api.blocket.se"


class APIError(Exception):
...
class APIError(Exception): ...


class LimitError(Exception): ...


def _make_request(*, url, token: str, raise_for_status: bool = True) -> Response:
Expand Down Expand Up @@ -101,7 +103,7 @@ def get_listings(self, search_id: int | None = None, limit: int = 99) -> dict:
Retrieve listings/ads based on the provided search criteria.
"""
if limit > 99:
raise AssertionError("Limit cannot be greater than 99.")
raise LimitError("Limit cannot be greater than 99.")

if search_id:
return self._for_search_id(search_id, limit)
Expand All @@ -119,10 +121,7 @@ def custom_search(
Supply a region for filtering. Default is all of Sweden.
"""
if limit > 99:
raise AssertionError("Limit cannot be greater than 99.")

if not search_query:
raise AssertionError("A search query is required.")
raise LimitError("Limit cannot be greater than 99.")

return _make_request(
url=f"{BASE_URL}/search_bff/v2/content?lim={limit}&q={search_query}&r={region.value}&status=active",
Expand Down
109 changes: 102 additions & 7 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ httpx = "^0.27.0"
python = "^3.10"
pre-commit = "^3.7.1"
ruff = "^0.5.2"
pytest = "^8.2.2"
respx = "^0.21.1"

[project.urls]
Homepage = "https://github.com/dunderrrrrr/blocket_api"
Expand All @@ -20,3 +22,9 @@ Issues = "https://github.com/dunderrrrrr/blocket_api/issues"
[build-system]
build-backend = "poetry.core.masonry.api"
requires = ["poetry-core"]


[tool.pytest.ini_options]
testpaths = [
"tests/*",
]
Empty file added tests/__init__.py
Empty file.
20 changes: 20 additions & 0 deletions tests/assertions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pytest
from blocket_api.blocket import BlocketAPI, LimitError

api = BlocketAPI("token")


def test_limit_errors():
with pytest.raises(LimitError):
api.get_listings(limit=100)

with pytest.raises(LimitError):
api.custom_search("saab", limit=100)


def test_typeerrors():
with pytest.raises(TypeError):
api.custom_search() # missing search query

with pytest.raises(TypeError):
BlocketAPI()
28 changes: 28 additions & 0 deletions tests/requests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import respx
import pytest
from httpx import Response
from blocket_api.blocket import BASE_URL, APIError, BlocketAPI, _make_request

api = BlocketAPI("token")


def test_make_request_no_raise():
_make_request(url=f"{BASE_URL}/not_found", token="token", raise_for_status=False)


@respx.mock
def test_make_request_raise_404():
respx.get(f"{BASE_URL}/not_found").mock(
return_value=Response(status_code=404),
)
with pytest.raises(APIError):
_make_request(url=f"{BASE_URL}/not_found", token="token", raise_for_status=True)


@respx.mock
def test_make_request_raise_401():
respx.get(f"{BASE_URL}/unauthorized").mock(
return_value=Response(status_code=401),
)
with pytest.raises(APIError):
_make_request(url=f"{BASE_URL}/unauthorized", token="token")
63 changes: 63 additions & 0 deletions tests/searches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import respx
from httpx import Response
from blocket_api.blocket import BASE_URL, BlocketAPI, Region

api = BlocketAPI("token")


@respx.mock
def test_saved_searches():
"""
Make sure mobility saved searches are merged with v2/searches.
"""
respx.get(f"{BASE_URL}/saved/v2/searches").mock(
return_value=Response(
status_code=200,
json={
"data": [
{"id": "1", "name": '"buggy", Bilar säljes i hela Sverige'},
{"id": "2", "name": "Cyklar säljes i flera kommuner"},
],
},
),
)
respx.get(f"{BASE_URL}/mobility-saved-searches/v1/searches").mock(
return_value=Response(
status_code=200,
json={"data": [{"id": "3", "name": "Bilar säljes i hela Sverige"}]},
),
)
assert api.saved_searches() == [
{"id": "1", "name": '"buggy", Bilar säljes i hela Sverige'},
{"id": "2", "name": "Cyklar säljes i flera kommuner"},
{"id": "3", "name": "Bilar säljes i hela Sverige"},
]


@respx.mock
def test_for_search_id():
respx.get(f"{BASE_URL}/saved/v2/searches_content/123?lim=99").mock(
return_value=Response(status_code=200, json={"data": "listings-data"}),
)
assert api.get_listings(search_id=123) == {"data": "listings-data"}


@respx.mock
def test_for_search_id_mobility():
respx.get(f"{BASE_URL}/saved/v2/searches_content/123?lim=99").mock(
return_value=Response(status_code=404),
)
respx.get(f"{BASE_URL}/mobility-saved-searches/v1/searches/123/ads?lim=99").mock(
return_value=Response(status_code=200, json={"data": "mobility-data"}),
)
assert api.get_listings(search_id=123) == {"data": "mobility-data"}


@respx.mock
def test_custom_search():
respx.get(
f"{BASE_URL}/search_bff/v2/content?lim=99&q=saab&r=20&status=active"
).mock(
return_value=Response(status_code=200, json={"data": {"location": "halland"}}),
)
api.custom_search("saab", Region.halland)

0 comments on commit be6a6ad

Please sign in to comment.