@@ -162,3 +162,64 @@ def load(self):
162162 source .remove (source .get ("parent" , {"name" : "Test-Parent" }), remove_children = True )
163163 source .sync_to (destination )
164164 assert call_order == ["Test-Child" , "Test-Parent" ]
165+
166+
167+ def test_natural_deletion_order_with_noop_parent ():
168+ """Test whether children are recursed through when natural deletion order is set and the parent has no changes."""
169+ call_order = []
170+
171+ class ChildModel (DiffSyncModel ):
172+ """Test child model that reports when its update method is called."""
173+ _modelname = "child"
174+ _identifiers = ("name" ,)
175+ _attributes = ("attribute" ,)
176+
177+ name : str
178+ attribute : str
179+
180+ def update (self , attrs ):
181+ call_order .append ("Update on child" )
182+ return super ().update (attrs )
183+
184+ class ParentModel (DiffSyncModel ):
185+ """Test parent model."""
186+ _modelname = "parent"
187+ _identifiers = ("name" ,)
188+ _attributes = ("attribute" ,)
189+ _children = {"child" : "children" }
190+
191+ name : str
192+ attribute : str
193+ children : List [ChildModel ] = []
194+
195+ class Adapter (DiffSync ):
196+ """Test adapter."""
197+ top_level = ["parent" ]
198+
199+ parent = ParentModel
200+ child = ChildModel
201+
202+ def load (self , is_source = False ) -> None :
203+ """Test load method. Generate a difference with the is_source parameter."""
204+ parent = self .parent (name = "Test Parent" , attribute = "This doesn't change" )
205+ parent .model_flags |= DiffSyncModelFlags .NATURAL_DELETION_ORDER
206+ self .add (parent )
207+ if is_source :
208+ child = self .child (name = "Test Child" , attribute = "Attribute from source" )
209+ child .model_flags |= DiffSyncModelFlags .NATURAL_DELETION_ORDER
210+ parent .add_child (child )
211+ self .add (child )
212+ else :
213+ child = self .child (name = "Test Child" , attribute = "Attribute from destination" )
214+ child .model_flags |= DiffSyncModelFlags .NATURAL_DELETION_ORDER
215+ parent .add_child (child )
216+ self .add (child )
217+
218+ source_adapter = Adapter ()
219+ source_adapter .load (is_source = True )
220+ destination_adapter = Adapter ()
221+ destination_adapter .load ()
222+
223+ source_adapter .sync_to (destination_adapter )
224+
225+ assert "Update on child" in call_order
0 commit comments