mirror of
https://github.com/zc-zhangchen/any-auto-register.git
synced 2026-05-08 00:04:07 +08:00
190 lines
7.9 KiB
Python
190 lines
7.9 KiB
Python
import unittest
|
|
from unittest import mock
|
|
|
|
from services.external_sync import sync_account
|
|
|
|
|
|
class DummyAccount:
|
|
def __init__(self, *, platform="chatgpt", email="demo@example.com", token="at-token", extra=None):
|
|
self.platform = platform
|
|
self.email = email
|
|
self.token = token
|
|
self.extra = dict(extra or {})
|
|
self.id = None
|
|
|
|
def get_extra(self):
|
|
return dict(self.extra)
|
|
|
|
|
|
def _config_getter(values: dict[str, str]):
|
|
def _get(key: str, default: str = "") -> str:
|
|
return values.get(key, default)
|
|
|
|
return _get
|
|
|
|
|
|
class ExternalSyncContributionModeTests(unittest.TestCase):
|
|
def test_contribution_enabled_uploads_only_to_contribution_server(self):
|
|
account = DummyAccount()
|
|
cfg = {
|
|
"contribution_enabled": "1",
|
|
"contribution_server_url": "http://contribution.local:7317",
|
|
"contribution_key": "pk-public-1",
|
|
"cpa_api_url": "http://cpa.local",
|
|
"codex_proxy_url": "http://codex.local",
|
|
"sub2api_api_url": "http://sub2api.local",
|
|
"sub2api_api_key": "sub2-key",
|
|
}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("services.external_sync.upload_chatgpt_account_to_cpa", return_value=(True, "ok")) as upload_mock:
|
|
with mock.patch("services.external_sync.persist_cpa_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(result[0]["name"], "Contribution")
|
|
self.assertTrue(result[0]["ok"])
|
|
upload_mock.assert_called_once_with(
|
|
account,
|
|
api_url="http://contribution.local:7317",
|
|
api_key="pk-public-1",
|
|
)
|
|
persist_mock.assert_called_once_with(account, True, "ok")
|
|
|
|
def test_contribution_enabled_without_server_url_fails_fast(self):
|
|
account = DummyAccount()
|
|
cfg = {
|
|
"contribution_enabled": "true",
|
|
"contribution_server_url": "",
|
|
"contribution_key": "pk-public-1",
|
|
}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("services.external_sync.upload_chatgpt_account_to_cpa") as upload_mock:
|
|
with mock.patch("services.external_sync.persist_cpa_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(result[0]["name"], "Contribution")
|
|
self.assertFalse(result[0]["ok"])
|
|
self.assertIn("未配置", result[0]["msg"])
|
|
upload_mock.assert_not_called()
|
|
persist_mock.assert_called_once()
|
|
|
|
def test_custom_contribution_upload_sends_token_json_and_top_level_tokens(self):
|
|
account = DummyAccount(
|
|
extra={
|
|
"refreshToken": "rt-camel-case",
|
|
"accessToken": "at-camel-case",
|
|
"idToken": "id-camel-case",
|
|
"clientId": "client-camel-case",
|
|
}
|
|
)
|
|
cfg = {
|
|
"contribution_enabled": "1",
|
|
"contribution_mode": "custom",
|
|
"custom_contribution_url": "http://custom.local:5000",
|
|
"custom_contribution_token": "custom-token",
|
|
}
|
|
|
|
response = mock.Mock()
|
|
response.status_code = 200
|
|
response.json.return_value = {"message": "queued"}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("platforms.chatgpt.cpa_upload.generate_token_json", return_value={"type": "codex", "email": account.email}):
|
|
with mock.patch("requests.post", return_value=response) as post_mock:
|
|
with mock.patch("services.external_sync.persist_cpa_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(result[0]["name"], "CustomContribution")
|
|
self.assertTrue(result[0]["ok"])
|
|
persist_mock.assert_called_once_with(account, True, "上传成功: queued")
|
|
post_mock.assert_called_once()
|
|
|
|
payload = post_mock.call_args.kwargs["json"]
|
|
self.assertEqual(payload["email"], account.email)
|
|
self.assertEqual(payload["refresh_token"], "rt-camel-case")
|
|
self.assertEqual(payload["access_token"], "at-camel-case")
|
|
self.assertEqual(payload["token_json"]["refresh_token"], "rt-camel-case")
|
|
self.assertEqual(payload["token_json"]["access_token"], "at-camel-case")
|
|
self.assertEqual(payload["token_json"]["id_token"], "id-camel-case")
|
|
self.assertEqual(payload["token_json"]["client_id"], "client-camel-case")
|
|
|
|
def test_contribution_disabled_keeps_existing_cpa_sync(self):
|
|
account = DummyAccount()
|
|
cfg = {
|
|
"contribution_enabled": "0",
|
|
"cpa_api_url": "http://cpa.local",
|
|
}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("services.external_sync.upload_chatgpt_account_to_cpa", return_value=(True, "ok")) as upload_mock:
|
|
with mock.patch("services.external_sync.persist_cpa_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(result[0]["name"], "CPA")
|
|
upload_mock.assert_called_once_with(account)
|
|
persist_mock.assert_called_once_with(account, True, "ok")
|
|
|
|
def test_cpa_disabled_skips_auto_upload_but_keeps_configuration(self):
|
|
account = DummyAccount()
|
|
cfg = {
|
|
"contribution_enabled": "0",
|
|
"cpa_enabled": "0",
|
|
"cpa_api_url": "http://cpa.local",
|
|
}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("services.external_sync.upload_chatgpt_account_to_cpa") as upload_mock:
|
|
with mock.patch("services.external_sync.persist_cpa_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(result, [])
|
|
upload_mock.assert_not_called()
|
|
persist_mock.assert_not_called()
|
|
|
|
def test_sub2api_enabled_uploads_and_persists_sync_status(self):
|
|
account = DummyAccount()
|
|
cfg = {
|
|
"contribution_enabled": "0",
|
|
"sub2api_enabled": "1",
|
|
"sub2api_api_url": "http://sub2api.local",
|
|
"sub2api_api_key": "sub2-key",
|
|
}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("platforms.chatgpt.sub2api_upload.upload_to_sub2api", return_value=(True, "ok")) as upload_mock:
|
|
with mock.patch("services.external_sync.persist_sub2api_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(len(result), 1)
|
|
self.assertEqual(result[0]["name"], "Sub2API")
|
|
self.assertTrue(result[0]["ok"])
|
|
upload_mock.assert_called_once()
|
|
persist_mock.assert_called_once_with(account, True, "ok")
|
|
|
|
def test_sub2api_disabled_skips_auto_upload_but_keeps_configuration(self):
|
|
account = DummyAccount()
|
|
cfg = {
|
|
"contribution_enabled": "0",
|
|
"sub2api_enabled": "0",
|
|
"sub2api_api_url": "http://sub2api.local",
|
|
"sub2api_api_key": "sub2-key",
|
|
}
|
|
|
|
with mock.patch("core.config_store.config_store.get", side_effect=_config_getter(cfg)):
|
|
with mock.patch("platforms.chatgpt.sub2api_upload.upload_to_sub2api") as upload_mock:
|
|
with mock.patch("services.external_sync.persist_sub2api_sync_result") as persist_mock:
|
|
result = sync_account(account)
|
|
|
|
self.assertEqual(result, [])
|
|
upload_mock.assert_not_called()
|
|
persist_mock.assert_not_called()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|