-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Drop YTest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
734f4d2
commit 1671747
Showing
3 changed files
with
57 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,69 @@ | ||
from __future__ import annotations | ||
|
||
from functools import partial | ||
|
||
import pytest | ||
from anyio import Event, create_task_group, move_on_after, sleep | ||
from anyio import Event, fail_after | ||
from pycrdt import Array, Doc, Map | ||
from websockets import connect | ||
|
||
from pycrdt_websocket import WebsocketProvider | ||
|
||
|
||
class YTest: | ||
def __init__(self, ydoc: Doc, timeout: float = 1.0): | ||
self.ydoc = ydoc | ||
class Change: | ||
def __init__(self, event, timeout, ydata, sid, key): | ||
self.event = event | ||
self.timeout = timeout | ||
self.ydoc["_test"] = self.ytest = Map() | ||
self.clock = -1.0 | ||
self.ydata = ydata | ||
self.sid = sid | ||
self.key = key | ||
|
||
def run_clock(self): | ||
self.clock = max(self.clock, 0.0) | ||
self.ytest["clock"] = self.clock | ||
async def wait(self): | ||
with fail_after(self.timeout): | ||
await self.event.wait() | ||
self.ydata.unobserve(self.sid) | ||
if self.key is None: | ||
return | ||
return self.ydata[self.key] | ||
|
||
async def clock_run(self): | ||
change = Event() | ||
|
||
def callback(event): | ||
if "clock" in event.keys: | ||
clk = event.keys["clock"]["newValue"] | ||
if clk > self.clock: | ||
self.clock = clk + 1.0 | ||
change.set() | ||
def callback(change_event, key, event): | ||
if key is None or key in event.keys: | ||
change_event.set() | ||
|
||
subscription_id = self.ytest.observe(callback) | ||
async with create_task_group(): | ||
with move_on_after(self.timeout): | ||
await change.wait() | ||
|
||
self.ytest.unobserve(subscription_id) | ||
def watch(ydata, key: str | None = None, timeout: float = 1.0): | ||
change_event = Event() | ||
sid = ydata.observe(partial(callback, change_event, key)) | ||
return Change(change_event, timeout, ydata, sid, key) | ||
|
||
|
||
@pytest.mark.anyio | ||
@pytest.mark.parametrize("yjs_client", "0", indirect=True) | ||
async def test_pycrdt_yjs_0(yws_server, yjs_client): | ||
ydoc = Doc() | ||
ytest = YTest(ydoc) | ||
async with connect("ws://127.0.0.1:1234/my-roomname") as websocket, WebsocketProvider( | ||
ydoc, websocket | ||
): | ||
ydoc["map"] = ymap = Map() | ||
# set a value in "in" | ||
for v_in in range(10): | ||
ymap["in"] = float(v_in) | ||
ytest.run_clock() | ||
await ytest.clock_run() | ||
v_out = ymap["out"] | ||
v_out = await watch(ymap, "out").wait() | ||
assert v_out == v_in + 1.0 | ||
|
||
|
||
@pytest.mark.anyio | ||
@pytest.mark.parametrize("yjs_client", "1", indirect=True) | ||
async def test_pycrdt_yjs_1(yws_server, yjs_client): | ||
# wait for the JS client to connect | ||
tt, dt = 0, 0.1 | ||
while True: | ||
await sleep(dt) | ||
if "/my-roomname" in yws_server.rooms: | ||
break | ||
tt += dt | ||
if tt >= 1: | ||
raise RuntimeError("Timeout waiting for client to connect") | ||
ydoc = yws_server.rooms["/my-roomname"].ydoc | ||
ytest = YTest(ydoc) | ||
ytest.run_clock() | ||
await ytest.clock_run() | ||
ydoc = Doc() | ||
ydoc["cells"] = ycells = Array() | ||
ydoc["state"] = ystate = Map() | ||
assert ycells.to_py() == [{"metadata": {"foo": "bar"}, "source": "1 + 2"}] | ||
assert ystate.to_py() == {"state": {"dirty": False}} | ||
ycells_change = watch(ycells) | ||
ystate_change = watch(ystate) | ||
async with connect("ws://127.0.0.1:1234/my-roomname") as websocket, WebsocketProvider( | ||
ydoc, websocket | ||
): | ||
await ycells_change.wait() | ||
await ystate_change.wait() | ||
assert ycells.to_py() == [{"metadata": {"foo": "bar"}, "source": "1 + 2"}] | ||
assert ystate.to_py() == {"state": {"dirty": False}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,24 @@ | ||
const Y = require('yjs') | ||
const WebsocketProvider = require('y-websocket').WebsocketProvider | ||
const ws = require('ws') | ||
|
||
const ydoc = new Y.Doc() | ||
const ytest = ydoc.getMap('_test') | ||
const ymap = ydoc.getMap('map') | ||
const ws = require('ws') | ||
|
||
function increment(resolve) { | ||
ymap.set('out', ymap.get('in') + 1); | ||
resolve(); | ||
} | ||
|
||
ymap.observe(event => { | ||
if (event.transaction.local || !event.changes.keys.has('in')) { | ||
return | ||
} | ||
new Promise(increment); | ||
}) | ||
|
||
const wsProvider = new WebsocketProvider( | ||
'ws://127.0.0.1:1234', 'my-roomname', | ||
ydoc, | ||
{ WebSocketPolyfill: ws } | ||
) | ||
|
||
wsProvider.on('status', event => { | ||
console.log(event.status) | ||
}) | ||
|
||
var clock = -1 | ||
|
||
ytest.observe(event => { | ||
event.changes.keys.forEach((change, key) => { | ||
if (key === 'clock') { | ||
const clk = ytest.get('clock') | ||
if (clk > clock) { | ||
ymap.set('out', ymap.get('in') + 1) | ||
clock = clk + 1 | ||
ytest.set('clock', clock) | ||
} | ||
} | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,21 @@ | ||
const Y = require('yjs') | ||
const WebsocketProvider = require('y-websocket').WebsocketProvider | ||
const ws = require('ws') | ||
|
||
const ydoc = new Y.Doc() | ||
const ytest = ydoc.getMap('_test') | ||
const ycells = ydoc.getArray("cells") | ||
const ystate = ydoc.getMap("state") | ||
const ws = require('ws') | ||
|
||
const wsProvider = new WebsocketProvider( | ||
'ws://127.0.0.1:1234', 'my-roomname', | ||
ydoc, | ||
{ WebSocketPolyfill: ws } | ||
) | ||
|
||
wsProvider.on('status', event => { | ||
console.log(event.status) | ||
}) | ||
|
||
var clock = -1 | ||
wsProvider.on('sync', () => { | ||
const ycells = ydoc.getArray('cells') | ||
const ystate = ydoc.getMap('state') | ||
|
||
ytest.observe(event => { | ||
event.changes.keys.forEach((change, key) => { | ||
if (key === 'clock') { | ||
const clk = ytest.get('clock') | ||
if (clk > clock) { | ||
const cells = [new Y.Map([['source', new Y.Text('1 + 2')], ['metadata', {'foo': 'bar'}]])] | ||
ycells.push(cells) | ||
ystate.set('state', {'dirty': false}) | ||
clock = clk + 1 | ||
ytest.set('clock', clock) | ||
} | ||
} | ||
}) | ||
const cells = [new Y.Map([['source', new Y.Text('1 + 2')], ['metadata', {'foo': 'bar'}]])] | ||
const state = {'dirty': false} | ||
ycells.push(cells) | ||
ystate.set('state', state) | ||
}) |