cmux/tests_v2/test_command_palette_window_scope.py
Lawrence Chen 5d63c5f035
Add command palette (Cmd+Shift+P) (#358)
Implements a VS Code-style command palette with fuzzy search,
workspace/surface switching, rename mode, and keyboard navigation.

Closes https://github.com/manaflow-ai/cmux/issues/133
2026-02-23 03:26:36 -08:00

99 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""
Regression test: command palette should open only in the active window.
Why: if command-palette toggle is broadcast to all windows, inactive windows can
end up with an open palette that steals focus once they become key.
"""
import os
import sys
import time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from cmux import cmux, cmuxError
SOCKET_PATH = os.environ.get("CMUX_SOCKET", "/tmp/cmux-debug.sock")
def _wait_until(predicate, timeout_s: float = 5.0, interval_s: float = 0.05, message: str = "timeout") -> None:
start = time.time()
while time.time() - start < timeout_s:
if predicate():
return
time.sleep(interval_s)
raise cmuxError(message)
def _palette_visible(client: cmux, window_id: str) -> bool:
res = client._call("debug.command_palette.visible", {"window_id": window_id}) or {}
return bool(res.get("visible"))
def _set_palette_visible(client: cmux, window_id: str, visible: bool) -> None:
if _palette_visible(client, window_id) == visible:
return
client._call("debug.command_palette.toggle", {"window_id": window_id})
_wait_until(
lambda: _palette_visible(client, window_id) == visible,
timeout_s=3.0,
message=f"palette in {window_id} did not become {visible}",
)
def main() -> int:
with cmux(SOCKET_PATH) as client:
client.activate_app()
time.sleep(0.2)
w1 = client.current_window()
w2 = client.new_window()
time.sleep(0.25)
ws1 = client.new_workspace(window_id=w1)
ws2 = client.new_workspace(window_id=w2)
time.sleep(0.25)
_set_palette_visible(client, w1, False)
_set_palette_visible(client, w2, False)
# Open palette in window1 and verify window2 remains untouched.
client._call("debug.command_palette.toggle", {"window_id": w1})
_wait_until(
lambda: _palette_visible(client, w1),
timeout_s=3.0,
message="window1 command palette did not open",
)
if _palette_visible(client, w2):
raise cmuxError("window2 palette became visible when toggling window1")
# Closing window1 palette should not affect window2.
client._call("debug.command_palette.toggle", {"window_id": w1})
_wait_until(
lambda: not _palette_visible(client, w1),
timeout_s=3.0,
message="window1 command palette did not close",
)
# Mirror the same check in the other direction.
client._call("debug.command_palette.toggle", {"window_id": w2})
_wait_until(
lambda: _palette_visible(client, w2),
timeout_s=3.0,
message="window2 command palette did not open",
)
if _palette_visible(client, w1):
raise cmuxError("window1 palette became visible when toggling window2")
client._call("debug.command_palette.toggle", {"window_id": w2})
_wait_until(
lambda: not _palette_visible(client, w2),
timeout_s=3.0,
message="window2 command palette did not close",
)
print("PASS: command palette is scoped to active window")
return 0
if __name__ == "__main__":
raise SystemExit(main())