test: 全面迁移 pytest 并加入格式门禁

This commit is contained in:
yml2213
2026-08-30 19:19:32 +08:00
parent 3ce1c7a51b
commit 13b5aedd1d
26 changed files with 1374 additions and 888 deletions
+47 -42
View File
@@ -1,17 +1,18 @@
"""精英手册兑换:csrf 复用、新链路接口与浏览器状态机路由的测试。"""
import unittest
import pytest
from unittest.mock import Mock, call
from core.douyu.activity_client import DouyuActivityClient, DouyuActivityError
class CsrfReuseTests(unittest.TestCase):
class TestCsrfReuse:
def test_reuses_cookie_token_without_any_http_call(self):
client = DouyuActivityClient("acf_uid=100; cvl_csrf_token=existing-token")
client._request_json = Mock()
self.assertEqual(client.csrf_token(), "existing-token")
assert client.csrf_token() == "existing-token"
client._request_json.assert_not_called()
def test_generates_csrf_when_cookie_missing(self):
@@ -24,7 +25,7 @@ class CsrfReuseTests(unittest.TestCase):
client._request_json = Mock(side_effect=fake_generate)
self.assertEqual(client.csrf_token(), "new-token")
assert client.csrf_token() == "new-token"
client._request_json.assert_called_once()
def test_force_refresh_rotates_token(self):
@@ -32,45 +33,51 @@ class CsrfReuseTests(unittest.TestCase):
client._request_json = Mock(return_value={"error": 0})
client._set_cookie_value("cvl_csrf_token", "rotated-token")
self.assertEqual(client.csrf_token(force_refresh=True), "rotated-token")
assert client.csrf_token(force_refresh=True) == "rotated-token"
def test_refreshes_csrf_once_on_token_error(self):
client = DouyuActivityClient("acf_uid=100")
client.csrf_token = Mock(side_effect=["bad-token", "good-token"])
client._request_json = Mock(side_effect=[
{"error": 1, "msg": "csrfToken 校验失败"},
{"error": 0, "data": {"orderId": "9", "expireSeconds": "300"}},
])
client._request_json = Mock(
side_effect=[
{"error": 1, "msg": "csrfToken 校验失败"},
{"error": 0, "data": {"orderId": "9", "expireSeconds": "300"}},
]
)
result = client.create_exchange_order(manual_id="m", rid="r", commodity_id="c")
self.assertEqual(result["order_id"], "9")
self.assertEqual(client.csrf_token.call_args_list, [call(), call(force_refresh=True)])
assert result["order_id"] == "9"
assert client.csrf_token.call_args_list == [call(), call(force_refresh=True)]
def test_no_refresh_on_regular_error(self):
client = DouyuActivityClient("acf_uid=100")
client.csrf_token = Mock(return_value="t")
client._request_json = Mock(return_value={"error": 1, "msg": "需要开通精英手册,才可以兑换本道具哦"})
client._request_json = Mock(
return_value={"error": 1, "msg": "需要开通精英手册,才可以兑换本道具哦"}
)
with self.assertRaisesRegex(DouyuActivityError, "需要开通精英手册"):
with pytest.raises(DouyuActivityError, match="需要开通精英手册"):
client.create_exchange_order(manual_id="m", rid="r", commodity_id="c")
client.csrf_token.assert_called_once_with()
def test_pay_referer_includes_room_id_like_browser(self):
client = DouyuActivityClient("acf_uid=100")
client.csrf_token = Mock(return_value="t")
client._request_json = Mock(return_value={"error": 0, "data": {"exchangeId": "11098933"}})
client._request_json = Mock(
return_value={"error": 0, "data": {"exchangeId": "11098933"}}
)
client.pay_exchange_order(manual_id="m", order_id="5874", rid="9263298")
headers = client._request_json.call_args.kwargs["headers"]
self.assertEqual(
headers["Referer"],
"https://www.douyu.com/pages/live-peace-handbook/web/shop?ditchname=pass0&roomId=9263298",
assert (
headers["Referer"]
== "https://www.douyu.com/pages/live-peace-handbook/web/shop?ditchname=pass0&roomId=9263298"
)
class ExchangePlanTests(unittest.TestCase):
class TestExchangePlan:
"""对齐浏览器兑换按钮状态机($e / Ve / Ge)的路由判定。"""
@staticmethod
@@ -92,72 +99,70 @@ class ExchangePlanTests(unittest.TestCase):
def test_normal_item_uses_classic_flow(self):
plan = DouyuActivityClient.resolve_exchange_plan(self.detail())
self.assertEqual(plan["action"], "classic")
self.assertEqual(plan["max_num"], 1)
assert plan["action"] == "classic"
assert plan["max_num"] == 1
def test_pre_exchange_order_still_classic(self):
plan = DouyuActivityClient.resolve_exchange_plan(self.detail(preExchange={"isExists": 1}))
self.assertEqual(plan["action"], "classic")
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(preExchange={"isExists": 1})
)
assert plan["action"] == "classic"
def test_reached_exchange_limit_blocked(self):
plan = DouyuActivityClient.resolve_exchange_plan(self.detail(status=1))
self.assertEqual(plan["action"], "blocked")
self.assertIn("上限", plan["text"])
assert plan["action"] == "blocked"
assert "上限" in plan["text"]
def test_no_stock_blocked(self):
plan = DouyuActivityClient.resolve_exchange_plan(self.detail(storeStatus=0))
self.assertEqual(plan["action"], "blocked")
self.assertIn("无库存", plan["text"])
assert plan["action"] == "blocked"
assert "无库存" in plan["text"]
def test_room_limited_and_not_in_room_blocked(self):
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(roomLimited=1, isLimitRoom=0)
)
self.assertEqual(plan["action"], "blocked")
self.assertIn("限定房间", plan["text"])
assert plan["action"] == "blocked"
assert "限定房间" in plan["text"]
def test_not_open_subscribe_item_subscribes(self):
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(openStatus=0, subscribeType=1)
)
self.assertEqual(plan["action"], "subscribe")
assert plan["action"] == "subscribe"
def test_not_open_pre_exchange_item_pre_exchanges(self):
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(openStatus=0, subscribeType=2)
)
self.assertEqual(plan["action"], "pre_exchange")
assert plan["action"] == "pre_exchange"
def test_not_open_plain_item_blocked(self):
plan = DouyuActivityClient.resolve_exchange_plan(self.detail(openStatus=0))
self.assertEqual(plan["action"], "blocked")
self.assertIn("未开启", plan["text"])
assert plan["action"] == "blocked"
assert "未开启" in plan["text"]
def test_elite_limited_requires_manual(self):
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(eliteLimited=1), manual_type=0
)
self.assertEqual(plan["action"], "blocked")
self.assertIn("精英手册", plan["text"])
assert plan["action"] == "blocked"
assert "精英手册" in plan["text"]
# 已开通手册(manualType=1)不受精英专享限制
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(eliteLimited=1), manual_type=1
)
self.assertEqual(plan["action"], "classic")
assert plan["action"] == "classic"
def test_pre_exchanged_waits_for_open(self):
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(subscribeType=2, exchangeInfo={"userStatus": 1})
)
self.assertEqual(plan["action"], "wait")
assert plan["action"] == "wait"
def test_batch_exchange_clamps_num(self):
plan = DouyuActivityClient.resolve_exchange_plan(
self.detail(batchExchange=1), batch_num_limit="5"
)
self.assertEqual(plan["max_num"], 5)
self.assertTrue(plan["batch_exchange"])
if __name__ == "__main__":
unittest.main()
assert plan["max_num"] == 5
assert plan["batch_exchange"]