@@ -260,6 +260,43 @@ describe('DraggableList — drag-local tree ref', () => {
260260 } ) ;
261261 } ) ;
262262
263+ describe ( 'unit drag over non-childAddable subsection via contained-unit collision' , ( ) => {
264+ it ( 'must not preview or commit when over unit inside childAddable=false subsection' , ( ) => {
265+ // sub-B has childAddable=false (e.g. library subsection) but draggable=true
266+ const unitA = makeUnit ( 'unit-A' ) ;
267+ const unitB = makeUnit ( 'unit-B' ) ;
268+ const subsectionA = makeSubsection ( 'sub-A' , [ unitA ] ) ;
269+ const subsectionB = makeSubsection ( 'sub-B' , [ unitB ] ) ;
270+ subsectionB . actions . childAddable = false ;
271+ const section1 = makeSection ( 'sec-1' , [ subsectionA ] ) ;
272+ const section2 = makeSection ( 'sec-2' , [ subsectionB ] ) ;
273+ const items = [ section1 , section2 ] ;
274+
275+ const callbacks = renderList ( items ) ;
276+
277+ expect ( mockDndHandlers . current ) . not . toBeNull ( ) ;
278+
279+ // Start dragging unit-A from sub-A.
280+ fireDragStart ( 'unit-A' , 'Unit A' , 'vertical' ) ;
281+
282+ // Drag over unit-B inside sub-B (childAddable=false).
283+ fireDragOver (
284+ 'unit-A' ,
285+ 'unit-B' ,
286+ { category : 'vertical' } ,
287+ { category : 'vertical' } ,
288+ ) ;
289+
290+ // unitDragOver guard should fire — no preview.
291+ expect ( callbacks . onPreviewTreeChange ) . not . toHaveBeenCalled ( ) ;
292+
293+ // Drag end — no commit.
294+ fireDragEnd ( 'unit-A' , 'unit-B' ) ;
295+
296+ expect ( callbacks . onUnitDrop ) . not . toHaveBeenCalled ( ) ;
297+ } ) ;
298+ } ) ;
299+
263300 describe ( 'drag cancellations reset ref' , ( ) => {
264301 it ( 'resets drag-local state on cancel' , ( ) => {
265302 const section1 = makeSection ( 'sec-1' , [ makeSubsection ( 'sub-A' ) ] ) ;
0 commit comments