Skip to content

Commit 9a4a5b5

Browse files
committed
Add a test for reloading (on Python side)
Automatic application of license header
1 parent 16380fa commit 9a4a5b5

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

tests/test_ynotebook.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Copyright (c) Jupyter Development Team.
2+
# Distributed under the terms of the Modified BSD License.
3+
4+
from pycrdt import Map
5+
6+
from jupyter_ydoc import YNotebook
7+
8+
9+
def make_code_cell(source: str):
10+
return {
11+
"cell_type": "code",
12+
"source": source,
13+
"metadata": {},
14+
"outputs": [],
15+
"execution_count": None,
16+
}
17+
18+
19+
class AnyInstanceOf:
20+
def __init__(self, cls):
21+
self.cls = cls
22+
23+
def __eq__(self, other):
24+
return isinstance(other, self.cls)
25+
26+
27+
def test_set_preserves_cells_when_unchanged():
28+
nb = YNotebook()
29+
nb.set({"cells": [make_code_cell("print('a')\n"), make_code_cell("print('b')\n")]})
30+
31+
changes = []
32+
33+
def record_changes(topic, event):
34+
changes.append((topic, event))
35+
36+
nb.observe(record_changes)
37+
38+
model = nb.get()
39+
40+
# Call set with identical structure
41+
nb.set(model)
42+
43+
# No changes should be observed at all
44+
assert changes == []
45+
46+
47+
def test_set_preserves_cells_with_insert_and_remove():
48+
nb = YNotebook()
49+
nb.set(
50+
{
51+
"cells": [
52+
make_code_cell("print('a')\n"), # original 0
53+
make_code_cell("print('b')\n"), # original 1 (will remove)
54+
make_code_cell("print('c')\n"), # original 2
55+
]
56+
}
57+
)
58+
59+
# Capture textual content for sanity check
60+
cell0_source_text = str(nb.ycells[0]["source"])
61+
cell2_source_text = str(nb.ycells[2]["source"])
62+
63+
# Get the model as Python object
64+
model = nb.get()
65+
66+
# Remove the middle cell and insert a new one between the retained cells
67+
cells = model["cells"]
68+
assert len(cells) == 3
69+
70+
# The cell ids are needed for retention logic; keep first and last
71+
first = cells[0]
72+
last = cells[2]
73+
74+
# New inserted cell
75+
inserted = make_code_cell("print('x')\n")
76+
model["cells"] = [first, inserted, last]
77+
78+
changes = []
79+
80+
def record_changes(topic, event):
81+
changes.append((topic, event))
82+
83+
nb.observe(record_changes)
84+
nb.set(model)
85+
86+
assert nb.cell_number == 3
87+
88+
# Content of the first and last cells should remain the same
89+
assert str(nb.ycells[0]["source"]) == cell0_source_text
90+
assert str(nb.ycells[2]["source"]) == cell2_source_text
91+
92+
# The middle cell should have a different source now
93+
assert str(nb.ycells[1]["source"]) == "print('x')\n"
94+
95+
# We should have one cell event
96+
cell_events = [e for t, e in changes if t == "cells"]
97+
assert len(cell_events) == 1
98+
event_transactions = cell_events[0]
99+
assert len(event_transactions) == 1
100+
assert event_transactions[0].delta == [
101+
{"retain": 1},
102+
{"delete": 1},
103+
{"insert": [AnyInstanceOf(Map)]},
104+
]

0 commit comments

Comments
 (0)