Files
MoviePilot/tests/test_transfer_rename_build_event.py

142 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
TransferRenameBuild 事件的单元测试。
通过 patch ``eventmanager.send_event`` 模拟链上插件处理器,避免依赖
MoviePilot 的"插件实例反查"机制(``__get_class_instance`` 要求 handler 位于
``app.<plugin>`` 模块内)。覆盖以下关键路径:
1. 插件就地 mutate ``rename_dict`` 后,主程序首次渲染读取到补充字段;
2. 插件用"返回新 dict"的方式(替换 ``event_data.rename_dict`` 引用)也能生效;
3. 没有任何监听者时(``send_event`` 返回 None渲染输出与改造前完全一致
4. ``get_rename_path`` 把正确的 ``source_path`` / ``source_item`` / ``template_string``
注入到 ``TransferRenameBuildEventData``,便于插件做条件早退。
"""
import unittest
from unittest.mock import patch
from app.core.event import Event
from app.modules.filemanager.transhandler import TransHandler
from app.schemas.event import TransferRenameBuildEventData
from app.schemas.types import ChainEventType
class TransferRenameBuildEventTest(unittest.TestCase):
"""
通过 ``unittest.mock.patch`` 替换 ``eventmanager.send_event`` 实现:
每个测试自定义一个 ``fake_send_event``,根据事件类型决定如何模拟链上插件
对 ``event_data`` 的修改,再返回 ``Event(event_data=...)``,与真实 dispatcher
返回行为对齐。
"""
TEMPLATE = "{{title}}{% if effect %} {{effect}}{% endif %}{% if codec %} {{codec}}{% endif %}"
@staticmethod
def _make_event(event_type: ChainEventType, data) -> Event:
"""构造真实 dispatcher 返回的 Event 对象,便于和生产代码读取路径对齐。"""
return Event(event_type=event_type.value, event_data=data)
def test_in_place_field_supplement_takes_effect(self):
captured = {}
def fake_send_event(event_type, data, **_kwargs):
if event_type is ChainEventType.TransferRenameBuild:
self.assertIsInstance(data, TransferRenameBuildEventData)
captured["template_string"] = data.template_string
captured["source_path"] = data.source_path
# 模拟插件就地补充字段
data.rename_dict["effect"] = "SDR"
return self._make_event(event_type, data)
return self._make_event(event_type, data)
with patch(
"app.modules.filemanager.transhandler.eventmanager.send_event",
side_effect=fake_send_event,
):
path = TransHandler.get_rename_path(
template_string=self.TEMPLATE,
rename_dict={"title": "Foo"},
source_path="/downloads/foo.mkv",
)
self.assertEqual(path.as_posix(), "Foo SDR")
self.assertEqual(captured["template_string"], self.TEMPLATE)
self.assertEqual(captured["source_path"], "/downloads/foo.mkv")
def test_returning_new_dict_reference_is_respected(self):
"""
模拟插件用"完整替换 rename_dict 引用"的写法,验证 get_rename_path 在事件
返回后会重新取引用,新 dict 中的字段也能被首次渲染读到。
"""
def fake_send_event(event_type, data, **_kwargs):
if event_type is ChainEventType.TransferRenameBuild:
new_dict = dict(data.rename_dict)
new_dict["codec"] = "H265"
data.rename_dict = new_dict
return self._make_event(event_type, data)
with patch(
"app.modules.filemanager.transhandler.eventmanager.send_event",
side_effect=fake_send_event,
):
path = TransHandler.get_rename_path(
template_string=self.TEMPLATE,
rename_dict={"title": "Foo"},
source_path="/downloads/foo.mkv",
)
self.assertEqual(path.as_posix(), "Foo H265")
def test_no_listeners_yields_unchanged_render(self):
"""
监听者缺席时 send_event 返回 Noneget_rename_path 应跳过引用刷新并按原
rename_dict 渲染,行为与改造前完全一致。
"""
def fake_send_event(event_type, _data, **_kwargs):
# 真实 dispatcher 在无 enabled handler 时返回 None
return None
with patch(
"app.modules.filemanager.transhandler.eventmanager.send_event",
side_effect=fake_send_event,
):
path = TransHandler.get_rename_path(
template_string=self.TEMPLATE,
rename_dict={"title": "Foo"},
source_path="/downloads/foo.mkv",
)
self.assertEqual(path.as_posix(), "Foo")
def test_event_data_carries_source_metadata(self):
"""
即便没有 source_pathrecommend_name 预览场景),事件仍会触发,但
``source_path`` / ``source_item`` 都为 None供插件自行早退。
"""
captured = {}
def fake_send_event(event_type, data, **_kwargs):
if event_type is ChainEventType.TransferRenameBuild:
captured["source_path"] = data.source_path
captured["source_item"] = data.source_item
return self._make_event(event_type, data)
with patch(
"app.modules.filemanager.transhandler.eventmanager.send_event",
side_effect=fake_send_event,
):
TransHandler.get_rename_path(
template_string=self.TEMPLATE,
rename_dict={"title": "Foo"},
)
self.assertIsNone(captured["source_path"])
self.assertIsNone(captured["source_item"])
if __name__ == "__main__":
unittest.main()