- delete GatewayHTTPServer/GatewayHandler, create_server, /healthz and /v1/channel; event_channel module removed - load_config now requires CREATOR_PLATFORM_URL + CREATOR_GATEWAY_KEY - run() wires Gateway into OutboundAgent; SIGINT/SIGTERM stop the agent - deploy env example, install script, systemd unit docs and deployment docs updated to the outbound model; NATIVE_GATEWAY_ENDPOINT dead dev config removed
58 lines
3.0 KiB
Python
58 lines
3.0 KiB
Python
"""Unit tests: an unsigned-in browser is pending, not a transport/identity error."""
|
|
import json
|
|
import unittest
|
|
from contextlib import nullcontext
|
|
from types import SimpleNamespace
|
|
from unittest.mock import Mock
|
|
|
|
from .platform.douyin import BrowserResponse, DouyinBrowser, DouyinError
|
|
from .server.http import Gateway, RequestError
|
|
|
|
|
|
class LoginPendingTests(unittest.TestCase):
|
|
def browser_with_response(self, body, status=200):
|
|
browser = DouyinBrowser()
|
|
browser.get = Mock(return_value=BrowserResponse(status, json.dumps(body), {}))
|
|
return browser
|
|
|
|
def test_unsigned_browser_has_explicit_pending_signal(self):
|
|
from .platform.douyin import DouyinLoginPending
|
|
for body in [{"status_code": 8}, {"status_code": 0, "user": {"uid": "0"}}]:
|
|
with self.subTest(body=body):
|
|
browser = self.browser_with_response(body)
|
|
with self.assertRaises(DouyinLoginPending):
|
|
browser.identity("safe")
|
|
|
|
def test_bad_response_is_not_pending(self):
|
|
from .platform.douyin import DouyinLoginPending
|
|
for body, status in [({}, 200), ({"status_code": 0}, 200), ({"status_code": 0, "user": {}}, 200), ({"status_code": 0, "user": {"uid": ""}}, 200), ({"status_code": 500}, 200), ({"status_code": 8}, 503), ({"status_code": 0, "user": {"uid": "bad"}}, 200)]:
|
|
with self.subTest(body=body, status=status):
|
|
with self.assertRaises(DouyinError) as raised:
|
|
self.browser_with_response(body, status).identity("safe")
|
|
self.assertNotIsInstance(raised.exception, DouyinLoginPending)
|
|
|
|
def gateway(self):
|
|
runtimes = Mock()
|
|
runtimes.alias_lock.return_value = nullcontext()
|
|
runtimes.require_generation.return_value = SimpleNamespace(runtime_id='a' * 64, network_exit_id='exit-1')
|
|
browser = Mock()
|
|
gateway = Gateway(runtimes, 'node-a', browser=browser)
|
|
payload = {'runtime_id': 'a' * 64, 'binding_version': 1, 'network_id': 'native-' + 'b' * 32, 'network_exit_id': 'exit-1', 'expected_account_key': '123'}
|
|
return gateway, browser, payload
|
|
|
|
def test_gateway_returns_pending_as_normal_status_and_logs_it(self):
|
|
from .platform.douyin import DouyinLoginPending
|
|
gateway, browser, payload = self.gateway()
|
|
browser.identity.side_effect = DouyinLoginPending("waiting for login")
|
|
with self.assertLogs("creatorhub.gateway", level="INFO") as logs:
|
|
result = gateway.douyin_identity("safe", payload)
|
|
self.assertEqual(result, {"status": "manual_login", "reason": "awaiting_login"})
|
|
self.assertIn("awaiting_login", " ".join(logs.output))
|
|
|
|
def test_gateway_keeps_real_failures_visible(self):
|
|
gateway, browser, payload = self.gateway()
|
|
browser.identity.side_effect = DouyinError("runtime disconnected")
|
|
with self.assertLogs("creatorhub.gateway", level="WARNING"):
|
|
with self.assertRaisesRegex(RequestError, "could not be verified"):
|
|
gateway.douyin_identity("safe", payload)
|