Skip to content

Commit

Permalink
Backport PR jupyter-server#288 on branch 2.x (Fix tests)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrochart committed Nov 29, 2024
1 parent 8f8a1ca commit af6d5c0
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 16 deletions.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ test = [
"pre-commit",
"pytest",
"pytest-asyncio",
"websockets >=10.0",
"httpx-ws >=0.5.2",
"hypercorn >=0.16.0",
"pycrdt-websocket >=0.15.0,<0.16.0",
]
docs = [
Expand Down
37 changes: 26 additions & 11 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@

import json
import subprocess
from functools import partial
from pathlib import Path

import pytest
from pycrdt_websocket import WebsocketServer
from websockets import serve # type: ignore
from anyio import Event, create_task_group
from hypercorn import Config
from hypercorn.asyncio import serve
from pycrdt_websocket import ASGIServer, WebsocketServer
from utils import ensure_server_running

# workaround until these PRs are merged:
# - https://github.com/yjs/y-websocket/pull/104
Expand All @@ -27,22 +31,33 @@ def update_json_file(path: Path, d: dict):


@pytest.fixture
async def yws_server(request):
async def yws_server(request, unused_tcp_port):
try:
kwargs = request.param
except Exception:
kwargs = {}
websocket_server = WebsocketServer(**kwargs)
try:
async with websocket_server, serve(websocket_server.serve, "localhost", 1234):
yield websocket_server
async with create_task_group() as tg:
try:
kwargs = request.param
except Exception:
kwargs = {}
websocket_server = WebsocketServer(**kwargs)
app = ASGIServer(websocket_server)
config = Config()
config.bind = [f"localhost:{unused_tcp_port}"]
shutdown_event = Event()
async with websocket_server as websocket_server:
tg.start_soon(
partial(serve, app, config, shutdown_trigger=shutdown_event.wait, mode="asgi")
)
await ensure_server_running("localhost", unused_tcp_port)
pytest.port = unused_tcp_port
yield unused_tcp_port, websocket_server
shutdown_event.set()
except Exception:
pass


@pytest.fixture
def yjs_client(request):
client_id = request.param
p = subprocess.Popen(f"yarn node {here / 'yjs_client_'}{client_id}.js", shell=True)
p = subprocess.Popen(["node", f"{here / 'yjs_client_'}{client_id}.js", str(pytest.port)])
yield p
p.kill()
9 changes: 6 additions & 3 deletions tests/test_pycrdt_yjs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

import pytest
from anyio import Event, create_task_group, move_on_after
from httpx_ws import aconnect_ws
from pycrdt import Doc, Map
from pycrdt_websocket import WebsocketProvider
from websockets import connect # type: ignore
from utils import Websocket

from jupyter_ydoc import YNotebook
from jupyter_ydoc.utils import cast_all
Expand Down Expand Up @@ -61,10 +62,12 @@ def source(self):
@pytest.mark.asyncio
@pytest.mark.parametrize("yjs_client", "0", indirect=True)
async def test_ypy_yjs_0(yws_server, yjs_client):
port, _ = yws_server
ydoc = Doc()
ynotebook = YNotebook(ydoc)
async with connect("ws://localhost:1234/my-roomname") as websocket, WebsocketProvider(
ydoc, websocket
room_name = "my-roomname"
async with aconnect_ws(f"http://localhost:{port}/{room_name}") as websocket, WebsocketProvider(
ydoc, Websocket(websocket, room_name)
):
nb = stringify_source(json.loads((files_dir / "nb0.ipynb").read_text()))
ynotebook.source = nb
Expand Down
43 changes: 43 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from anyio import Lock, connect_tcp


class Websocket:
def __init__(self, websocket, path: str):
self._websocket = websocket
self._path = path
self._send_lock = Lock()

@property
def path(self) -> str:
return self._path

def __aiter__(self):
return self

async def __anext__(self) -> bytes:
try:
message = await self.recv()
except Exception:
raise StopAsyncIteration()
return message

async def send(self, message: bytes):
async with self._send_lock:
await self._websocket.send_bytes(message)

async def recv(self) -> bytes:
b = await self._websocket.receive_bytes()
return bytes(b)


async def ensure_server_running(host: str, port: int) -> None:
while True:
try:
await connect_tcp(host, port)
except OSError:
pass
else:
break
3 changes: 2 additions & 1 deletion tests/yjs_client_0.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
import { YNotebook } from '@jupyter/ydoc'
import { WebsocketProvider } from 'y-websocket'

const port = process.argv[2]
const notebook = new YNotebook()
const ytest = notebook.ydoc.getMap('_test')
import ws from 'ws'

const wsProvider = new WebsocketProvider(
'ws://localhost:1234', 'my-roomname',
`ws://127.0.0.1:${port}`, 'my-roomname',
notebook.ydoc,
{ WebSocketPolyfill: ws }
)
Expand Down

0 comments on commit af6d5c0

Please sign in to comment.