mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-09-21 03:01:27 -03:00
feat(sidebar): show empty folders and create folders from the sidebar (#999)
Empty folders (tracked in the scan-recorded all_folders list, same source
the move/download destination picker uses) can now be surfaced in the
folder sidebar via a view-options toggle, dimmed when their subtree holds
no models. Folders can be created directly from the sidebar through a new
POST /api/lm/{prefix}/create-folder endpoint with library-root
containment checks; the scanner records the new directory incrementally
so the tree reflects it without a rescan.
The sidebar header moves its view toggles (tree/list, recursive, empty
folders) into a "..." menu to fit the new create-folder button.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from py.routes.handlers.model_handlers import ModelMoveHandler
|
||||
|
||||
|
||||
class FakeMoveService:
|
||||
def __init__(self, result):
|
||||
self._result = result
|
||||
self.received_path = None
|
||||
|
||||
async def create_folder(self, folder_path):
|
||||
self.received_path = folder_path
|
||||
return self._result
|
||||
|
||||
|
||||
class FakeRequest:
|
||||
def __init__(self, payload):
|
||||
self._payload = payload
|
||||
|
||||
async def json(self):
|
||||
return self._payload
|
||||
|
||||
|
||||
def _make_handler(result):
|
||||
service = FakeMoveService(result)
|
||||
handler = ModelMoveHandler(
|
||||
move_service=service, logger=logging.getLogger(__name__)
|
||||
)
|
||||
return handler, service
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_success():
|
||||
handler, service = _make_handler(
|
||||
{"success": True, "folder": "characters/anime", "created": True}
|
||||
)
|
||||
|
||||
response = await handler.create_folder(
|
||||
FakeRequest({"folder_path": "/library/characters/anime"})
|
||||
)
|
||||
|
||||
assert response.status == 200
|
||||
payload = json.loads(response.text)
|
||||
assert payload["success"] is True
|
||||
assert payload["folder"] == "characters/anime"
|
||||
assert service.received_path == "/library/characters/anime"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_missing_path():
|
||||
handler, service = _make_handler({"success": True})
|
||||
|
||||
response = await handler.create_folder(FakeRequest({}))
|
||||
|
||||
assert response.status == 400
|
||||
payload = json.loads(response.text)
|
||||
assert payload["success"] is False
|
||||
assert service.received_path is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_service_failure_maps_to_400():
|
||||
handler, _service = _make_handler(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Folder path '/etc/evil' is outside configured library directories",
|
||||
}
|
||||
)
|
||||
|
||||
response = await handler.create_folder(FakeRequest({"folder_path": "/etc/evil"}))
|
||||
|
||||
assert response.status == 400
|
||||
payload = json.loads(response.text)
|
||||
assert payload["success"] is False
|
||||
assert "outside configured library" in payload["error"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_folder_invalid_json_body():
|
||||
class BadJsonRequest:
|
||||
async def json(self):
|
||||
raise ValueError("bad json")
|
||||
|
||||
handler, _service = _make_handler({"success": True})
|
||||
|
||||
response = await handler.create_folder(BadJsonRequest())
|
||||
|
||||
assert response.status == 400
|
||||
payload = json.loads(response.text)
|
||||
assert payload["success"] is False
|
||||
Reference in New Issue
Block a user