137 lines
4.7 KiB
Python
137 lines
4.7 KiB
Python
import json
|
|
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
|
|
from src.webui.routers.plugin import management as management_module
|
|
from src.webui.routers.plugin import support as support_module
|
|
|
|
|
|
@pytest.fixture
|
|
def client(tmp_path, monkeypatch) -> TestClient:
|
|
plugins_dir = tmp_path / "plugins"
|
|
plugins_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
demo_dir = plugins_dir / "demo_plugin"
|
|
demo_dir.mkdir()
|
|
(demo_dir / "_manifest.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"manifest_version": 2,
|
|
"id": "test.demo",
|
|
"name": "Demo Plugin",
|
|
"version": "1.0.0",
|
|
"description": "demo plugin",
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
monkeypatch.setattr(management_module, "require_plugin_token", lambda _: "ok")
|
|
monkeypatch.setattr(support_module, "get_plugins_dir", lambda: plugins_dir)
|
|
|
|
app = FastAPI()
|
|
app.include_router(management_module.router, prefix="/api/webui/plugins")
|
|
return TestClient(app)
|
|
|
|
|
|
def test_installed_plugins_only_scan_plugins_dir_and_exclude_a_memorix(client: TestClient):
|
|
response = client.get("/api/webui/plugins/installed")
|
|
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload["success"] is True
|
|
|
|
ids = [plugin["id"] for plugin in payload["plugins"]]
|
|
assert ids == ["test.demo"]
|
|
assert "a-dawn.a-memorix" not in ids
|
|
assert all("/src/plugins/built_in/" not in plugin["path"] for plugin in payload["plugins"])
|
|
|
|
|
|
def test_resolve_installed_plugin_path_falls_back_to_manifest_id(client: TestClient):
|
|
plugin_path = support_module.resolve_installed_plugin_path("test.demo")
|
|
|
|
assert plugin_path is not None
|
|
assert plugin_path.name == "demo_plugin"
|
|
|
|
|
|
def test_resolve_installed_plugin_path_accepts_manifest_id_case_mismatch(client: TestClient):
|
|
plugin_path = support_module.resolve_installed_plugin_path("Test.Demo")
|
|
|
|
assert plugin_path is not None
|
|
assert plugin_path.name == "demo_plugin"
|
|
|
|
|
|
def test_install_plugin_preserves_manifest_declared_id(client: TestClient, monkeypatch):
|
|
class FakeGitMirrorService:
|
|
async def clone_repository(self, **kwargs):
|
|
target_path = kwargs["target_path"]
|
|
target_path.mkdir(parents=True, exist_ok=True)
|
|
(target_path / "_manifest.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"manifest_version": 2,
|
|
"id": "author.declared",
|
|
"name": "Declared Plugin",
|
|
"version": "1.0.0",
|
|
"author": {"name": "author"},
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
return {"success": True}
|
|
|
|
monkeypatch.setattr(management_module, "get_git_mirror_service", lambda: FakeGitMirrorService())
|
|
|
|
response = client.post(
|
|
"/api/webui/plugins/install",
|
|
json={
|
|
"plugin_id": "market.plugin",
|
|
"repository_url": "https://github.com/author/declared",
|
|
"branch": "main",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
plugin_path = support_module.resolve_installed_plugin_path("author.declared")
|
|
assert plugin_path is not None
|
|
manifest = json.loads((plugin_path / "_manifest.json").read_text(encoding="utf-8"))
|
|
assert manifest["id"] == "author.declared"
|
|
|
|
|
|
def test_install_plugin_backfills_missing_manifest_id(client: TestClient, monkeypatch):
|
|
class FakeGitMirrorService:
|
|
async def clone_repository(self, **kwargs):
|
|
target_path = kwargs["target_path"]
|
|
target_path.mkdir(parents=True, exist_ok=True)
|
|
(target_path / "_manifest.json").write_text(
|
|
json.dumps(
|
|
{
|
|
"manifest_version": 2,
|
|
"name": "Legacy Plugin",
|
|
"version": "1.0.0",
|
|
"author": {"name": "author"},
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
return {"success": True}
|
|
|
|
monkeypatch.setattr(management_module, "get_git_mirror_service", lambda: FakeGitMirrorService())
|
|
|
|
response = client.post(
|
|
"/api/webui/plugins/install",
|
|
json={
|
|
"plugin_id": "market.legacy",
|
|
"repository_url": "https://github.com/author/legacy",
|
|
"branch": "main",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
plugin_path = support_module.resolve_installed_plugin_path("market.legacy")
|
|
assert plugin_path is not None
|
|
manifest = json.loads((plugin_path / "_manifest.json").read_text(encoding="utf-8"))
|
|
assert manifest["id"] == "market.legacy"
|