Bump version and prevent screenshot deadlock

This commit is contained in:
GitHub Copilot
2026-01-28 13:30:21 +00:00
parent 216380405a
commit 69f0e2748f
5 changed files with 203 additions and 74 deletions
@@ -1,6 +1,8 @@
from __future__ import annotations
import json
from contextlib import asynccontextmanager
from typing import TYPE_CHECKING
from unittest.mock import AsyncMock
import pytest
@@ -9,7 +11,10 @@ from aiohttp.test_utils import TestClient, TestServer
from textual_webterm.config import App, Config
from textual_webterm.local_server import LocalServer
from textual_webterm.types import RouteKey, SessionID
if TYPE_CHECKING:
from collections.abc import AsyncIterator
async def _make_client(server: LocalServer) -> TestClient:
app = web.Application()
@@ -20,6 +25,36 @@ async def _make_client(server: LocalServer) -> TestClient:
return client
@pytest.fixture
def server_factory(tmp_path):
counter = {"i": 0}
def _make(apps: list[App] | None = None) -> LocalServer:
counter["i"] += 1
config = Config(
apps=apps
or [App(name="Test", slug="test", path=".", command="echo test", terminal=True)]
)
config_file = tmp_path / f"config-{counter['i']}.toml"
config_file.write_text("")
return LocalServer(config_path=str(config_file), config=config)
return _make
@pytest.fixture
def client_factory():
@asynccontextmanager
async def _factory(server: LocalServer) -> AsyncIterator[TestClient]:
client = await _make_client(server)
try:
yield client
finally:
await client.close()
return _factory
@pytest.mark.asyncio
async def test_websocket_creates_session_on_resize(tmp_path):
config = Config(
@@ -121,3 +156,51 @@ async def test_websocket_ignores_invalid_envelopes(tmp_path):
await ws.close()
finally:
await client.close()
@pytest.mark.asyncio
@pytest.mark.parametrize(
("payload", "is_binary"),
[
("not json", False),
(json.dumps({"not": "a list"}), False),
(json.dumps([]), False),
(b"\x00\x01\x02", True),
],
)
async def test_websocket_invalid_payloads_keep_connection(
server_factory, client_factory, payload, is_binary
):
server = server_factory()
async with client_factory(server) as client:
ws = await client.ws_connect("/ws/test")
if is_binary:
await ws.send_bytes(payload)
else:
await ws.send_str(payload)
await ws.send_str(json.dumps(["ping", "ok"]))
msg = await ws.receive(timeout=1)
assert msg.type == WSMsgType.TEXT
assert json.loads(msg.data) == ["pong", "ok"]
await ws.close()
@pytest.mark.asyncio
async def test_websocket_clears_stale_session(server_factory, client_factory):
server = server_factory()
class DummySession:
def is_running(self):
return False
session_id = SessionID("sid")
route_key = RouteKey("test")
server.session_manager.routes[route_key] = session_id
server.session_manager.sessions[session_id] = DummySession()
async with client_factory(server) as client:
ws = await client.ws_connect("/ws/test")
assert server.session_manager.get_session(session_id) is None
assert server.session_manager.routes.get(route_key) is None
await ws.close()