- pyrightconfig.json 钉死 Python 3.12 虚拟环境,消除由于查找系统 Python 3.9 带来的假性报错 - 修复 huya/login.py 引用不存在函数的问题并补充单元测试 - 修复 browser_harvest.py 对 set 下标访问的错误并提升报错信息质量 - 虎牙 6 个子路由显式导入依赖,消除 import * 带来的未定义变量报警 - 规范化 Pydantic Field(default=...) 默认值声明 - 完善 solver.py / app_login.py 等核心路径类型守卫与 @overload 重载 - 在 pyproject.toml 中显式锁定 ruff lint 规则集 (E4, E7, E9, F, B, I, BLE) - 门禁脚本同步增加 ruff check 检查并在 AGENTS.md 补齐实践经验总结
103 lines
3.3 KiB
Python
103 lines
3.3 KiB
Python
import io
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from core.huya import browser_harvest
|
|
|
|
|
|
class _FakeStderr:
|
|
def readline(self):
|
|
return "DevTools listening on ws://127.0.0.1/devtools/browser/test\n"
|
|
|
|
|
|
class _FakeProcess:
|
|
stderr = _FakeStderr()
|
|
|
|
def kill(self):
|
|
pass
|
|
|
|
|
|
def test_launch_defaults_to_headless(monkeypatch):
|
|
calls = []
|
|
|
|
def fake_popen(args, **kwargs):
|
|
calls.append((args, kwargs))
|
|
return _FakeProcess()
|
|
|
|
def no_http(*args, **kwargs):
|
|
raise OSError("test: no CDP endpoint")
|
|
|
|
monkeypatch.setattr(browser_harvest.subprocess, "Popen", fake_popen)
|
|
monkeypatch.setattr(browser_harvest.urllib.request, "urlopen", no_http)
|
|
|
|
browser_harvest.launch(Path("/tmp/test-huya-profile"), 9555)
|
|
|
|
args, kwargs = calls[0]
|
|
assert "--headless=new" in args
|
|
assert kwargs["stdout"] is browser_harvest.subprocess.DEVNULL
|
|
|
|
|
|
def test_launch_can_show_window_when_requested(monkeypatch):
|
|
calls = []
|
|
|
|
def fake_popen(args, **kwargs):
|
|
calls.append(args)
|
|
return _FakeProcess()
|
|
|
|
def no_http(*args, **kwargs):
|
|
raise OSError("test: no CDP endpoint")
|
|
|
|
monkeypatch.setattr(browser_harvest.subprocess, "Popen", fake_popen)
|
|
monkeypatch.setattr(browser_harvest.urllib.request, "urlopen", no_http)
|
|
|
|
browser_harvest.launch(Path("/tmp/test-huya-profile"), 9556, headless=False)
|
|
|
|
assert "--headless=new" not in calls[0]
|
|
|
|
|
|
def test_launch_prefers_page_target_over_browser_endpoint(monkeypatch):
|
|
"""页面级 ws 必须优先于 browser 级(Network 域只能挂在 page target 上)。
|
|
|
|
这里原本写的是 ``pages[0]``,而 ``pages`` 是集合推导出来的 **set** ——
|
|
``set`` 不可下标,抛出的 TypeError 又被外层 ``except Exception: pass``
|
|
吞掉,于是每次都退回 browser 级 endpoint:页面级探测**从来没有成功过一次**,
|
|
而且没有任何日志能看出来。这就是本用例存在的意义。
|
|
"""
|
|
page_ws = "ws://127.0.0.1/devtools/page/PAGE"
|
|
browser_ws = "ws://127.0.0.1/devtools/browser/test"
|
|
payload = json.dumps([{"type": "page", "webSocketDebuggerUrl": page_ws}])
|
|
|
|
monkeypatch.setattr(
|
|
browser_harvest.subprocess, "Popen", lambda args, **kwargs: _FakeProcess()
|
|
)
|
|
# _FakeProcess.stderr 会给出 browser 级 endpoint,用来证明「选中了页面级」
|
|
monkeypatch.setattr(
|
|
browser_harvest.urllib.request,
|
|
"urlopen",
|
|
lambda *args, **kwargs: io.StringIO(payload),
|
|
)
|
|
|
|
_proc, ws_url = browser_harvest.launch(Path("/tmp/test-huya-profile"), 9557)
|
|
|
|
assert ws_url == page_ws
|
|
assert ws_url != browser_ws
|
|
|
|
|
|
def test_launch_falls_back_to_browser_endpoint_without_page_target(monkeypatch):
|
|
"""没有 page target 时才允许退回 browser 级 endpoint。"""
|
|
browser_ws = "ws://127.0.0.1/devtools/browser/test"
|
|
payload = json.dumps([{"type": "service_worker", "webSocketDebuggerUrl": "ws://x"}])
|
|
|
|
monkeypatch.setattr(
|
|
browser_harvest.subprocess, "Popen", lambda args, **kwargs: _FakeProcess()
|
|
)
|
|
monkeypatch.setattr(
|
|
browser_harvest.urllib.request,
|
|
"urlopen",
|
|
lambda *args, **kwargs: io.StringIO(payload),
|
|
)
|
|
|
|
_proc, ws_url = browser_harvest.launch(Path("/tmp/test-huya-profile"), 9558)
|
|
|
|
assert ws_url == browser_ws
|