Files
Nexus/tests/test_btpanel_client.py
T
r 6859846b7c sync: 主项目全量同步(含 btpanel 一键登录回归修复与前端构建产物)
- bootstrap 失败恢复 SSH 临时登录回退
- ssh_bootstrap 真安装检测与 config 目录自愈
- axs Gitea 发布源切换为 https://axs.kuma1xn.vip
2026-07-08 23:52:40 +08:00

90 lines
2.9 KiB
Python

"""Tests for Baota panel client signing and credentials."""
import hashlib
import time
from unittest.mock import AsyncMock
import httpx
import pytest
from server.infrastructure.btpanel.client import BtPanelApiError, BtPanelClient, raise_if_panel_error
from server.infrastructure.btpanel.credentials import (
BT_PANEL_ATTR,
BtPanelCredentials,
merge_bt_panel_extra,
public_bt_panel_status,
)
from server.domain.models import Server
def test_sign_algorithm_matches_panel_common():
api_key = "test-api-key"
now = 1700000000
expected = hashlib.md5(f"{now}{api_key}".encode()).hexdigest()
creds = BtPanelCredentials(base_url="http://127.0.0.1:8888", api_key=api_key)
client = BtPanelClient(creds, server_id=1)
# patch time
orig = time.time
try:
time.time = lambda: now # type: ignore[method-assign]
signed = client._sign()
finally:
time.time = orig # type: ignore[method-assign]
assert signed["request_time"] == now
assert signed["request_token"] == expected
def test_merge_bt_panel_extra_encrypts_key(monkeypatch):
monkeypatch.setattr(
"server.infrastructure.btpanel.credentials.encrypt_value",
lambda s: f"enc:{s}",
)
extra = merge_bt_panel_extra({}, base_url="https://1.2.3.4:8888/abc", api_key="secret")
block = extra[BT_PANEL_ATTR]
assert block["base_url"] == "https://1.2.3.4:8888/abc"
assert block["api_key_enc"] == "enc:secret"
def test_public_bt_panel_status():
server = Server(id=1, name="s", domain="1.2.3.4", extra_attrs={
BT_PANEL_ATTR: {"base_url": "https://x:8888", "api_key_enc": "x"},
})
st = public_bt_panel_status(server)
assert st["configured"] is True
assert st["api_key_set"] is True
def test_raise_if_panel_error_on_status_false():
with pytest.raises(BtPanelApiError, match="IP校验失败"):
raise_if_panel_error({"status": False, "msg": "IP校验失败,您的访问IP为[1.2.3.4]"})
def test_raise_if_panel_error_ignores_success_payload():
payload = {"memTotal": 7939, "cpuNum": 2}
raise_if_panel_error(payload)
raise_if_panel_error({"status": True, "data": []})
@pytest.mark.asyncio
async def test_post_wraps_connect_error(monkeypatch):
creds = BtPanelCredentials(base_url="http://127.0.0.1:8888", api_key="k")
client = BtPanelClient(creds, server_id=1)
class _BrokenClient:
async def __aenter__(self):
return self
async def __aexit__(self, *args):
return None
async def post(self, *args, **kwargs):
raise httpx.ConnectError("All connection attempts failed")
monkeypatch.setattr("server.infrastructure.btpanel.client.httpx.AsyncClient", lambda **kw: _BrokenClient())
monkeypatch.setattr(client, "_load_cookies", AsyncMock(return_value={}))
with pytest.raises(BtPanelApiError, match="无法连接宝塔面板"):
await client.post("/system?action=GetSystemTotal")