test: 全面迁移 pytest 并加入格式门禁
This commit is contained in:
+194
-143
@@ -1,202 +1,253 @@
|
||||
import pytest
|
||||
import json
|
||||
import re
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import Mock
|
||||
|
||||
from core.douyu.activity_client import DouyuActivityClient, DouyuActivityError
|
||||
|
||||
|
||||
class XpdExchangeTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
class TestXpdExchange:
|
||||
def setup_method(self):
|
||||
self.client = DouyuActivityClient(
|
||||
'acf_uid=100; acf_stk=stk; acf_ltkid=ltkid',
|
||||
"acf_uid=100; acf_stk=stk; acf_ltkid=ltkid",
|
||||
)
|
||||
|
||||
def test_exchange_uses_fresh_embed_authorization_and_point_price(self):
|
||||
self.client._request = Mock(return_value=SimpleNamespace(
|
||||
text='var buyInfo={"ret":"0","msg":"ok","serial":"order-1","newBalance":88};',
|
||||
))
|
||||
self.client._request = Mock(
|
||||
return_value=SimpleNamespace(
|
||||
text='var buyInfo={"ret":"0","msg":"ok","serial":"order-1","newBalance":88};',
|
||||
)
|
||||
)
|
||||
|
||||
result = self.client.xpd_exchange_goods(
|
||||
embed_query={
|
||||
'gameId': 'cjm', 'actId': '46195', 'appId': 'bp_cf',
|
||||
'livePlatId': 'douyu', 'code': 'fresh-code',
|
||||
'timestamp': '123', 'v': '2.0', 'sig': 'fresh-signature',
|
||||
"gameId": "cjm",
|
||||
"actId": "46195",
|
||||
"appId": "bp_cf",
|
||||
"livePlatId": "douyu",
|
||||
"code": "fresh-code",
|
||||
"timestamp": "123",
|
||||
"v": "2.0",
|
||||
"sig": "fresh-signature",
|
||||
},
|
||||
act_id='46195',
|
||||
rid='9263298',
|
||||
commodity_id='goods-1',
|
||||
act_id="46195",
|
||||
rid="9263298",
|
||||
commodity_id="goods-1",
|
||||
price=1200,
|
||||
picture='https://cdn.example/item.jpg',
|
||||
picture="https://cdn.example/item.jpg",
|
||||
pay_type=1,
|
||||
action_id='46195',
|
||||
action_id="46195",
|
||||
)
|
||||
|
||||
self.assertEqual(result['serial'], 'order-1')
|
||||
self.assertEqual(result['new_balance'], 88)
|
||||
assert result["serial"] == "order-1"
|
||||
assert result["new_balance"] == 88
|
||||
call = self.client._request.call_args
|
||||
self.assertEqual(call.args[:2], ('get', self.client.XPD_LIVE_BUY_API))
|
||||
params = call.kwargs['params']
|
||||
self.assertEqual(params['code'], 'fresh-code')
|
||||
self.assertEqual(params['sig'], 'fresh-signature')
|
||||
self.assertEqual(params['propid'], 'goods-1')
|
||||
self.assertEqual(params['paytype'], '1')
|
||||
self.assertEqual(json.loads(params['appext']), {
|
||||
'user_price': 1200,
|
||||
'sGoodsPic': 'https://cdn.example/item.jpg',
|
||||
'paytype': 1,
|
||||
})
|
||||
assert call.args[:2] == ("get", self.client.XPD_LIVE_BUY_API)
|
||||
params = call.kwargs["params"]
|
||||
assert params["code"] == "fresh-code"
|
||||
assert params["sig"] == "fresh-signature"
|
||||
assert params["propid"] == "goods-1"
|
||||
assert params["paytype"] == "1"
|
||||
assert json.loads(params["appext"]) == {
|
||||
"user_price": 1200,
|
||||
"sGoodsPic": "https://cdn.example/item.jpg",
|
||||
"paytype": 1,
|
||||
}
|
||||
|
||||
def test_role_and_balance_preserve_ios_platform_zero(self):
|
||||
self.client._request = Mock(return_value=SimpleNamespace(
|
||||
text=(
|
||||
'var info={"gameOpenId":"openid-ios","roleId":"role-ios",'
|
||||
'"roleName":"iOS角色","type":"wx","platId":0,"area":1};'
|
||||
),
|
||||
))
|
||||
role = self.client.xpd_get_role(embed_query={}, act_id='46195', rid='9263298')
|
||||
self.assertEqual(role['plat_id'], '0')
|
||||
self.assertEqual(role['area'], '1')
|
||||
|
||||
self.client._request = Mock(return_value=SimpleNamespace(
|
||||
text='var banlanceInfo={"ret":0,"balance":2199};',
|
||||
))
|
||||
result = self.client.xpd_balance(
|
||||
embed_query={}, act_id='46195', openid='openid-ios',
|
||||
roleid='role-ios', plat='0', areaid='1',
|
||||
self.client._request = Mock(
|
||||
return_value=SimpleNamespace(
|
||||
text=(
|
||||
'var info={"gameOpenId":"openid-ios","roleId":"role-ios",'
|
||||
'"roleName":"iOS角色","type":"wx","platId":0,"area":1};'
|
||||
),
|
||||
)
|
||||
)
|
||||
params = self.client._request.call_args.kwargs['params']
|
||||
self.assertEqual(params['plat'], '0')
|
||||
self.assertTrue(re.fullmatch(r'\d{13}', params['_time']))
|
||||
self.assertEqual(result['balance'], 2199)
|
||||
role = self.client.xpd_get_role(embed_query={}, act_id="46195", rid="9263298")
|
||||
assert role["plat_id"] == "0"
|
||||
assert role["area"] == "1"
|
||||
|
||||
self.client._request = Mock(
|
||||
return_value=SimpleNamespace(
|
||||
text='var banlanceInfo={"ret":0,"balance":2199};',
|
||||
)
|
||||
)
|
||||
result = self.client.xpd_balance(
|
||||
embed_query={},
|
||||
act_id="46195",
|
||||
openid="openid-ios",
|
||||
roleid="role-ios",
|
||||
plat="0",
|
||||
areaid="1",
|
||||
)
|
||||
params = self.client._request.call_args.kwargs["params"]
|
||||
assert params["plat"] == "0"
|
||||
assert re.fullmatch(r"\d{13}", params["_time"])
|
||||
assert result["balance"] == 2199
|
||||
|
||||
def test_exchange_surfaces_daoju_failure_message(self):
|
||||
self.client._request = Mock(return_value=SimpleNamespace(
|
||||
text='var buyInfo={"ret":"-1","msg":"点券不足"};',
|
||||
))
|
||||
self.client._request = Mock(
|
||||
return_value=SimpleNamespace(
|
||||
text='var buyInfo={"ret":"-1","msg":"点券不足"};',
|
||||
)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(DouyuActivityError, '点券不足'):
|
||||
with pytest.raises(DouyuActivityError, match="点券不足"):
|
||||
self.client.xpd_exchange_goods(
|
||||
embed_query={'code': 'fresh-code'},
|
||||
act_id='46195',
|
||||
rid='9263298',
|
||||
commodity_id='goods-1',
|
||||
embed_query={"code": "fresh-code"},
|
||||
act_id="46195",
|
||||
rid="9263298",
|
||||
commodity_id="goods-1",
|
||||
price=1200,
|
||||
)
|
||||
|
||||
def test_list_goods_requests_and_preserves_inventory(self):
|
||||
self.client._request = Mock(return_value=SimpleNamespace(
|
||||
text=(
|
||||
'var recommend={"data":{"client_data":{"itemsdetail":[{'
|
||||
'"iGoodsId":"goods-1","sGoodsName":"测试商品","iPrice":"6800",'
|
||||
'"iJb2Price":"0","iGoodsLeft":"0"}]}}};'
|
||||
),
|
||||
))
|
||||
|
||||
result = self.client.xpd_list_goods(
|
||||
embed_query={}, act_id='46195', openid='openid', roleid='roleid',
|
||||
self.client._request = Mock(
|
||||
return_value=SimpleNamespace(
|
||||
text=(
|
||||
'var recommend={"data":{"client_data":{"itemsdetail":[{'
|
||||
'"iGoodsId":"goods-1","sGoodsName":"测试商品","iPrice":"6800",'
|
||||
'"iJb2Price":"0","iGoodsLeft":"0"}]}}};'
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(result['goods'][0]['price'], 6800)
|
||||
self.assertEqual(result['goods'][0]['goods_left'], 0)
|
||||
params = self.client._request.call_args.kwargs['params']
|
||||
self.assertEqual(params['excludeFields'], 'iCategoryId_76')
|
||||
self.assertNotIn('category', params)
|
||||
result = self.client.xpd_list_goods(
|
||||
embed_query={},
|
||||
act_id="46195",
|
||||
openid="openid",
|
||||
roleid="roleid",
|
||||
)
|
||||
|
||||
assert result["goods"][0]["price"] == 6800
|
||||
assert result["goods"][0]["goods_left"] == 0
|
||||
params = self.client._request.call_args.kwargs["params"]
|
||||
assert params["excludeFields"] == "iCategoryId_76"
|
||||
assert "category" not in params
|
||||
|
||||
def test_list_goods_fetches_every_page_and_deduplicates_goods(self):
|
||||
first_page = [
|
||||
{'iGoodsId': f'goods-{index}', 'sGoodsName': f'商品 {index}'}
|
||||
{"iGoodsId": f"goods-{index}", "sGoodsName": f"商品 {index}"}
|
||||
for index in range(10)
|
||||
]
|
||||
second_page = [
|
||||
{'iGoodsId': 'goods-9', 'sGoodsName': '重复商品'},
|
||||
{'iGoodsId': 'goods-10', 'sGoodsName': '商品 10'},
|
||||
{"iGoodsId": "goods-9", "sGoodsName": "重复商品"},
|
||||
{"iGoodsId": "goods-10", "sGoodsName": "商品 10"},
|
||||
]
|
||||
self.client._request = Mock(side_effect=[
|
||||
SimpleNamespace(text=f'var recommend={{"errcode":0,"data":{{"client_data":{{"itemsdetail":{json.dumps(first_page)}}}}}}};'),
|
||||
SimpleNamespace(text=f'var recommend={{"errcode":0,"data":{{"client_data":{{"itemsdetail":{json.dumps(second_page)}}}}}}};'),
|
||||
])
|
||||
|
||||
result = self.client.xpd_list_goods(
|
||||
embed_query={}, act_id='46195', openid='openid', roleid='roleid',
|
||||
self.client._request = Mock(
|
||||
side_effect=[
|
||||
SimpleNamespace(
|
||||
text=f'var recommend={{"errcode":0,"data":{{"client_data":{{"itemsdetail":{json.dumps(first_page)}}}}}}};'
|
||||
),
|
||||
SimpleNamespace(
|
||||
text=f'var recommend={{"errcode":0,"data":{{"client_data":{{"itemsdetail":{json.dumps(second_page)}}}}}}};'
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(len(result['goods']), 11)
|
||||
self.assertEqual([item['commodity_id'] for item in result['goods']][-1], 'goods-10')
|
||||
self.assertEqual(self.client._request.call_count, 2)
|
||||
first_params = self.client._request.call_args_list[0].kwargs['params']
|
||||
second_params = self.client._request.call_args_list[1].kwargs['params']
|
||||
self.assertEqual((first_params['page_begin'], first_params['page_num']), ('0', '1'))
|
||||
self.assertEqual((second_params['page_begin'], second_params['page_num']), ('10', '2'))
|
||||
result = self.client.xpd_list_goods(
|
||||
embed_query={},
|
||||
act_id="46195",
|
||||
openid="openid",
|
||||
roleid="roleid",
|
||||
)
|
||||
|
||||
assert len(result["goods"]) == 11
|
||||
assert [item["commodity_id"] for item in result["goods"]][-1] == "goods-10"
|
||||
assert self.client._request.call_count == 2
|
||||
first_params = self.client._request.call_args_list[0].kwargs["params"]
|
||||
second_params = self.client._request.call_args_list[1].kwargs["params"]
|
||||
assert (first_params["page_begin"], first_params["page_num"]) == ("0", "1")
|
||||
assert (second_params["page_begin"], second_params["page_num"]) == ("10", "2")
|
||||
|
||||
def test_purchase_records_parses_order_list_and_paginates(self):
|
||||
first_record = {
|
||||
'sSerialNum': 'order-1',
|
||||
'dtBuyTime': '2026-08-08 01:00:42',
|
||||
'dtPayTime': '2026-08-08 01:00:55',
|
||||
'iStatus': '3',
|
||||
'iPrice': '800',
|
||||
'iPayAmount': '800',
|
||||
'sRoleName': '测试角色',
|
||||
'sGoodsInfo': json.dumps({
|
||||
'list': [{'sGoodsName': '改名卡', 'sGoodsPic': 'https://cdn.example/item.jpg'}],
|
||||
}),
|
||||
"sSerialNum": "order-1",
|
||||
"dtBuyTime": "2026-08-08 01:00:42",
|
||||
"dtPayTime": "2026-08-08 01:00:55",
|
||||
"iStatus": "3",
|
||||
"iPrice": "800",
|
||||
"iPayAmount": "800",
|
||||
"sRoleName": "测试角色",
|
||||
"sGoodsInfo": json.dumps(
|
||||
{
|
||||
"list": [
|
||||
{
|
||||
"sGoodsName": "改名卡",
|
||||
"sGoodsPic": "https://cdn.example/item.jpg",
|
||||
}
|
||||
],
|
||||
}
|
||||
),
|
||||
}
|
||||
self.client._request = Mock(side_effect=[
|
||||
SimpleNamespace(text=f'var info={{"ret":"0","msg":"ok","data":{{"cnt":11,"list":{json.dumps([first_record])}}}}};'),
|
||||
SimpleNamespace(text='var info={"ret":"0","msg":"ok","data":{"cnt":11,"list":[]}};'),
|
||||
])
|
||||
self.client._request = Mock(
|
||||
side_effect=[
|
||||
SimpleNamespace(
|
||||
text=f'var info={{"ret":"0","msg":"ok","data":{{"cnt":11,"list":{json.dumps([first_record])}}}}};'
|
||||
),
|
||||
SimpleNamespace(
|
||||
text='var info={"ret":"0","msg":"ok","data":{"cnt":11,"list":[]}};'
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
result = self.client.xpd_purchase_records(
|
||||
embed_query={
|
||||
'gameId': 'cjm', 'actId': '18882', 'appId': 'bp_cf',
|
||||
'livePlatId': 'douyu', 'code': 'fresh-code',
|
||||
'timestamp': '123', 'v': '2.0', 'sig': 'fresh-signature',
|
||||
"gameId": "cjm",
|
||||
"actId": "18882",
|
||||
"appId": "bp_cf",
|
||||
"livePlatId": "douyu",
|
||||
"code": "fresh-code",
|
||||
"timestamp": "123",
|
||||
"v": "2.0",
|
||||
"sig": "fresh-signature",
|
||||
},
|
||||
act_id='46195',
|
||||
act_id="46195",
|
||||
page_size=1,
|
||||
)
|
||||
|
||||
self.assertEqual(result['total'], 11)
|
||||
self.assertEqual(result['records'][0]['goods_name'], '改名卡')
|
||||
self.assertEqual(result['records'][0]['serial'], 'order-1')
|
||||
self.assertEqual(self.client._request.call_count, 2)
|
||||
params = self.client._request.call_args_list[0].kwargs['params']
|
||||
self.assertEqual(params['_service'], 'order.list')
|
||||
self.assertEqual(params['pn'], '1')
|
||||
self.assertEqual(params['code'], 'fresh-code')
|
||||
|
||||
assert result["total"] == 11
|
||||
assert result["records"][0]["goods_name"] == "改名卡"
|
||||
assert result["records"][0]["serial"] == "order-1"
|
||||
assert self.client._request.call_count == 2
|
||||
params = self.client._request.call_args_list[0].kwargs["params"]
|
||||
assert params["_service"] == "order.list"
|
||||
assert params["pn"] == "1"
|
||||
assert params["code"] == "fresh-code"
|
||||
|
||||
def test_exchange_keeps_raw_price_from_goods_list(self):
|
||||
self.client._request = Mock(side_effect=[
|
||||
SimpleNamespace(
|
||||
text='var recommend={"errcode":0,"data":{"client_data":{"itemsdetail":[{'
|
||||
'"iGoodsId":"goods-1","sGoodsName":"测试商品","iPrice":"6800",'
|
||||
'"iJb2Price":"0","iGoodsLeft":"-1"}]}}};',
|
||||
),
|
||||
SimpleNamespace(text='var buyInfo={"ret":"0","msg":"ok","serial":"order-1","newBalance":88};'),
|
||||
])
|
||||
|
||||
goods = self.client.xpd_list_goods(
|
||||
embed_query={}, act_id='46195', openid='openid', roleid='roleid',
|
||||
)['goods']
|
||||
result = self.client.xpd_exchange_goods(
|
||||
embed_query={'code': 'fresh-code'},
|
||||
act_id='46195',
|
||||
rid='9263298',
|
||||
commodity_id=goods[0]['commodity_id'],
|
||||
price=goods[0]['price'],
|
||||
picture='',
|
||||
pay_type=1,
|
||||
action_id='46195',
|
||||
self.client._request = Mock(
|
||||
side_effect=[
|
||||
SimpleNamespace(
|
||||
text='var recommend={"errcode":0,"data":{"client_data":{"itemsdetail":[{'
|
||||
'"iGoodsId":"goods-1","sGoodsName":"测试商品","iPrice":"6800",'
|
||||
'"iJb2Price":"0","iGoodsLeft":"-1"}]}}};',
|
||||
),
|
||||
SimpleNamespace(
|
||||
text='var buyInfo={"ret":"0","msg":"ok","serial":"order-1","newBalance":88};'
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(goods[0]['price'], 6800)
|
||||
self.assertEqual(result['serial'], 'order-1')
|
||||
params = self.client._request.call_args.kwargs['params']
|
||||
self.assertEqual(json.loads(params['appext'])['user_price'], 6800)
|
||||
goods = self.client.xpd_list_goods(
|
||||
embed_query={},
|
||||
act_id="46195",
|
||||
openid="openid",
|
||||
roleid="roleid",
|
||||
)["goods"]
|
||||
result = self.client.xpd_exchange_goods(
|
||||
embed_query={"code": "fresh-code"},
|
||||
act_id="46195",
|
||||
rid="9263298",
|
||||
commodity_id=goods[0]["commodity_id"],
|
||||
price=goods[0]["price"],
|
||||
picture="",
|
||||
pay_type=1,
|
||||
action_id="46195",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
assert goods[0]["price"] == 6800
|
||||
assert result["serial"] == "order-1"
|
||||
params = self.client._request.call_args.kwargs["params"]
|
||||
assert json.loads(params["appext"])["user_price"] == 6800
|
||||
|
||||
Reference in New Issue
Block a user