first ruggedy draft
This commit is contained in:
123
tests/test_paypal_connector.py
Normal file
123
tests/test_paypal_connector.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
from mousehold_agent.paypal_connector import (
|
||||
PayPalAPIError,
|
||||
PayPalConfig,
|
||||
_paypal_error_message,
|
||||
_token_payload_to_auth_check,
|
||||
paypal_transaction_to_observation,
|
||||
paypal_transaction_to_preview,
|
||||
)
|
||||
from mousehold_agent.paypal_connector import _validate_date_range as validate_date_range
|
||||
|
||||
|
||||
def test_paypal_negative_transaction_becomes_confirmed_expense() -> None:
|
||||
observation = paypal_transaction_to_observation(
|
||||
{
|
||||
"transaction_info": {
|
||||
"transaction_id": "PAYPAL-001",
|
||||
"transaction_initiation_date": "2026-06-20T12:30:00Z",
|
||||
"transaction_updated_date": "2026-06-20T12:31:00Z",
|
||||
"transaction_amount": {"currency_code": "EUR", "value": "-18.99"},
|
||||
"transaction_status": "S",
|
||||
"transaction_subject": "Payment to Example Merchant",
|
||||
},
|
||||
"payer_info": {"email_address": "merchant@example.test"},
|
||||
},
|
||||
household_id="household-1",
|
||||
source_account_id="account-1",
|
||||
owner_user_id="user-1",
|
||||
)
|
||||
|
||||
assert observation["source_type"] == "paypal_api"
|
||||
assert observation["provider_transaction_id"] == "PAYPAL-001"
|
||||
assert observation["event_type"] == "expense"
|
||||
assert observation["status"] == "confirmed"
|
||||
assert observation["amount"] == "18.99"
|
||||
assert observation["event_date"] == "2026-06-20"
|
||||
|
||||
|
||||
def test_paypal_positive_transaction_becomes_income() -> None:
|
||||
observation = paypal_transaction_to_observation(
|
||||
{
|
||||
"transaction_info": {
|
||||
"transaction_id": "PAYPAL-002",
|
||||
"transaction_initiation_date": "2026-06-21T09:10:00+0000",
|
||||
"transaction_amount": {"currency_code": "EUR", "value": "42.50"},
|
||||
"transaction_status": "S",
|
||||
},
|
||||
"payer_info": {
|
||||
"payer_name": {"given_name": "Alice", "surname": "Example"},
|
||||
},
|
||||
},
|
||||
household_id="household-1",
|
||||
source_account_id="account-1",
|
||||
owner_user_id="user-1",
|
||||
)
|
||||
|
||||
assert observation["event_type"] == "income"
|
||||
assert observation["amount"] == "42.50"
|
||||
assert observation["counterparty"] == "Alice Example"
|
||||
|
||||
|
||||
def test_paypal_pending_transaction_preview_is_announced() -> None:
|
||||
preview = paypal_transaction_to_preview(
|
||||
{
|
||||
"transaction_info": {
|
||||
"transaction_id": "PAYPAL-003",
|
||||
"transaction_initiation_date": "2026-06-22T09:10:00Z",
|
||||
"transaction_amount": {"currency_code": "EUR", "value": "-10.00"},
|
||||
"transaction_status": "P",
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
assert preview["status"] == "announced"
|
||||
assert preview["event_type"] == "expense"
|
||||
|
||||
|
||||
def test_paypal_date_range_is_limited_to_31_days() -> None:
|
||||
with pytest.raises(PayPalAPIError):
|
||||
validate_date_range(date(2026, 6, 1), date(2026, 7, 2))
|
||||
|
||||
|
||||
def test_paypal_not_authorized_error_mentions_transaction_search_scope() -> None:
|
||||
message = _paypal_error_message(
|
||||
403,
|
||||
'{"name":"NOT_AUTHORIZED","message":"Authorization failed due to insufficient permissions."}',
|
||||
)
|
||||
|
||||
assert "Transaction Search" in message
|
||||
assert "https://uri.paypal.com/services/reporting/search/read" in message
|
||||
|
||||
|
||||
def test_paypal_auth_check_reports_missing_transaction_search_scope() -> None:
|
||||
check = _token_payload_to_auth_check(
|
||||
PayPalConfig(client_id="client", client_secret="secret", environment="sandbox"),
|
||||
{
|
||||
"scope": "openid https://uri.paypal.com/services/invoicing",
|
||||
"token_type": "Bearer",
|
||||
"app_id": "APP-123",
|
||||
"expires_in": 3600,
|
||||
},
|
||||
)
|
||||
|
||||
assert check["app_id"] == "APP-123"
|
||||
assert check["environment"] == "sandbox"
|
||||
assert check["has_transaction_search"] is False
|
||||
|
||||
|
||||
def test_paypal_auth_check_parses_comma_separated_scope_text() -> None:
|
||||
check = _token_payload_to_auth_check(
|
||||
PayPalConfig(client_id="client", client_secret="secret", environment="sandbox"),
|
||||
{
|
||||
"scope": "openid,https://uri.paypal.com/services/reporting/search/read",
|
||||
"token_type": "Bearer",
|
||||
},
|
||||
)
|
||||
|
||||
assert check["has_transaction_search"] is True
|
||||
assert "https://uri.paypal.com/services/reporting/search/read" in check["scopes"]
|
||||
Reference in New Issue
Block a user