mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-10 16:04:37 +08:00
fix: avoid blocking plugin release history refresh (#6084)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
from unittest.mock import ANY, AsyncMock, MagicMock, patch
|
||||
|
||||
from app.api.endpoints import plugin as plugin_endpoint
|
||||
from app import schemas
|
||||
from app.api.endpoints.plugin import plugin_history
|
||||
from app.api.endpoints.plugin import plugin_releases
|
||||
@@ -68,6 +69,38 @@ def test_plugin_history_returns_installed_plugin_when_remote_missing():
|
||||
assert result.history == {}
|
||||
|
||||
|
||||
def test_plugin_history_uses_installed_repo_without_refreshing_all_markets():
|
||||
"""
|
||||
已安装插件记录了来源仓库时,更新说明只刷新该仓库,避免弹窗触发全市场慢刷新。
|
||||
"""
|
||||
installed_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
plugin_name="Demo Plugin",
|
||||
plugin_version="1.0.0",
|
||||
repo_url="https://github.com/demo/plugins",
|
||||
installed=True,
|
||||
)
|
||||
market_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
repo_url="https://github.com/demo/plugins",
|
||||
history={"v1.1.0": "- 新增更新说明"},
|
||||
)
|
||||
plugin_manager = MagicMock()
|
||||
plugin_manager.get_local_plugins.return_value = [installed_plugin]
|
||||
plugin_manager.get_local_repo_plugins.return_value = []
|
||||
plugin_manager.async_get_plugins_from_market = AsyncMock(return_value=[market_plugin])
|
||||
plugin_manager.async_get_online_plugins = AsyncMock(return_value=[])
|
||||
|
||||
with patch("app.api.endpoints.plugin.PluginManager", return_value=plugin_manager):
|
||||
result = asyncio.run(plugin_history("DemoPlugin", None, True))
|
||||
|
||||
assert result.history == {"v1.1.0": "- 新增更新说明"}
|
||||
plugin_manager.async_get_plugins_from_market.assert_awaited_once_with(
|
||||
"https://github.com/demo/plugins", settings.VERSION_FLAG, True
|
||||
)
|
||||
plugin_manager.async_get_online_plugins.assert_not_awaited()
|
||||
|
||||
|
||||
def test_plugin_releases_returns_supported_versions_with_latest_and_current(monkeypatch):
|
||||
"""
|
||||
release 列表接口返回可安装版本,并标记当前 package 最新版本与本地已安装版本。
|
||||
@@ -154,6 +187,7 @@ def test_plugin_releases_falls_back_to_compatible_base_package(monkeypatch):
|
||||
)
|
||||
plugin_manager.get_local_plugin_version.return_value = None
|
||||
plugin_helper = MagicMock()
|
||||
plugin_helper.async_has_plugin_release_cache = AsyncMock(return_value=False)
|
||||
plugin_helper.async_get_plugin_release_versions = AsyncMock(return_value=[])
|
||||
|
||||
with (
|
||||
@@ -185,6 +219,7 @@ def test_plugin_releases_uses_force_refresh_for_market_metadata(monkeypatch):
|
||||
plugin_manager.async_get_plugins_from_market = AsyncMock(return_value=[market_plugin])
|
||||
plugin_manager.get_local_plugin_version.return_value = None
|
||||
plugin_helper = MagicMock()
|
||||
plugin_helper.async_has_plugin_release_cache = AsyncMock(return_value=False)
|
||||
plugin_helper.async_get_plugin_release_versions = AsyncMock(return_value=[])
|
||||
|
||||
with (
|
||||
@@ -203,6 +238,100 @@ def test_plugin_releases_uses_force_refresh_for_market_metadata(monkeypatch):
|
||||
)
|
||||
|
||||
|
||||
def test_plugin_releases_force_uses_cached_release_response_and_schedules_refresh(monkeypatch):
|
||||
"""
|
||||
手动刷新时 package 元数据仍强刷,但 Release 明细先读缓存并后台刷新,避免弹窗阻塞。
|
||||
"""
|
||||
from app.core.cache import is_fresh
|
||||
|
||||
market_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
plugin_version="1.2.3",
|
||||
repo_url="https://github.com/demo/plugins",
|
||||
release=True,
|
||||
)
|
||||
plugin_manager = MagicMock()
|
||||
plugin_manager.async_get_plugins_from_market = AsyncMock(return_value=[market_plugin])
|
||||
plugin_manager.get_local_plugin_version.return_value = None
|
||||
fresh_states = []
|
||||
plugin_helper = MagicMock()
|
||||
plugin_helper.async_has_plugin_release_cache = AsyncMock(return_value=True)
|
||||
|
||||
async def fake_releases(*_args):
|
||||
fresh_states.append(is_fresh())
|
||||
return [
|
||||
{
|
||||
"version": "1.2.3",
|
||||
"tag_name": "DemoPlugin_v1.2.3",
|
||||
"asset_name": "demoplugin_v1.2.3.zip",
|
||||
}
|
||||
]
|
||||
|
||||
plugin_helper.async_get_plugin_release_versions = fake_releases
|
||||
scheduled = []
|
||||
|
||||
def fake_schedule(plugin_id, repo_url):
|
||||
scheduled.append((plugin_id, repo_url))
|
||||
|
||||
with (
|
||||
patch("app.api.endpoints.plugin.PluginManager", return_value=plugin_manager),
|
||||
patch("app.api.endpoints.plugin.PluginHelper", return_value=plugin_helper),
|
||||
patch.object(plugin_endpoint, "_schedule_plugin_release_refresh", fake_schedule),
|
||||
):
|
||||
result = asyncio.run(plugin_releases("DemoPlugin", None, "https://github.com/demo/plugins", True))
|
||||
|
||||
assert result["release_supported"] is True
|
||||
assert fresh_states == [False]
|
||||
assert scheduled == [("DemoPlugin", "https://github.com/demo/plugins")]
|
||||
plugin_helper.async_has_plugin_release_cache.assert_awaited_once_with(
|
||||
"https://github.com/demo/plugins"
|
||||
)
|
||||
plugin_manager.async_get_plugins_from_market.assert_awaited_once_with(
|
||||
"https://github.com/demo/plugins", settings.VERSION_FLAG, True
|
||||
)
|
||||
|
||||
|
||||
def test_plugin_releases_force_skips_background_refresh_without_release_cache(monkeypatch):
|
||||
"""
|
||||
冷缓存 force 请求已在响应路径读取 Release,不能马上再启动一次重复强刷。
|
||||
"""
|
||||
market_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
plugin_version="1.2.3",
|
||||
repo_url="https://github.com/demo/plugins",
|
||||
release=True,
|
||||
)
|
||||
plugin_manager = MagicMock()
|
||||
plugin_manager.async_get_plugins_from_market = AsyncMock(return_value=[market_plugin])
|
||||
plugin_manager.get_local_plugin_version.return_value = None
|
||||
plugin_helper = MagicMock()
|
||||
plugin_helper.async_has_plugin_release_cache = AsyncMock(return_value=False)
|
||||
plugin_helper.async_get_plugin_release_versions = AsyncMock(return_value=[
|
||||
{
|
||||
"version": "1.2.3",
|
||||
"tag_name": "DemoPlugin_v1.2.3",
|
||||
"asset_name": "demoplugin_v1.2.3.zip",
|
||||
}
|
||||
])
|
||||
scheduled = []
|
||||
|
||||
def fake_schedule(plugin_id, repo_url):
|
||||
scheduled.append((plugin_id, repo_url))
|
||||
|
||||
with (
|
||||
patch("app.api.endpoints.plugin.PluginManager", return_value=plugin_manager),
|
||||
patch("app.api.endpoints.plugin.PluginHelper", return_value=plugin_helper),
|
||||
patch.object(plugin_endpoint, "_schedule_plugin_release_refresh", fake_schedule),
|
||||
):
|
||||
result = asyncio.run(plugin_releases("DemoPlugin", None, "https://github.com/demo/plugins", True))
|
||||
|
||||
assert result["release_supported"] is True
|
||||
assert scheduled == []
|
||||
plugin_helper.async_has_plugin_release_cache.assert_awaited_once_with(
|
||||
"https://github.com/demo/plugins"
|
||||
)
|
||||
|
||||
|
||||
def test_plugin_releases_hides_items_when_market_plugin_does_not_enable_release(monkeypatch):
|
||||
"""
|
||||
接口是否支持 Release 安装要与当前 package 的 release 声明保持一致。
|
||||
|
||||
Reference in New Issue
Block a user