feat: Add Booklooker client configuration and exception handling
- Introduced BooklookerConfig class for runtime configuration management. - Created custom exceptions for API errors, including authentication and validation errors. - Generated API contracts from OpenAPI specification, including endpoints and security schemes. - Implemented models for articles, orders, and webhooks to facilitate data handling. - Developed a webhook helper for processing and enriching webhook events. - Added tests for configuration defaults, token expiration, and webhook enrichment.
This commit is contained in:
commit
1d8ee1bba6
21 changed files with 3009 additions and 0 deletions
27
tests/test_models.py
Normal file
27
tests/test_models.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
from booklooker_client import BooklookerConfig, SyncBooklookerClient
|
||||
from booklooker_client.models import ArticleField, ArticleList, ArticleListItem, AuthToken
|
||||
|
||||
|
||||
def test_config_defaults() -> None:
|
||||
config = BooklookerConfig(api_key="demo")
|
||||
assert config.base_url == "https://api.booklooker.de/2.0"
|
||||
assert config.timeout > 0
|
||||
|
||||
|
||||
def test_auth_token_not_immediately_expired() -> None:
|
||||
token = AuthToken(token="abc", expires_after_seconds=600)
|
||||
assert token.expired is False
|
||||
|
||||
|
||||
def test_article_list_model() -> None:
|
||||
article_list = ArticleList(items=[ArticleListItem(value="ABC-1")], field=ArticleField.ORDER_NO)
|
||||
assert article_list.items[0].value == "ABC-1"
|
||||
|
||||
|
||||
def test_client_exposes_generated_endpoints() -> None:
|
||||
client = SyncBooklookerClient(BooklookerConfig(api_key="demo"))
|
||||
try:
|
||||
assert "POST /authenticate" in client.available_endpoints
|
||||
assert "GET /order" in client.available_endpoints
|
||||
finally:
|
||||
client.close()
|
||||
41
tests/test_webhooks.py
Normal file
41
tests/test_webhooks.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
from booklooker_client import BooklookerWebhookHelper
|
||||
from booklooker_client.models.order import OrderBatch, OrderRecord
|
||||
|
||||
|
||||
class FakeClient:
|
||||
def get_orders(self, *, order_id=None, date=None, date_from=None, date_to=None):
|
||||
return OrderBatch(orders=[OrderRecord(orderId=order_id, buyerUsername="alice")])
|
||||
|
||||
def get_article_status(self, order_no: str):
|
||||
class _Result:
|
||||
def model_dump(self, mode="json"):
|
||||
return {"order_no": order_no, "status": "ACTIVE"}
|
||||
|
||||
return _Result()
|
||||
|
||||
|
||||
def test_webhook_helper_enriches_order_payload() -> None:
|
||||
helper = BooklookerWebhookHelper()
|
||||
event = helper.enrich_with_client(
|
||||
{
|
||||
"event_type": "order.created",
|
||||
"event_id": "evt-1",
|
||||
"orderId": 1234,
|
||||
},
|
||||
FakeClient(),
|
||||
)
|
||||
|
||||
assert event.resource_type == "order"
|
||||
assert event.resource_id == "1234"
|
||||
assert event.enriched_data is not None
|
||||
assert event.enriched_data["orders"][0]["buyerUsername"] == "alice"
|
||||
|
||||
|
||||
def test_duplicate_detection() -> None:
|
||||
helper = BooklookerWebhookHelper()
|
||||
first = helper.enrich_with_client({"event_type": "order.created", "event_id": "evt-2", "orderId": 99}, FakeClient())
|
||||
second = helper.enrich_with_client({"event_type": "order.created", "event_id": "evt-2", "orderId": 99}, FakeClient())
|
||||
|
||||
assert first.resource_type == "order"
|
||||
assert second.resource_type == "duplicate"
|
||||
assert second.enriched_data == {"duplicate": True}
|
||||
Loading…
Add table
Add a link
Reference in a new issue