Files
Octop/tests/unit/api/test_workspace_io_path.py
006f141d84 Fix/remote browser drag (#50)
* feat(browser): support real remote drag with shared canvas pointer

Forward CDP mousedown/mousemove/mouseup (with clickCount) so remote
browser and desktop can drag instead of pan-to-scroll, and share a
connecting indicator while the stream starts.



* fix(chat): restore loading earlier messages on scroll up

Keep the load-older gate armed across virtual list updates, release
the in-flight latch when history declines to start, and expose a
clickable fallback when the list does not overflow.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(workspace): clarify path semantics with from_workspace

Add from_workspace so workspace UI keeps leading-slash relative paths
while chat/tool downloads can pass host-absolute send_file paths
through BackendWorkspace, with a host download allowlist.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(workspace): preserve chat document path semantics

* fix(workspace): harden file URL and host path checks on Windows

Preserve Unix-style file:// paths instead of url2pathname backslashes,
decode percent-encoded segments, and deny POSIX system roots like /etc
before Path.resolve() on Windows.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(workspace): decode Windows file URLs to native paths

Unquote percent-encoded segments in file:///C:/… URLs and normalize
via Path so send_file enrichment matches str(Path.resolve()) on Windows.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: jubaoliang <jubaoliang@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 15:26:52 +08:00

44 lines
1.5 KiB
Python

"""Workspace I/O path resolution for download / file APIs."""
from __future__ import annotations
from octop.api.routers.workspace import _workspace_io_path
def test_from_workspace_false_slash_is_host_absolute() -> None:
abs_path = "/Users/jubaoliang/Desktop/IronMan_PPT/钢铁侠.pptx"
assert _workspace_io_path(abs_path, from_workspace=False) == abs_path
assert _workspace_io_path("/logo.png", from_workspace=False) == "/logo.png"
def test_from_workspace_true_slash_is_workspace_relative() -> None:
assert _workspace_io_path("/logo.png", from_workspace=True) == "logo.png"
assert _workspace_io_path("/outbound/a.pptx", from_workspace=True) == "outbound/a.pptx"
assert _workspace_io_path("/", from_workspace=True) == "."
def test_relative_without_slash_always_workspace() -> None:
assert (
_workspace_io_path("generated/water-ppt/a.pptx", from_workspace=False)
== "generated/water-ppt/a.pptx"
)
assert (
_workspace_io_path("generated/water-ppt/a.pptx", from_workspace=True)
== "generated/water-ppt/a.pptx"
)
def test_file_url_always_host_absolute() -> None:
assert (
_workspace_io_path("file:///Users/me/report.pptx", from_workspace=False)
== "/Users/me/report.pptx"
)
assert (
_workspace_io_path("file:///Users/me/report.pptx", from_workspace=True)
== "/Users/me/report.pptx"
)
def test_default_from_workspace_is_false() -> None:
assert _workspace_io_path("/Users/me/a.pptx") == "/Users/me/a.pptx"