mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-18 18:16:38 +03:00
feat(webui): add native workspace folder picker
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from nanobot.webui import native_folder_picker as picker
|
||||
|
||||
|
||||
def _picker_script(tmp_path: Path, body: str) -> Path:
|
||||
script = tmp_path / "picker.sh"
|
||||
script.write_text(f"#!/bin/sh\n{body}\n", encoding="utf-8")
|
||||
script.chmod(0o755)
|
||||
return script
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pick_native_folder_returns_selected_directory(tmp_path, monkeypatch) -> None:
|
||||
selected = tmp_path / "project"
|
||||
selected.mkdir()
|
||||
script = _picker_script(tmp_path, f"printf '%s' '{selected}'")
|
||||
monkeypatch.setattr(
|
||||
picker,
|
||||
"_picker_command",
|
||||
lambda: picker._PickerCommand((str(script),), frozenset({1})),
|
||||
)
|
||||
|
||||
assert await picker.pick_native_folder() == str(selected)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pick_native_folder_maps_dialog_cancel_to_none(tmp_path, monkeypatch) -> None:
|
||||
script = _picker_script(tmp_path, "exit 1")
|
||||
monkeypatch.setattr(
|
||||
picker,
|
||||
"_picker_command",
|
||||
lambda: picker._PickerCommand((str(script),), frozenset({1})),
|
||||
)
|
||||
|
||||
assert await picker.pick_native_folder() is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pick_native_folder_rejects_non_directory_result(tmp_path, monkeypatch) -> None:
|
||||
missing = tmp_path / "missing"
|
||||
script = _picker_script(tmp_path, f"printf '%s' '{missing}'")
|
||||
monkeypatch.setattr(
|
||||
picker,
|
||||
"_picker_command",
|
||||
lambda: picker._PickerCommand((str(script),), frozenset({1})),
|
||||
)
|
||||
|
||||
with pytest.raises(picker.NativeFolderPickerError, match="invalid directory"):
|
||||
await picker.pick_native_folder()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pick_native_folder_reports_unavailable(monkeypatch) -> None:
|
||||
monkeypatch.setattr(picker, "_picker_command", lambda: None)
|
||||
|
||||
assert picker.native_folder_picker_available() is False
|
||||
with pytest.raises(picker.NativeFolderPickerError, match="unavailable"):
|
||||
await picker.pick_native_folder()
|
||||
@@ -72,6 +72,7 @@ def test_workspace_payload_is_config_data_dir_scoped(tmp_path, monkeypatch) -> N
|
||||
assert payload["default_scope"]["access_mode"] == "full"
|
||||
assert payload["default_access_mode"] == "default"
|
||||
assert payload["controls"]["can_change_project"] is True
|
||||
assert payload["controls"]["can_pick_folder"] is False
|
||||
|
||||
|
||||
def test_workspace_payload_hides_mutable_state_when_controls_unavailable(
|
||||
@@ -91,6 +92,22 @@ def test_workspace_payload_hides_mutable_state_when_controls_unavailable(
|
||||
assert payload["default_scope"]["project_path"] == str(default.resolve())
|
||||
assert payload["controls"]["can_change_project"] is False
|
||||
assert payload["controls"]["can_use_full_access"] is False
|
||||
assert payload["controls"]["can_pick_folder"] is False
|
||||
|
||||
|
||||
def test_workspace_payload_advertises_native_folder_picker(tmp_path, monkeypatch) -> None:
|
||||
monkeypatch.setattr("nanobot.webui.workspaces.get_webui_dir", lambda: tmp_path / "webui")
|
||||
default = tmp_path / "default"
|
||||
default.mkdir()
|
||||
|
||||
payload = workspaces_payload(
|
||||
default_workspace=default,
|
||||
default_restrict_to_workspace=False,
|
||||
controls_available=True,
|
||||
folder_picker_available=True,
|
||||
)
|
||||
|
||||
assert payload["controls"]["can_pick_folder"] is True
|
||||
|
||||
|
||||
def test_workspace_payload_uses_webui_default_access_mode(tmp_path, monkeypatch) -> None:
|
||||
|
||||
Reference in New Issue
Block a user