Add Docker exec PTY sessions

This commit is contained in:
GitHub Copilot
2026-01-29 13:18:31 +00:00
parent 74a2e31a55
commit 8dc16b59e2
7 changed files with 409 additions and 18 deletions
+12 -7
View File
@@ -6,7 +6,12 @@ from unittest.mock import AsyncMock, MagicMock
import pytest
from webterm.docker_watcher import LABEL_NAME, THEME_LABEL, DockerWatcher, _get_auto_command
from webterm.docker_watcher import (
AUTO_COMMAND_SENTINEL,
LABEL_NAME,
THEME_LABEL,
DockerWatcher,
)
@pytest.fixture
@@ -56,8 +61,7 @@ class TestDockerWatcher:
def test_get_container_command_auto(self, docker_watcher):
"""Test command generation when label is 'auto'."""
container = {"Names": ["/my-container"], "Labels": {LABEL_NAME: "auto"}}
expected = f"docker exec -it my-container {_get_auto_command()}"
assert docker_watcher._get_container_command(container) == expected
assert docker_watcher._get_container_command(container) == AUTO_COMMAND_SENTINEL
def test_get_container_command_custom(self, docker_watcher):
"""Test command when label has custom value."""
@@ -93,7 +97,7 @@ class TestDockerWatcher:
session_manager.add_app.assert_called_once()
call_args = session_manager.add_app.call_args
assert call_args[0][0] == "test-container" # name
assert "docker exec -it test-container" in call_args[0][1] # command
assert call_args[0][1] == AUTO_COMMAND_SENTINEL # command
assert call_args[0][2] == "test-container" # slug
assert call_args[1]["terminal"] is True
assert call_args[1]["theme"] == "monokai"
@@ -235,8 +239,9 @@ class TestDockerWatcherIntegration:
("labels", "expected"),
[
({"webterm-command": "echo hi"}, "echo hi"),
({"webterm-command": "auto"}, f"docker exec -it my-container {_get_auto_command()}"),
({"other": "value"}, f"docker exec -it my-container {_get_auto_command()}"),
({"webterm-command": "auto"}, AUTO_COMMAND_SENTINEL),
({"webterm-command": ""}, AUTO_COMMAND_SENTINEL),
({"other": "value"}, AUTO_COMMAND_SENTINEL),
],
)
def test_get_container_command_variants(docker_watcher, labels, expected):
@@ -247,7 +252,7 @@ def test_get_container_command_variants(docker_watcher, labels, expected):
def test_auto_command_env_override(monkeypatch, docker_watcher):
monkeypatch.setenv("WEBTERM_DOCKER_AUTO_COMMAND", "/bin/sh")
container = {"Names": ["/my-container"], "Labels": {LABEL_NAME: "auto"}}
assert docker_watcher._get_container_command(container) == "docker exec -it my-container /bin/sh"
assert docker_watcher._get_container_command(container) == AUTO_COMMAND_SENTINEL
@pytest.mark.asyncio
+25
View File
@@ -6,6 +6,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from webterm.config import App
from webterm.docker_watcher import AUTO_COMMAND_SENTINEL
from webterm.session_manager import SessionManager
from webterm.types import RouteKey, SessionID
@@ -190,6 +191,30 @@ class TestSessionManager:
assert SessionID("test-session") in manager.sessions
assert RouteKey("test-route") in manager.routes
@pytest.mark.asyncio
@pytest.mark.skipif(platform.system() == "Windows", reason="Terminal not supported on Windows")
async def test_new_docker_exec_session(self, mock_poller, mock_path):
from webterm.docker_exec_session import DockerExecSession
app = App(
name="my-container",
slug="my-container",
path="./",
command=AUTO_COMMAND_SENTINEL,
terminal=True,
)
manager = SessionManager(mock_poller, mock_path, [app])
with patch.object(DockerExecSession, "open", new_callable=AsyncMock):
result = await manager.new_session(
"my-container",
SessionID("test-session"),
RouteKey("test-route"),
)
assert result is not None
assert isinstance(result, DockerExecSession)
class TestSessionManagerRoutes:
"""Tests for SessionManager route handling."""