@@ -162,12 +162,19 @@ def array_dataset() -> vtkPolyData:
162162# rather than coincides -- if the re-serialisation names the renderer, the
163163# interactor, the picker or the active camera instead of the render window.
164164#
165+ # REGISTERED_WASM_IDS stands for the separately registered objects -- the
166+ # interactor, the picker and the widget objects -- that LocalView.update
167+ # carries alongside the render window and that api.get_all_ids appends to the
168+ # root it is handed. Kept as its own literal so that a re-serialisation
169+ # passing the render window alone fails rather than coincides.
170+ #
165171# Asserting against the id source's own answer for the attribute production
166172# reads would pin nothing: it would pass whichever object production named.
167173# ---------------------------------------------------------------------------
168174
169175RENDER_WINDOW_WASM_ID = 8150001
170176WRONG_OBJECT_WASM_ID = 8150999
177+ REGISTERED_WASM_IDS = [8150101 , 8150102 , 8150103 ]
171178
172179
173180@pytest .fixture
@@ -183,6 +190,12 @@ def renderer():
183190 identity, the render window resolves to RENDER_WINDOW_WASM_ID and every
184191 other object to WRONG_OBJECT_WASM_ID. That is what lets the ordering test
185192 below assert which object the re-serialisation named.
193+
194+ ``api.get_all_ids`` is seeded alongside it, since the re-serialisation
195+ roots on ``api.get_all_ids(render_window_id)``. It is stubbed as a
196+ faithful function of the root it is handed -- the real
197+ ``ObjectManagerAPI.get_all_ids`` returns ``[root_id, *widgets[root_id]]``
198+ -- so the identity keying above still reaches the assertion.
186199 """
187200 mock_server = MagicMock ()
188201 mock_server .state = {}
@@ -209,6 +222,9 @@ def renderer():
209222 if obj is r ._render_window
210223 else WRONG_OBJECT_WASM_ID
211224 )
225+ r ._local_view .api .get_all_ids .side_effect = (
226+ lambda root_id : [root_id , * REGISTERED_WASM_IDS ]
227+ )
212228 return r
213229
214230
@@ -1134,7 +1150,9 @@ def test_apply_state_syncs_the_camera_under_the_lock_before_the_render_step(scen
11341150 ``("serialize", <ids>)`` for the re-serialisation -- the tuple is the
11351151 recording format, not the argument -- and ``"bridge"`` for the delegated
11361152 render step. ``<ids>`` is asserted as the list production passes, since
1137- ``UpdateStatesFromObjects`` takes a sequence.
1153+ ``UpdateStatesFromObjects`` takes a sequence: the render window at the
1154+ head, keyed on identity, followed by the separately registered objects
1155+ that ``LocalView.update`` carries alongside it.
11381156
11391157 Ordered between the two: after the write, because re-serialising before
11401158 it would publish the pre-load camera; before the render step, because the
@@ -1161,7 +1179,7 @@ def _sync(camera_state):
11611179
11621180 assert order == [
11631181 "camera" ,
1164- ("serialize" , [RENDER_WINDOW_WASM_ID ]),
1182+ ("serialize" , [RENDER_WINDOW_WASM_ID , * REGISTERED_WASM_IDS ]),
11651183 "bridge" ,
11661184 ]
11671185 assert observed ["depth" ] >= 1
@@ -1202,8 +1220,8 @@ def test_apply_state_serializes_the_camera_under_the_lock(scene):
12021220# then ``self._renderer.serialize_camera_state()``, both inside
12031221# ``_vtk_lock``. Same shape as the ``sync_camera`` trigger section above: the
12041222# re-serialisation runs after the reset, is spied on
1205- # ``_object_manager.UpdateStatesFromObjects`` with the render-window id, and
1206- # the lock is held (depth >= 1) at both points.
1223+ # ``_object_manager.UpdateStatesFromObjects`` with the render-window id at the
1224+ # head of the root list, and the lock is held (depth >= 1) at both points.
12071225#
12081226# Own literals are unnecessary here -- reset_camera takes no camera argument,
12091227# only the scene-graph bounds -- so what is pinned is order and lock depth,
@@ -1221,7 +1239,10 @@ def test_reset_camera_serializes_after_the_reset_with_the_render_window_id(scene
12211239 The spy appends ``"reset"`` for the reset call and the two-tuple
12221240 ``("serialize", <ids>)`` for the re-serialisation; the tuple is the
12231241 recording format, not the argument. ``<ids>`` is asserted as the list
1224- production passes, since ``UpdateStatesFromObjects`` takes a sequence.
1242+ production passes, since ``UpdateStatesFromObjects`` takes a sequence:
1243+ the render window at the head, keyed on identity, followed by the
1244+ separately registered objects that ``LocalView.update`` carries
1245+ alongside it.
12251246 """
12261247 order = []
12271248 real_reset = scene ._renderer .reset_camera
@@ -1237,7 +1258,10 @@ def _reset(bounds):
12371258
12381259 scene .reset_camera ()
12391260
1240- assert order == ["reset" , ("serialize" , [RENDER_WINDOW_WASM_ID ])]
1261+ assert order == [
1262+ "reset" ,
1263+ ("serialize" , [RENDER_WINDOW_WASM_ID , * REGISTERED_WASM_IDS ]),
1264+ ]
12411265
12421266
12431267def test_reset_camera_holds_the_lock_across_both_halves (scene ):
0 commit comments