agent-zero/tests/test_file_browser_navigation.py
Alessandro ffddc3ebcb Promote Files into shared canvas surface
Add Files to the universal canvas rail and sidebar flow, with a reusable floating surface modal chrome that matches Browser/Desktop behavior.

Make the File Browser modal draggable/resizable with Focus mode, keep Editor on the same draggable modal helper, and preserve dock/undock handoff state.

Harden File Browser startup so empty paths resolve to the default workdir, restyle the Up control, compact New file/New folder actions, and hide Modified before Name/Size in narrow containers.

Update DOX contracts and focused regression coverage for the new Files surface, modal chrome, default-path fallback, and compact layout behavior.
2026-06-23 11:19:58 +02:00

136 lines
6.4 KiB
Python

from pathlib import Path
import sys
PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
from helpers.file_browser import FileBrowser
def read(*parts: str) -> str:
return PROJECT_ROOT.joinpath(*parts).read_text(encoding="utf-8")
def test_file_browser_remember_last_directory_defaults_enabled() -> None:
settings_source = read("helpers", "settings.py")
assert "file_browser_remember_last_directory: bool" in settings_source
assert "file_browser_remember_last_directory=get_default_value(" in settings_source
assert '"file_browser_remember_last_directory",\n True,' in settings_source
def test_file_browser_editable_path_bar_and_remembered_directory_contract() -> None:
html = read("webui", "components", "modals", "file-browser", "file-browser.html")
store = read("webui", "components", "modals", "file-browser", "file-browser-store.js")
workdir_settings = read("webui", "components", "settings", "agent", "workdir.html")
assert 'class="path-navigator"' in html
assert 'class="nav-button back-button"' in html
assert 'class="text-button back-button"' not in html
assert ".nav-button:focus-visible" in html
assert ".nav-button .material-symbols-outlined" in html
assert 'class="nav-button-label">Up</span>' in html
assert "flex-direction: column;" in html
assert ".nav-button-label" in html
assert 'x-model="$store.fileBrowser.pathInput"' in html
assert '@submit.prevent="$store.fileBrowser.submitPath()"' in html
assert "Go to directory" in html
assert "$store.fileBrowser.pathError" in html
assert "FILE_BROWSER_LAST_DIRECTORY_STORAGE_KEY" in store
assert 'callJsonApi("settings_get", null)' in store
assert "file_browser_remember_last_directory" in store
assert "getRememberedDirectory()" in store
assert "rememberCurrentDirectory(this.browser.currentPath)" in store
assert "clearRememberedDirectory()" in store
assert "scheduleMountedDefaultLoad()" in store
assert 'this.browser.currentPath = "";' in store
assert 'this.browser.parentPath = "";' in store
assert 'const requestedPath = this.normalizeOpeningPath(path) || "$WORK_DIR";' in store
assert "`/get_work_dir_files?path=${encodeURIComponent(requestedPath)}`" in store
assert 'result.current_path || (requestedPath === "$WORK_DIR" ? "/a0" : requestedPath)' in store
explicit_path_index = store.index("const explicitPath = this.normalizeOpeningPath")
remembered_path_index = store.index("const rememberedPath = !explicitPath")
assert explicit_path_index < remembered_path_index
assert "Remember last file browser location" in workdir_settings
assert "$store.settings.settings.file_browser_remember_last_directory" in workdir_settings
def test_file_browser_compact_controls_and_narrow_layout_contract() -> None:
html = read("webui", "components", "modals", "file-browser", "file-browser.html")
dox = read("webui", "components", "modals", "file-browser", "AGENTS.md")
assert 'aria-label="New file"' in html
assert 'title="New file"' in html
assert 'aria-label="New folder"' in html
assert 'title="New folder"' in html
assert ">New File<" not in html
assert ">New Folder<" not in html
assert ".btn-new-item" in html
assert "width: 2.8rem;" in html
assert "height: 2.8rem;" in html
assert "container: file-browser / inline-size;" in html
assert "@container file-browser (max-width: 620px)" in html
assert "grid-template-columns: 2.25rem minmax(0, 1fr) minmax(4.25rem, max-content) 5.25rem;" in html
assert ".file-cell-date,\n .file-date {\n display: none;" in html
assert ".file-cell-size,\n .file-size" not in html
assert "hiding the Modified date column" in dox
assert "New file and New folder controls icon-only" in dox
def test_file_browser_empty_api_path_uses_default_workdir_contract() -> None:
api_source = read("api", "get_work_dir_files.py")
api_dox = read("api", "get_work_dir_files.py.dox.md")
assert 'current_path = request.args.get("path", "") or "$WORK_DIR"' in api_source
assert 'current_path = "/a0"' in api_source
assert "Empty `path` requests and explicit `$WORK_DIR` requests resolve" in api_dox
def test_file_browser_is_registered_as_right_canvas_surface() -> None:
html = read("webui", "components", "modals", "file-browser", "file-browser.html")
store = read("webui", "components", "modals", "file-browser", "file-browser-store.js")
surfaces = read("webui", "js", "surfaces.js")
register = read("extensions", "webui", "right_canvas_register_surfaces", "register-files.js")
panel = read("extensions", "webui", "right-canvas-panels", "files-panel.html")
input_store = read("webui", "components", "chat", "input", "input-store.js")
assert 'id: "files"' in surfaces
assert 'title: "Files"' in surfaces
assert 'modalPath: "modals/file-browser/file-browser.html"' in surfaces
assert 'await store.openSurface(payload.path || payload.filePath || payload.directory || "")' in surfaces
assert 'data-surface-id="files"' in html
assert 'data-surface-modal-path="modals/file-browser/file-browser.html"' in html
assert 'class="surface-modal file-browser-modal modal-no-backdrop"' in html
assert 'class="file-browser-modal-body"' in html
assert 'x-create="$store.fileBrowser.onMount($el, xAttrs($el) || {})"' in html
assert 'x-destroy="$store.fileBrowser.onUnmount(xAttrs($el) || {})"' in html
assert ".modal-inner.file-browser-modal" in html
assert "resize: both" in html
assert "openSurface(path" in store
assert "setupFloatingSurfaceModalChrome" in store
assert 'focusButtonClass: "file-browser-modal-focus-button"' in store
assert "beginSurfaceHandoff()" in store
assert "finishSurfaceHandoff()" in store
assert 'id: "files"' in register
assert "fileBrowserStore.openSurface" in register
assert 'data-surface-id="files"' in panel
assert 'path="modals/file-browser/file-browser.html" mode="canvas"' in panel
assert 'openLatestSurface("files"' in input_store
def test_file_browser_reports_missing_directory(tmp_path: Path) -> None:
missing_directory = tmp_path / "missing"
result = FileBrowser().get_files(str(missing_directory))
assert result["entries"] == []
assert result["current_path"] == str(missing_directory)
assert result["error"] == "Directory not found"