Files
Nexus/tests/test_btpanel_client.py
T

90 lines
2.9 KiB
Python
Raw Normal View History

"""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")