@@ -162,3 +162,67 @@ def load(self):
162
162
source .remove (source .get ("parent" , {"name" : "Test-Parent" }), remove_children = True )
163
163
source .sync_to (destination )
164
164
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
+
174
+ _modelname = "child"
175
+ _identifiers = ("name" ,)
176
+ _attributes = ("attribute" ,)
177
+
178
+ name : str
179
+ attribute : str
180
+
181
+ def update (self , attrs ):
182
+ call_order .append ("Update on child" )
183
+ return super ().update (attrs )
184
+
185
+ class ParentModel (DiffSyncModel ):
186
+ """Test parent model."""
187
+
188
+ _modelname = "parent"
189
+ _identifiers = ("name" ,)
190
+ _attributes = ("attribute" ,)
191
+ _children = {"child" : "children" }
192
+
193
+ name : str
194
+ attribute : str
195
+ children : List [ChildModel ] = []
196
+
197
+ class Adapter (DiffSync ):
198
+ """Test adapter."""
199
+
200
+ top_level = ["parent" ]
201
+
202
+ parent = ParentModel
203
+ child = ChildModel
204
+
205
+ def load (self , is_source = False ) -> None :
206
+ """Test load method. Generate a difference with the is_source parameter."""
207
+ parent = self .parent (name = "Test Parent" , attribute = "This doesn't change" )
208
+ parent .model_flags |= DiffSyncModelFlags .NATURAL_DELETION_ORDER
209
+ self .add (parent )
210
+ if is_source :
211
+ child = self .child (name = "Test Child" , attribute = "Attribute from source" )
212
+ child .model_flags |= DiffSyncModelFlags .NATURAL_DELETION_ORDER
213
+ parent .add_child (child )
214
+ self .add (child )
215
+ else :
216
+ child = self .child (name = "Test Child" , attribute = "Attribute from destination" )
217
+ child .model_flags |= DiffSyncModelFlags .NATURAL_DELETION_ORDER
218
+ parent .add_child (child )
219
+ self .add (child )
220
+
221
+ source_adapter = Adapter ()
222
+ source_adapter .load (is_source = True )
223
+ destination_adapter = Adapter ()
224
+ destination_adapter .load ()
225
+
226
+ source_adapter .sync_to (destination_adapter )
227
+
228
+ assert "Update on child" in call_order
0 commit comments