Files
remnawave-minishop/tests/test_payment_http_client.py
3252a8 ce6273a652 fix(payments): apply request timeout changes without restart
PAYMENT_REQUEST_TIMEOUT_SECONDS was read once in each provider's
__init__ and baked into the aiohttp session, so admin overrides
(applied in-process) only took effect after a container restart.
Providers now hand HttpClientMixin a timeout source callable; the
mixin builds the session with the current value and swaps in a fresh
session when the value changes, closing the replaced one only after
any in-flight request on it is bound by its own total timeout.

Also:
- check the Heleket payment-info success flag before reading the
  payload so a non-dict provider response cannot raise in the
  pending-payment reuse path
- add PAYMENT_REQUEST_TIMEOUT_SECONDS to the FreeKassa settings stub
  in test_security.py (fixes three tests broken by the new field)
2026-06-10 11:21:15 +03:00

56 lines
2.2 KiB
Python

import unittest
from types import SimpleNamespace
from bot.payment_providers.shared.http_client import (
HttpClientMixin,
_should_retry_transport_error,
)
class _DummyHttpClient(HttpClientMixin):
def __init__(self, total_timeout=20):
self._init_http_client(total_timeout=total_timeout)
class PaymentHttpClientTests(unittest.IsolatedAsyncioTestCase):
async def test_http_client_tracks_sent_headers_for_safe_retries(self):
client = _DummyHttpClient()
try:
session = await client._get_session()
self.assertFalse(session.connector.force_close)
self.assertTrue(session.trace_configs)
finally:
await client.close()
async def test_http_client_retries_only_before_headers_are_sent(self):
self.assertTrue(_should_retry_transport_error(TimeoutError(), {"headers_sent": False}))
self.assertFalse(_should_retry_transport_error(TimeoutError(), {"headers_sent": True}))
async def test_http_client_applies_runtime_timeout_changes(self):
settings = SimpleNamespace(PAYMENT_REQUEST_TIMEOUT_SECONDS=20)
client = _DummyHttpClient(total_timeout=lambda: settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
try:
first = await client._get_session()
self.assertEqual(first.timeout.total, 20)
self.assertIs(await client._get_session(), first)
settings.PAYMENT_REQUEST_TIMEOUT_SECONDS = 5
second = await client._get_session()
self.assertIsNot(second, first)
self.assertEqual(second.timeout.total, 5)
# The replaced session must stay usable for in-flight requests;
# it is closed later, and close() always sweeps it up.
self.assertFalse(first.closed)
finally:
await client.close()
self.assertTrue(first.closed)
self.assertTrue(second.closed)
async def test_http_client_falls_back_to_default_timeout_on_bad_source(self):
client = _DummyHttpClient(total_timeout=lambda: None)
try:
session = await client._get_session()
self.assertEqual(session.timeout.total, 20.0)
finally:
await client.close()