Bump version and prevent screenshot deadlock
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user