Files
live-hub-py/tests/test_douyu_write_path_contracts.py
T
yml2213andCursor e81119117f feat(huya): 多选登录改单线程队列并拆分路由与工作台
默认同时只登一个号,失败两次跳下一个,号间留间隔,结束后可一键重试失败账号。
顺带拆分虎牙路由与斗鱼工作台页面,并补齐 raw_cookie 重建入口。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 11:31:50 +08:00

117 lines
4.0 KiB
Python

"""斗鱼写路径契约:锁单/支付编排走 mock 客户端,不打真实兑换。"""
from unittest.mock import Mock
from sqlalchemy import create_engine, event
from sqlalchemy.orm import sessionmaker
from web.backend.database import Base
from web.backend.models import Account, DouyuGoodsSnapshot, DouyuTask, User
from web.backend.services.douyu_runner import DouyuBatchRunner
class TestDouyuWritePathContracts:
def setup_method(self):
self.engine = create_engine("sqlite://")
@event.listens_for(self.engine, "connect")
def enable_foreign_keys(connection, _):
connection.execute("PRAGMA foreign_keys=ON")
Base.metadata.create_all(self.engine)
self.session = sessionmaker(bind=self.engine)()
self.user = User(username="operator", password_hash="hash", role="super_admin")
self.account = Account(
username="dyuser",
password="pw",
email="a@example.com",
email_password="em",
)
self.session.add_all([self.user, self.account])
self.session.commit()
self.session.add(
DouyuGoodsSnapshot(
commodity_id="bag10",
name="套装-兔兔白日梦",
raw={"name": "套装-兔兔白日梦"},
)
)
self.session.commit()
def teardown_method(self):
self.session.close()
Base.metadata.drop_all(self.engine)
self.engine.dispose()
def _runner(self, task_type: str) -> DouyuBatchRunner:
return DouyuBatchRunner(db=self.session, batch_id="batch1", task_type=task_type)
def _task(self, task_type: str, payload: dict) -> DouyuTask:
task = DouyuTask(
batch_id="batch1",
account_id=self.account.id,
task_type=task_type,
handbook_scope="elite",
status="running",
result={"payload": payload},
created_by=self.user.id,
)
self.session.add(task)
self.session.commit()
return task
def test_lock_goods_records_order_without_paying(self):
task = self._task("lock_goods", {"commodity_id": "bag10", "num": 1})
runner = self._runner("lock_goods")
client = Mock()
client.create_exchange_order.return_value = {
"order_id": "5874",
"expire_seconds": "300",
}
runner._client = Mock(return_value=client)
runner._execute_lock_goods(
self.session,
task,
self.account,
"acf_uid=100",
{"manual_id": "G4KA4Qnz4LDp7", "rid": "9263298"},
)
self.session.refresh(task)
self.session.refresh(self.account)
assert task.status == "success"
assert task.result["order_id"] == "5874"
assert self.account.bind_status == "goods_locked"
client.create_exchange_order.assert_called_once()
client.pay_exchange_order.assert_not_called()
def test_pay_locked_order_uses_existing_order_id(self):
task = self._task(
"pay_locked_order",
{"order_id": "5874", "commodity_id": "bag10"},
)
runner = self._runner("pay_locked_order")
client = Mock()
client.pay_exchange_order.return_value = {
"exchange_id": "11098933",
"commodity_image": "https://example.test/item.png",
"exchange_num": 1,
}
runner._client = Mock(return_value=client)
runner._refresh_account_points = Mock(return_value={"points": 1280})
runner._execute_pay_locked_order(
self.session,
task,
self.account,
"acf_uid=100",
{"manual_id": "G4KA4Qnz4LDp7", "rid": "9263298"},
)
self.session.refresh(task)
assert task.status == "success"
assert task.result["exchange_id"] == "11098933"
client.pay_exchange_order.assert_called_once()
client.create_exchange_order.assert_not_called()