mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-02 21:34:32 +08:00
Merge pull request #6666 from Aqr-K/feat/plugin-instance-target-enablement
feat(plugin): 插件实例默认调用目标与启停,未指定实例时不再兜底取第一个
This commit is contained in:
135
tests/test_plugin_instance_default_target_endpoints.py
Normal file
135
tests/test_plugin_instance_default_target_endpoints.py
Normal file
@@ -0,0 +1,135 @@
|
||||
"""插件实例默认调用目标设置与清除接口测试。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import inspect
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from app.api.dependencies.auth import get_current_active_superuser
|
||||
from app.api.endpoints import plugintarget as plugintarget_endpoint
|
||||
from app.api.endpoints.plugintarget import (
|
||||
clear_plugin_instance_default_target,
|
||||
set_plugin_instance_default_target,
|
||||
)
|
||||
|
||||
|
||||
def _depends_default(func, parameter_name: str):
|
||||
"""取出端点函数指定参数的 FastAPI Depends 默认值。"""
|
||||
return inspect.signature(func).parameters[parameter_name].default
|
||||
|
||||
|
||||
def _manager(**methods):
|
||||
"""按方法名快速拼装一个鸭子类型的 Manager 替身。"""
|
||||
return type("Manager", (), methods)()
|
||||
|
||||
|
||||
def test_both_endpoints_require_superuser_dependency():
|
||||
"""设为默认与清除默认两个端点都要求超级管理员。"""
|
||||
for func in (set_plugin_instance_default_target, clear_plugin_instance_default_target):
|
||||
depends = _depends_default(func, "_")
|
||||
assert depends.dependency is get_current_active_superuser
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# PUT /instances/{plugin_id}/{instance_id}/default_target
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
def test_put_delegates_to_manager_and_reports_success(monkeypatch):
|
||||
"""设置请求原样转交给 Manager,命中时返回成功。"""
|
||||
calls: list = []
|
||||
manager = _manager(
|
||||
set_plugin_instance_default_target=lambda self, *a: (calls.append(a), True)[1]
|
||||
)
|
||||
monkeypatch.setattr(plugintarget_endpoint, "get_plugin_manager", lambda: manager)
|
||||
|
||||
result = set_plugin_instance_default_target("DemoPlugin", "DemoPluginWork", None)
|
||||
|
||||
assert result.success is True
|
||||
assert calls == [("DemoPlugin", "DemoPluginWork")]
|
||||
|
||||
|
||||
def test_put_reports_missing_instance_as_404(monkeypatch):
|
||||
"""目标实例不归属该插件时,Manager 返回 False,接口须映射为 404。"""
|
||||
manager = _manager(set_plugin_instance_default_target=lambda self, *a: False)
|
||||
monkeypatch.setattr(plugintarget_endpoint, "get_plugin_manager", lambda: manager)
|
||||
|
||||
with pytest.raises(HTTPException) as excinfo:
|
||||
set_plugin_instance_default_target("DemoPlugin", "Missing", None)
|
||||
|
||||
assert excinfo.value.status_code == 404
|
||||
|
||||
|
||||
def test_put_reports_missing_plugin_as_404(monkeypatch):
|
||||
"""插件本身不存在时返回 404。"""
|
||||
|
||||
def _raise(*_a):
|
||||
raise LookupError("插件 Missing 不存在")
|
||||
|
||||
manager = _manager(set_plugin_instance_default_target=_raise)
|
||||
monkeypatch.setattr(plugintarget_endpoint, "get_plugin_manager", lambda: manager)
|
||||
|
||||
with pytest.raises(HTTPException) as excinfo:
|
||||
set_plugin_instance_default_target("Missing", "Missing", None)
|
||||
|
||||
assert excinfo.value.status_code == 404
|
||||
|
||||
|
||||
def test_put_maps_unique_index_violation_to_409(monkeypatch):
|
||||
"""并发置位撞上条件唯一索引时映射为可重试的 409,而不是 500。"""
|
||||
|
||||
def _raise(*_a):
|
||||
raise IntegrityError("stmt", {}, Exception("unique"))
|
||||
|
||||
manager = _manager(set_plugin_instance_default_target=_raise)
|
||||
monkeypatch.setattr(plugintarget_endpoint, "get_plugin_manager", lambda: manager)
|
||||
|
||||
with pytest.raises(HTTPException) as excinfo:
|
||||
set_plugin_instance_default_target("DemoPlugin", "DemoPluginWork", None)
|
||||
|
||||
assert excinfo.value.status_code == 409
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# DELETE /instances/{plugin_id}/{instance_id}/default_target
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
def test_delete_delegates_to_manager_and_is_idempotent(monkeypatch):
|
||||
"""清除请求原样转交给 Manager,重复调用同样返回成功。"""
|
||||
calls: list = []
|
||||
manager = _manager(
|
||||
clear_plugin_instance_default_target=lambda self, *a: calls.append(a)
|
||||
)
|
||||
monkeypatch.setattr(plugintarget_endpoint, "get_plugin_manager", lambda: manager)
|
||||
|
||||
first = clear_plugin_instance_default_target("DemoPlugin", "DemoPluginWork", None)
|
||||
second = clear_plugin_instance_default_target("DemoPlugin", "DemoPluginWork", None)
|
||||
|
||||
assert first.success is True
|
||||
assert second.success is True
|
||||
assert calls == [("DemoPlugin", "DemoPluginWork"), ("DemoPlugin", "DemoPluginWork")]
|
||||
|
||||
|
||||
def test_delete_reports_missing_plugin_as_404(monkeypatch):
|
||||
"""插件本身不存在时返回 404。"""
|
||||
|
||||
def _raise(*_a):
|
||||
raise LookupError("插件 Missing 不存在")
|
||||
|
||||
manager = _manager(clear_plugin_instance_default_target=_raise)
|
||||
monkeypatch.setattr(plugintarget_endpoint, "get_plugin_manager", lambda: manager)
|
||||
|
||||
with pytest.raises(HTTPException) as excinfo:
|
||||
clear_plugin_instance_default_target("Missing", "Missing", None)
|
||||
|
||||
assert excinfo.value.status_code == 404
|
||||
|
||||
|
||||
def test_router_registers_default_target_paths():
|
||||
"""路由器暴露设为默认与清除默认两个路径,注册在插件前缀下。"""
|
||||
paths = {route.path for route in plugintarget_endpoint.router.routes}
|
||||
assert "/instances/{plugin_id}/{instance_id}/default_target" in paths
|
||||
Reference in New Issue
Block a user