diff --git a/projects/jupyter-server-ydoc/jupyter_server_ydoc/handlers.py b/projects/jupyter-server-ydoc/jupyter_server_ydoc/handlers.py index 3003361a..f89e20dd 100644 --- a/projects/jupyter-server-ydoc/jupyter_server_ydoc/handlers.py +++ b/projects/jupyter-server-ydoc/jupyter_server_ydoc/handlers.py @@ -606,8 +606,9 @@ async def _cleanup_undo_manager(self, room_id: str) -> None: class DocForkHandler(APIHandler): """ Jupyter Server handler to: - - create a fork of a document (optionally synchronizing with the root document), - - delete a fork of a document (optionally merging in the root document). + - create a fork of a root document (optionally synchronizing with the root document), + - delete a fork of a root document (optionally merging back in the root document). + - get fork IDs of a root document. """ auth_resource = "contents" @@ -618,6 +619,22 @@ def initialize( ) -> None: self._websocket_server = ywebsocket_server + @web.authenticated + @authorized + async def get(self, root_roomid): + """ + Returns a dictionary of given root room ID to the root's fork room IDs. + """ + self.write( + { + root_roomid: [ + fork_roomid + for fork_roomid, _root_roomid in FORK_ROOMS.items() + if _root_roomid == root_roomid + ] + } + ) + @web.authenticated @authorized async def put(self, root_roomid): diff --git a/projects/jupyter-server-ydoc/jupyter_server_ydoc/pytest_plugin.py b/projects/jupyter-server-ydoc/jupyter_server_ydoc/pytest_plugin.py index 8070430f..24710d0b 100644 --- a/projects/jupyter-server-ydoc/jupyter_server_ydoc/pytest_plugin.py +++ b/projects/jupyter-server-ydoc/jupyter_server_ydoc/pytest_plugin.py @@ -155,6 +155,18 @@ async def _inner(room_id: str) -> Any: return _inner +@pytest.fixture +def rtc_get_forks_client(jp_fetch): + async def _inner(root_roomid: str) -> Any: + return await jp_fetch( + "/api/collaboration/fork", + root_roomid, + method="GET", + ) + + return _inner + + @pytest.fixture def rtc_create_fork_client(jp_fetch): async def _inner(root_roomid: str, sync: bool) -> Any: diff --git a/tests/test_handlers.py b/tests/test_handlers.py index 050e9d9e..dedf0621 100644 --- a/tests/test_handlers.py +++ b/tests/test_handlers.py @@ -222,6 +222,7 @@ async def test_fork_handler( rtc_create_file, rtc_connect_doc_client, rtc_connect_fork_client, + rtc_get_forks_client, rtc_create_fork_client, rtc_delete_fork_client, rtc_fetch_session, @@ -245,9 +246,23 @@ def _on_root_change(topic: str, event: Any) -> None: root_ydoc.ydoc, ws ): await root_connect_event.wait() + + resp = await rtc_create_fork_client(f"text:file:{file_id}", False) + data = json.loads(resp.body.decode("utf-8")) + fork_roomid0 = data["roomId"] + + resp = await rtc_get_forks_client(f"text:file:{file_id}") + data = json.loads(resp.body.decode("utf-8")) + assert data == {f"text:file:{file_id}": [fork_roomid0]} + resp = await rtc_create_fork_client(f"text:file:{file_id}", True) data = json.loads(resp.body.decode("utf-8")) - fork_roomid = data["roomId"] + fork_roomid1 = data["roomId"] + + resp = await rtc_get_forks_client(f"text:file:{file_id}") + data = json.loads(resp.body.decode("utf-8")) + assert data == {f"text:file:{file_id}": [fork_roomid0, fork_roomid1]} + fork_ydoc = YUnicode() fork_connect_event = Event() @@ -258,7 +273,7 @@ def _on_fork_change(topic: str, event: Any) -> None: fork_ydoc.observe(_on_fork_change) fork_text = fork_ydoc.ydoc.get("source", type=Text) - async with await rtc_connect_fork_client(fork_roomid) as ws, WebsocketProvider( + async with await rtc_connect_fork_client(fork_roomid1) as ws, WebsocketProvider( fork_ydoc.ydoc, ws ): await fork_connect_event.wait() @@ -270,6 +285,17 @@ def _on_fork_change(topic: str, event: Any) -> None: await sleep(0.1) assert str(root_text) == "Hello, World!" - await rtc_delete_fork_client(fork_roomid, 1) + + await rtc_delete_fork_client(fork_roomid0, 1) + await sleep(0.1) + assert str(root_text) == "Hello, World!" + resp = await rtc_get_forks_client(f"text:file:{file_id}") + data = json.loads(resp.body.decode("utf-8")) + assert data == {f"text:file:{file_id}": [fork_roomid1]} + + await rtc_delete_fork_client(fork_roomid1, 1) await sleep(0.1) assert str(root_text) == "Hello, World! Hi!" + resp = await rtc_get_forks_client(f"text:file:{file_id}") + data = json.loads(resp.body.decode("utf-8")) + assert data == {f"text:file:{file_id}": []}