mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-09 03:13:11 +08:00
Run `ruff check app tests scripts --fix` with the configured rule set (E4/E7/E9/F/I): import sorting (I001), f-strings without placeholders (F541), lambda/variable/unused-import cleanups that ruff marks safe. Nine files whose only ruff debt sits next to pre-existing pylint import-resolution errors (lazy exports, sys.path script imports) or whose "unused" imports are reached through attribute access by tests are left untouched so the changed-file pylint gate and the benchmark tests stay green; their diagnostics remain in the baseline. app/startup/lifecycle/__init__.py and app/main.py import business modules after cache composition, import-path and stdio setup on purpose (the source comments document the contract), so declare E402 per-file-ignores for them instead of adding per-line noqa. Ruff ratchet watermark drops from 498 to 100; sync the baseline fixture and the optimization checklist figure. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
from types import SimpleNamespace
|
||
from typing import Any, Iterator
|
||
|
||
import pytest
|
||
|
||
from app.foundation.singleton import Singleton
|
||
from app.runtime.extensions.plugin.contracts import PluginDashboardError
|
||
from app.runtime.extensions.plugin.manager import PluginManager
|
||
|
||
|
||
@pytest.fixture
|
||
def plugin_manager() -> Iterator[PluginManager]:
|
||
"""构造隔离的插件管理器实例,避免单例状态污染其它用例。"""
|
||
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
||
manager = PluginManager()
|
||
yield manager
|
||
Singleton._instances.pop((PluginManager, (), frozenset()), None)
|
||
|
||
|
||
def _plugin_with_dashboard(dashboard: Any) -> SimpleNamespace:
|
||
"""构造仅包含仪表板接口的插件实例。"""
|
||
return SimpleNamespace(
|
||
plugin_name="演示插件",
|
||
get_render_mode=lambda: ("vue", "dist/assets"),
|
||
get_dashboard=lambda key=None, user_agent=None: dashboard,
|
||
)
|
||
|
||
|
||
def test_plugin_dashboard_keeps_vue_elements_none(plugin_manager: PluginManager) -> None:
|
||
"""Vue 仪表板的 elements=None 应原样返回给前端渲染远程组件。"""
|
||
plugin_manager.running_plugins["DemoPlugin"] = _plugin_with_dashboard(
|
||
(
|
||
{"cols": 12},
|
||
{"title": "演示插件", "border": True},
|
||
None,
|
||
)
|
||
)
|
||
|
||
dashboard = plugin_manager.get_plugin_dashboard("DemoPlugin", "usage")
|
||
|
||
assert dashboard.id == "DemoPlugin"
|
||
assert dashboard.render_mode == "vue"
|
||
assert dashboard.cols == {"cols": 12}
|
||
assert dashboard.attrs == {"title": "演示插件", "border": True}
|
||
assert dashboard.elements is None
|
||
|
||
|
||
def test_plugin_dashboard_returns_none_when_plugin_has_no_dashboard(plugin_manager: PluginManager) -> None:
|
||
"""插件声明当前无仪表板时应返回 None,而不是触发解包异常。"""
|
||
plugin_manager.running_plugins["DemoPlugin"] = _plugin_with_dashboard(None)
|
||
|
||
assert plugin_manager.get_plugin_dashboard("DemoPlugin", "missing") is None
|
||
|
||
|
||
def test_plugin_dashboard_rejects_invalid_dashboard_shape(plugin_manager: PluginManager) -> None:
|
||
"""非空但不符合三元组契约的仪表板数据应返回服务端错误。"""
|
||
plugin_manager.running_plugins["DemoPlugin"] = _plugin_with_dashboard(
|
||
{"cols": {}, "attrs": {}, "elements": []}
|
||
)
|
||
|
||
with pytest.raises(PluginDashboardError) as exc_info:
|
||
plugin_manager.get_plugin_dashboard("DemoPlugin", "broken")
|
||
|
||
assert "仪表盘数据格式错误" in str(exc_info.value)
|