agent-zero/tests/test_office_canvas_setup.py
Alessandro 70adbe91a0 Polish Editor and Browser surface cleanup
Remove obsolete Office markdown editor UI and handoff code now that Markdown lives in the dedicated Editor surface.

Harden the Editor modal so it opens directly into a Markdown draft and rebinds Ace to the visible root when switching surfaces.

Make Browser address Enter navigation explicit and update the canvas setup expectations for the slimmer Office shell.
2026-05-15 12:38:29 +02:00

520 lines
25 KiB
Python

from __future__ import annotations
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[1]
def read(*parts: str) -> str:
return (PROJECT_ROOT.joinpath(*parts)).read_text(encoding="utf-8")
def test_modals_are_generic_and_surfaces_own_live_surface_paths():
modals_js = read("webui", "js", "modals.js")
modals_css = read("webui", "css", "modals.css")
surfaces_js = read("webui", "js", "surfaces.js")
surfaces_css = read("webui", "css", "surfaces.css")
for forbidden in (
"right-canvas-store",
"/plugins/_browser",
"/plugins/_office",
"/plugins/_desktop",
"SINGLE_VISIBLE_MODAL_SURFACE_PATHS",
"data-canvas",
"surface-window",
):
assert forbidden not in modals_js
assert "modalStack" in modals_js
assert 'const backdrop = document.createElement("div")' in modals_js
assert "backdrop.style.display" in modals_js
assert "modalSurfaceMetadata" not in modals_js
assert "modal-content-loaded" in modals_js
assert ".surface-floating" not in modals_css
assert ".surface-switcher" not in modals_css
assert "CORE_SURFACES" in surfaces_js
assert "modalSurfaceMetadata" in surfaces_js
assert "closeSurfaceGroupModals" in surfaces_js
assert 'id: "browser"' in surfaces_js
assert 'id: "desktop"' in surfaces_js
assert 'id: "editor"' in surfaces_js
assert "/plugins/_browser/webui/main.html" in surfaces_js
assert "/plugins/_desktop/webui/main.html" in surfaces_js
assert "/plugins/_editor/webui/main.html" in surfaces_js
assert "LEGACY_SURFACE_IDS" in surfaces_js
assert '["office", "desktop"]' in surfaces_js
assert "htmlDataset.surfaceId" in surfaces_js
assert "htmlDataset.canvasSurface" in surfaces_js
assert ".surface-modal" in surfaces_css
assert ".surface-floating" in surfaces_css
assert ".surface-resize-handle" in surfaces_css
assert ".surface-switcher" in surfaces_css
assert "surface-window" not in surfaces_js + surfaces_css
def test_right_canvas_uses_desktop_surface_id_and_migrates_legacy_office_state():
canvas_store = read("webui", "components", "canvas", "right-canvas-store.js")
desktop_register = read(
"plugins",
"_desktop",
"extensions",
"webui",
"surfaces_register",
"register-desktop.js",
)
desktop_panel = read(
"plugins",
"_desktop",
"extensions",
"webui",
"right-canvas-panels",
"desktop-panel.html",
)
desktop_new_menu = read(
"plugins",
"_desktop",
"extensions",
"webui",
"right-canvas-toolbar-start",
"desktop-new-menu.html",
)
right_canvas_css = read("webui", "components", "canvas", "right-canvas.css")
desktop_web_panel = read("plugins", "_desktop", "webui", "desktop-panel.html")
editor_register = read(
"plugins",
"_editor",
"extensions",
"webui",
"right_canvas_register_surfaces",
"register-editor.js",
)
editor_panel = read(
"plugins",
"_editor",
"extensions",
"webui",
"right-canvas-panels",
"editor-panel.html",
)
editor_main = read("plugins", "_editor", "webui", "main.html")
editor_web_panel = read("plugins", "_editor", "webui", "editor-panel.html")
editor_store = read("plugins", "_editor", "webui", "editor-store.js")
editor_preview = read("plugins", "_editor", "webui", "editor-preview.js")
safe_markdown = read("webui", "js", "safe-markdown.js")
assert 'await callJsExtensions("surfaces_register", this);' in canvas_store
assert 'await callJsExtensions("right_canvas_register_surfaces", this);' in canvas_store
assert "migratePersistedSurfaceState" in canvas_store
assert "normalizeSurfaceId" in canvas_store
assert "const saved = migratePersistedSurfaceState(JSON.parse" in canvas_store
assert 'id: "desktop"' in desktop_register
assert 'modalPath: "/plugins/_desktop/webui/main.html"' in desktop_register
assert 'id: "editor"' in editor_register
assert 'title: "Editor"' in editor_register
assert 'order: 30' in editor_register
assert 'modalPath: "/plugins/_editor/webui/main.html"' in editor_register
assert 'data-surface-id="desktop"' in desktop_panel
assert "isSurfaceVisible('desktop')" in desktop_panel
assert 'data-surface-id="editor"' in editor_panel
assert "isSurfaceVisible('editor')" in editor_panel
assert 'data-surface-id="editor"' in editor_main
assert 'data-surface-modal-path="/plugins/_editor/webui/main.html"' in editor_main
assert "editor-source-editor" in editor_web_panel
assert "data-editor-source" in editor_web_panel
assert "editor-tabs" in editor_web_panel
assert "editor-new-tab" in editor_web_panel
assert 'aria-label="New Markdown"' in editor_web_panel
assert "editor-close-confirm" in editor_web_panel
assert "Save & Close" in editor_web_panel
assert "Close All" in editor_web_panel
assert "editor-document-header" not in editor_web_panel
assert "editor-document-save-button" not in editor_web_panel
assert "data-editor-ace" in editor_web_panel
assert "data-editor-preview" in editor_web_panel
assert "data-editor-preview-source" in editor_web_panel
assert "editor-mode-toggle" in editor_web_panel
assert "editor-search-bar" in editor_web_panel
assert "editor-preview-title" in editor_web_panel
assert "editor-preview-page-editor" in editor_web_panel
assert "editor-table-wrap" in editor_web_panel
assert "closeAllFiles" in editor_store
assert "confirmPendingClose" in editor_store
assert "ensureInitialMarkdownFile" in editor_store
assert "await this.ensureInitialMarkdownFile();" in editor_store
assert "startPreviewEdit" in editor_store
assert "applyPreviewEdit" in editor_store
assert "previewEditDirty" in editor_store
assert "replacePageMarkdown" in editor_store
assert "enhanceTaskLists" in editor_store
assert "togglePreviewTask" in editor_store
assert 'input[type="checkbox"]' in editor_store
assert "renderEditorPreviewMarkdown" in editor_store
assert "buildMarkdownPages" in editor_store
assert "hydrateActiveSession" in editor_store
assert "refreshSourceEditorLayout" in editor_store
assert "editor.resize?.(true)" in editor_store
assert "openSearch" in editor_store
assert "handlePreviewClick" in editor_store
assert "ace.edit" in editor_store
assert "showGutter: false" in editor_store
assert "globalThis.confirm" not in editor_store
assert ".editor-toolbar" in editor_web_panel
assert "overflow: visible;" in editor_web_panel
assert "z-index: 10000;" in editor_web_panel
assert "renderSafeMarkdown" in editor_preview
assert "prepareFootnotes" in editor_preview
assert "resolveDocumentRelativePath" in editor_preview
assert "slice(start, end)" in editor_preview
assert "allowDataImages: true" in editor_preview
assert "allowLatex: true" in editor_preview
assert "html = sanitizeHtml(html, options);" in safe_markdown
assert "right-canvas-desktop-actions" in desktop_new_menu
assert "isSurfaceActive('desktop')" in desktop_new_menu
assert "runNewMenuAction('writer')" in desktop_new_menu
assert "runNewMenuAction('spreadsheet')" in desktop_new_menu
assert "runNewMenuAction('presentation')" in desktop_new_menu
assert "runNewMenuAction('markdown')" not in desktop_new_menu
assert ".right-canvas-header" in right_canvas_css
assert "overflow: visible;" in right_canvas_css
assert ".right-canvas-toolbar" in right_canvas_css
assert ".right-canvas-desktop-actions .office-new-menu" in desktop_web_panel
assert "z-index: 4000;" in desktop_web_panel
assert not (PROJECT_ROOT / "plugins" / "_office" / "extensions" / "webui" / "right_canvas_register_surfaces" / "register-office.js").exists()
assert not (PROJECT_ROOT / "plugins" / "_office" / "extensions" / "webui" / "right-canvas-panels" / "office-panel.html").exists()
def test_browser_surface_restores_focus_mode_chrome():
browser_store = read("plugins", "_browser", "webui", "browser-store.js")
browser_panel = read("plugins", "_browser", "webui", "browser-panel.html")
assert "browser-modal-focus-button" in browser_store
assert "is-focus-mode" in browser_store
assert "fullscreen_exit" in browser_store
assert "Focus mode" in browser_store
assert "Restore size" in browser_store
assert ".modal-inner.browser-modal.is-focus-mode" in browser_panel
def test_office_frontend_is_document_only_and_does_not_import_browser_or_desktop_runtime_code():
office_store = read("plugins", "_office", "webui", "office-store.js")
office_panel = read("plugins", "_office", "webui", "office-panel.html")
office_modal = read("plugins", "_office", "webui", "main.html")
assert "/plugins/_browser" not in office_store
assert "right-canvas-store" not in office_store
assert "handleUrlIntent" not in office_store
assert "ensureDesktopSession" not in office_store
assert "desktop_save" not in office_store
assert "desktop_sync" not in office_store
assert "desktop_state" not in office_store
assert "desktop_shutdown" not in office_store
assert "Xpra" not in office_store
assert "xpra" not in office_store
assert "data-office-desktop-host" not in office_panel
assert "office-desktop-frame" not in office_panel
assert "Restart Desktop" not in office_panel
assert "data-surface-id" not in office_modal
assert "modal-no-backdrop" not in office_modal
assert "data-canvas-surface" not in office_modal
assert "office-source-editor" not in office_panel
assert "data-office-source" not in office_panel
assert "office-document-header" not in office_panel
assert "runNewMenuAction('markdown')" not in office_panel
assert 'data-office-new-action="markdown"' not in office_store
assert "openRenameModal" not in office_store
assert "office_save" not in office_store
assert 'callOffice("renamed"' not in office_store
assert "data-office-source" not in office_store
assert "office_input" not in office_store
assert "requires_desktop" in office_store
assert "openSurface(\"desktop\"" not in office_store
def test_desktop_plugin_owns_routes_runtime_surface_and_state_paths():
desktop_plugin = PROJECT_ROOT / "plugins" / "_desktop"
assert (desktop_plugin / "plugin.yaml").exists()
assert (desktop_plugin / "api" / "desktop_session.py").exists()
assert (desktop_plugin / "helpers" / "desktop_session.py").exists()
assert (desktop_plugin / "helpers" / "desktop_state.py").exists()
assert (desktop_plugin / "skills" / "linux-desktop" / "scripts" / "desktopctl.sh").exists()
desktop_startup = read("plugins", "_desktop", "extensions", "python", "startup_migration", "_20_desktop_routes.py")
desktop_api = read("plugins", "_desktop", "api", "desktop_session.py")
desktop_session = read("plugins", "_desktop", "helpers", "desktop_session.py")
desktop_state = read("plugins", "_desktop", "helpers", "desktop_state.py")
desktop_store = read("plugins", "_desktop", "webui", "desktop-store.js")
desktop_main = read("plugins", "_desktop", "webui", "main.html")
desktop_web_panel = read("plugins", "_desktop", "webui", "desktop-panel.html")
assert "virtual_desktop_routes.install_route_hooks()" in desktop_startup
assert 'action in {"open_document", "document"}' in desktop_api
assert 'if ext == "md":' in desktop_api
assert "Markdown documents use the Editor surface." in desktop_api
assert "return self._open_markdown(doc, input, request)" not in desktop_api
assert "markdown_sessions" not in desktop_api
assert '"status": desktop.get("status") or {}' in desktop_api
assert 'callJsonApi("/plugins/_desktop/desktop_session"' in desktop_store
assert 'callDesktop("open_document"' in desktop_store
assert 'callOffice("create"' in desktop_store
assert "open_in_desktop: isOfficialExtension(fmt)" in desktop_store
assert "DESKTOP_RUNTIME_INSTALL_MESSAGE" in desktop_store
assert "openDesktopWhenRuntimeReady" in desktop_store
assert "isDesktopRuntimeInstalling" in desktop_store
assert "Installing Agent Zero Desktop runtime dependencies" in desktop_session
assert "__a0XpraOffsetWarnPatched" in desktop_store
assert "window does not fit in canvas, offsets" in desktop_store
assert "decode error packet" in desktop_store
assert 'data-surface-id="desktop"' in desktop_main
assert "virtual_desktop.session_url" in desktop_session
assert 'owner="desktop"' in desktop_session
assert 'STATE_DIR = Path(files.get_abs_path("usr", "plugins", PLUGIN_NAME))' in desktop_session
assert 'STATE_DIR = BASE_DIR / "usr" / "plugins" / PLUGIN_NAME' in desktop_state
assert "> x-component > div[x-data] > .office-panel" in desktop_web_panel
assert ".office-state-line > span:not(.material-symbols-outlined)" in desktop_web_panel
assert not (PROJECT_ROOT / "plugins" / "_office" / "helpers" / "desktop_state.py").exists()
assert not (PROJECT_ROOT / "plugins" / "_office" / "helpers" / "libreoffice_desktop_routes.py").exists()
assert not (PROJECT_ROOT / "plugins" / "_office" / "assets" / "desktop").exists()
def test_plugin_owned_runtime_state_paths_are_declared():
office_documents = read("plugins", "_office", "helpers", "document_store.py")
browser_playwright = read("plugins", "_browser", "helpers", "playwright.py")
browser_extensions = read("plugins", "_browser", "helpers", "extension_manager.py")
docker_playwright = read("docker", "run", "fs", "ins", "install_playwright.sh")
assert 'PLUGIN_NAME = "_office"' in office_documents
assert 'STATE_DIR = Path(files.get_abs_path("usr", "plugins", PLUGIN_NAME, "documents"))' in office_documents
assert 'PLAYWRIGHT_CACHE_DIR = ("tmp", "playwright")' in browser_playwright
assert '"usr", "plugins", "_browser", "playwright"' in browser_playwright
assert "Path(files.get_abs_path(*PLAYWRIGHT_CACHE_DIR))" in browser_playwright
assert "find_playwright_binary(_primary_cache_dir())" in browser_playwright
assert "Path(files.get_abs_path(*EXTENSIONS_ROOT_DIR))" in browser_extensions
assert "PLAYWRIGHT_BROWSERS_PATH=/a0/tmp/playwright" in docker_playwright
def test_document_artifacts_only_open_desktop_from_explicit_document_ui_requests():
auto_open = read(
"plugins",
"_office",
"extensions",
"webui",
"set_messages_after_loop",
"auto-open-document-results.js",
)
document_actions = read("plugins", "_office", "extensions", "webui", "lib", "document-actions.js")
document_handler = read(
"plugins",
"_office",
"extensions",
"webui",
"get_tool_message_handler",
"document-artifact-handler.js",
)
response_cards = read(
"plugins",
"_office",
"extensions",
"webui",
"set_messages_after_loop",
"document-response-file-cards.js",
)
messages_css = read("webui", "css", "messages.css")
document_tool = read("plugins", "_office", "tools", "document_artifact.py")
office_api = read("plugins", "_office", "api", "office_session.py")
assert 'openSurface(surfaceForDocument' in auto_open
assert 'return documentExtension(payload, document) === "md" ? "editor" : "desktop";' in auto_open
assert "isExplicitDocumentUiRequest(payload)" in auto_open
assert 'action === "open"' in auto_open
assert "open_in_canvas" in auto_open
assert "open_in_desktop" in auto_open
assert 'surfaces.open("desktop"' not in auto_open
assert "rightCanvas.open" not in auto_open
assert "globalThis.Alpine" not in auto_open
assert "syncDocumentResultsIntoOpenSurfaces" in auto_open
assert "isOfficeCanvas" not in auto_open
assert "officeStore" in auto_open
assert "desktopStore" in auto_open
assert "editorStore" in auto_open
assert "store?.previewEditDirty" in auto_open
assert "syncOpenEditorSurface" in auto_open
assert "isEditorSurfaceOpen" in auto_open
assert "syncOpenDesktopCanvas" in auto_open
assert "syncOpenOfficeModal" in auto_open
assert "isDesktopSurfaceOpen" in auto_open
assert "function documentTarget(payload = {}, document = {})" in auto_open
assert "syncTextEditorMarkdownResult" in auto_open
assert "textEditorTarget" in auto_open
assert 'toolName === "text_editor"' in auto_open
assert 'return ["write", "patch"].includes(action);' in auto_open
assert "void syncOpenDocumentSurfaces(target);" in auto_open
assert "void syncOpenDocumentSurfaces({ path, file_id: fileId });" not in auto_open
assert "return documentExtension(payload, document) === \"md\" ? \"editor\" : \"desktop\";" in auto_open
assert "hasSameDocument" in auto_open
assert 'source: "tool-result-sync"' in auto_open
assert '".modal .office-panel"' not in auto_open
assert "normalizeDocumentMetadata" in document_actions
assert "buildDocumentFileCard" in document_actions
assert "document-file-card" in document_actions
assert "buildDocumentFileCard" not in document_handler
assert "buildDocumentFileActionButtons" not in document_handler
assert "document-file-card-wrapper" not in document_handler
assert "message-document-artifact" not in document_handler
assert "actionButtons: []" in document_handler
assert "injectDocumentCardsIntoFinalResponses" in response_cards
assert "buildDocumentFileCard" in response_cards
assert "buildDocumentFileActionButtons" in response_cards
assert "message-agent-response" in response_cards
assert "document-response-file-cards" in response_cards
assert "document-response-file-action" in response_cards
assert "RESPONSE_CARD_ACTIONS" in response_cards
assert "documentIdentityKey" in response_cards
assert "uniqueByDocument" in response_cards
assert "PENDING_TTL_MS" in response_cards
assert "pendingContextId" in response_cards
assert "globalThis.getContext" in response_cards
assert "prunePendingDocuments" in response_cards
assert "wrapper.dataset.documents" in response_cards
assert "refreshResponseFileActions" in response_cards
assert "parseStoredDocuments" in response_cards
assert "openDocumentInDesktop" in document_actions
assert "openDocumentInEditor" in document_actions
assert "openDocumentArtifact" in document_actions
assert 'await openSurface("editor"' in document_actions
assert "await openDocumentInEditor(document);" in document_actions
assert "await openDocumentInDesktop(document);" in document_actions
assert 'ensureModalOpen("/plugins/_office/webui/main.html")' not in document_actions
assert 'ensureModalOpen("/plugins/_office/webui/main.html")' not in auto_open
assert "Open in canvas" in document_actions
assert "Copy path" not in document_actions
assert "copyToClipboard" not in document_actions
assert "Details" not in document_handler
assert "Details" not in response_cards
assert "/api/download_work_dir_file" in document_actions
assert 'openSurface("desktop"' in document_actions
assert 'openSurface("editor"' in document_actions
assert "Open in canvas with Writer" in document_actions
assert "Open in canvas with Calc" in document_actions
assert "Open in canvas with Impress" in document_actions
assert 'const EDITOR_FORMATS = ["md"]' in document_actions
assert 'const DESKTOP_FORMATS = ["odt", "ods", "odp", "docx", "xlsx", "pptx"]' in document_actions
assert ".document-file-card" in messages_css
assert ".document-response-file-cards" in messages_css
assert ".document-file-action-label" not in messages_css
assert ".process-step-detail-content.document-file-card-wrapper" not in messages_css
assert "open_in_canvas: bool = False" in document_tool
assert '"open_in_canvas": bool(open_in_canvas)' in document_tool
assert '"open_in_desktop": bool(open_in_desktop)' in document_tool
assert '"requires_desktop": True' in office_api
assert 'input.get("open_in_desktop") is not True' in office_api
assert '"requires_editor": True' in office_api
def test_editor_plugin_owns_markdown_sessions_and_active_context_extras():
editor_plugin = PROJECT_ROOT / "plugins" / "_editor"
assert (editor_plugin / "plugin.yaml").exists()
assert (editor_plugin / "api" / "editor_session.py").exists()
assert (editor_plugin / "api" / "ws_editor.py").exists()
editor_session = read("plugins", "_editor", "helpers", "markdown_sessions.py")
editor_api = read("plugins", "_editor", "api", "editor_session.py")
editor_ws = read("plugins", "_editor", "api", "ws_editor.py")
editor_context = read("plugins", "_editor", "helpers", "open_files_context.py")
office_ws = read("plugins", "_office", "api", "ws_office.py")
office_markdown_sessions = read("plugins", "_office", "helpers", "markdown_sessions.py")
editor_extras = read(
"plugins",
"_editor",
"extensions",
"python",
"message_loop_prompts_after",
"_55_include_editor_open_files.py",
)
desktop_context = read(
"plugins",
"_desktop",
"extensions",
"python",
"message_loop_prompts_after",
"_55_include_desktop_state.py",
)
office_context = read(
"plugins",
"_office",
"extensions",
"python",
"message_loop_prompts_after",
"_55_include_office_canvas_context.py",
)
assert "context_id: str" in editor_session
assert "self._active_by_context" in editor_session
assert "def list_open" in editor_session
assert "session.context_id == context_id" in editor_session
assert "dirty" in editor_session
assert "active" in editor_session
assert 'action == "list"' in editor_api
assert 'action == "activate"' in editor_api
assert 'event == "editor_activate"' in editor_ws
assert "[EDITOR OPEN FILES]" in read("plugins", "_editor", "prompts", "agent.extras.editor_open_files.md")
assert "Content is omitted" in editor_context
assert "self.agent.context.id" in editor_extras
assert "editor_open_files" in editor_extras
assert "desktop_state" in desktop_context
assert 'pop("office_canvas"' in office_context
assert "Markdown editing moved to /plugins/_editor." in office_ws
assert "from plugins._office.helpers import document_store, markdown_sessions" not in office_ws
assert "from plugins._editor.helpers.markdown_sessions import" in office_markdown_sessions
def test_office_and_desktop_skills_are_rehomed_and_renamed():
office_skills = PROJECT_ROOT / "plugins" / "_office" / "skills"
desktop_skills = PROJECT_ROOT / "plugins" / "_desktop" / "skills"
assert not (office_skills / "linux-desktop").exists()
assert (desktop_skills / "linux-desktop" / "SKILL.md").exists()
assert not (office_skills / "office-artifacts").exists()
assert not (office_skills / "word-documents").exists()
assert not (office_skills / "excel-workbooks").exists()
assert not (office_skills / "presentation-decks").exists()
expected = {
"document-artifacts": office_skills / "document-artifacts" / "SKILL.md",
"writer-documents": office_skills / "writer-documents" / "SKILL.md",
"calc-spreadsheets": office_skills / "calc-spreadsheets" / "SKILL.md",
"impress-presentations": office_skills / "impress-presentations" / "SKILL.md",
"markdown-documents": office_skills / "markdown-documents" / "SKILL.md",
}
for name, path in expected.items():
text = path.read_text(encoding="utf-8")
assert f"name: {name}" in text
desktop_skill = (desktop_skills / "linux-desktop" / "SKILL.md").read_text(encoding="utf-8")
desktopctl = (desktop_skills / "linux-desktop" / "scripts" / "desktopctl.sh").read_text(encoding="utf-8")
assert "/a0/plugins/_desktop/skills/linux-desktop/scripts/desktopctl.sh" in desktop_skill
assert "Open in Desktop action" in desktop_skill
assert "$BASE_DIR/usr/plugins/_desktop/profiles/$SESSION" in desktopctl
assert "$BASE_DIR/usr/plugins/_desktop/sessions/$SESSION.json" in desktopctl
def test_skill_catalog_and_connector_boundaries_are_static_guarded():
skills_py = read("helpers", "skills.py")
connector_list = read("plugins", "_a0_connector", "api", "v1", "skills_list.py")
connector_delete = read("plugins", "_a0_connector", "api", "v1", "skills_delete.py")
assert "RENAMED_SKILLS" not in skills_py
assert "RENAMED_SKILL_PATHS" not in skills_py
assert "_migrate_skill_name" not in skills_py
assert "_migrate_skill_path" not in skills_py
assert "Built-in plugin skills cannot be deleted" in skills_py
assert "list_skill_catalog" in connector_list
assert "list_skills(" not in connector_list
assert '"origin": skill["origin"]' in connector_list
assert "list_skill_catalog" in connector_delete
assert 'match.get("origin") not in {"User", "Project"}' in connector_delete
assert "only user or project skills can be deleted" in connector_delete