@@ -35,6 +35,13 @@ suite('Keyboard-driven movement', function () {
3535 workspace . getInjectionDiv ( ) . dispatchEvent ( event ) ;
3636 }
3737
38+ function startMoveStack ( workspace ) {
39+ const event = createKeyDownEvent ( Blockly . utils . KeyCodes . M , [
40+ Blockly . utils . KeyCodes . SHIFT ,
41+ ] ) ;
42+ workspace . getInjectionDiv ( ) . dispatchEvent ( event ) ;
43+ }
44+
3845 function moveUp ( workspace , modifiers ) {
3946 const event = createKeyDownEvent ( Blockly . utils . KeyCodes . UP , modifiers ) ;
4047 workspace . getInjectionDiv ( ) . dispatchEvent ( event ) ;
@@ -407,6 +414,103 @@ suite('Keyboard-driven movement', function () {
407414 testExemptedShortcutsAllowed ( ) ;
408415 } ) ;
409416
417+ suite ( 'to disconnect blocks' , function ( ) {
418+ setup ( function ( ) {
419+ this . block1 = this . workspace . newBlock ( 'draw_emoji' ) ;
420+ this . block1 . initSvg ( ) ;
421+ this . block1 . render ( ) ;
422+
423+ this . block2 = this . workspace . newBlock ( 'draw_emoji' ) ;
424+ this . block2 . initSvg ( ) ;
425+ this . block2 . render ( ) ;
426+ this . block1 . nextConnection . connect ( this . block2 . previousConnection ) ;
427+
428+ this . block3 = this . workspace . newBlock ( 'draw_emoji' ) ;
429+ this . block3 . initSvg ( ) ;
430+ this . block3 . render ( ) ;
431+ this . block2 . nextConnection . connect ( this . block3 . previousConnection ) ;
432+ } ) ;
433+
434+ test ( 'from top block - Detaches single block' , function ( ) {
435+ Blockly . getFocusManager ( ) . focusNode ( this . block1 ) ;
436+ startMove ( this . workspace ) ;
437+ assert . isNull ( this . block1 . nextConnection . targetBlock ( ) ) ;
438+ assert . equal ( this . block1 . isDragging ( ) , true ) ;
439+ assert . equal ( this . block2 . isDragging ( ) , false ) ;
440+ assert . equal ( this . block3 . isDragging ( ) , false ) ;
441+ cancelMove ( this . workspace ) ;
442+ } ) ;
443+
444+ test ( 'from middle block - Detaches single block' , function ( ) {
445+ Blockly . getFocusManager ( ) . focusNode ( this . block2 ) ;
446+ startMove ( this . workspace ) ;
447+ assert . isNull ( this . block2 . previousConnection . targetBlock ( ) ) ;
448+ assert . isNull ( this . block2 . nextConnection . targetBlock ( ) ) ;
449+ assert . equal ( this . block1 . isDragging ( ) , false ) ;
450+ assert . equal ( this . block2 . isDragging ( ) , true ) ;
451+ assert . equal ( this . block3 . isDragging ( ) , false ) ;
452+ cancelMove ( this . workspace ) ;
453+ } ) ;
454+
455+ test ( 'from bottom block - Detaches single block' , function ( ) {
456+ Blockly . getFocusManager ( ) . focusNode ( this . block3 ) ;
457+ startMove ( this . workspace ) ;
458+ assert . isNull ( this . block3 . previousConnection . targetBlock ( ) ) ;
459+ assert . equal ( this . block1 . isDragging ( ) , false ) ;
460+ assert . equal ( this . block2 . isDragging ( ) , false ) ;
461+ assert . equal ( this . block3 . isDragging ( ) , true ) ;
462+ cancelMove ( this . workspace ) ;
463+ } ) ;
464+
465+ test ( 'from top block - Detaches entire three-block stack' , function ( ) {
466+ Blockly . getFocusManager ( ) . focusNode ( this . block1 ) ;
467+ startMoveStack ( this . workspace ) ;
468+ assert . strictEqual ( this . block1 . nextConnection . targetBlock ( ) , this . block2 ) ;
469+ assert . strictEqual ( this . block2 . nextConnection . targetBlock ( ) , this . block3 ) ;
470+ assert . equal ( this . block1 . isDragging ( ) , true ) ;
471+ assert . equal ( this . block2 . isDragging ( ) , true ) ;
472+ assert . equal ( this . block3 . isDragging ( ) , true ) ;
473+ cancelMove ( this . workspace ) ;
474+ } ) ;
475+
476+ test ( 'from middle block - Detaches two-block stack from middle down' , function ( ) {
477+ Blockly . getFocusManager ( ) . focusNode ( this . block2 ) ;
478+ startMoveStack ( this . workspace ) ;
479+ assert . isNull ( this . block2 . previousConnection . targetBlock ( ) ) ;
480+ assert . strictEqual ( this . block2 . nextConnection . targetBlock ( ) , this . block3 ) ;
481+ assert . equal ( this . block1 . isDragging ( ) , false ) ;
482+ assert . equal ( this . block2 . isDragging ( ) , true ) ;
483+ assert . equal ( this . block3 . isDragging ( ) , true ) ;
484+ cancelMove ( this . workspace ) ;
485+ } ) ;
486+
487+ test ( 'from bottom block - Detaches single-block stack from bottom' , function ( ) {
488+ Blockly . getFocusManager ( ) . focusNode ( this . block3 ) ;
489+ startMoveStack ( this . workspace ) ;
490+ assert . isNull ( this . block3 . previousConnection . targetBlock ( ) ) ;
491+ assert . equal ( this . block1 . isDragging ( ) , false ) ;
492+ assert . equal ( this . block2 . isDragging ( ) , false ) ;
493+ assert . equal ( this . block3 . isDragging ( ) , true ) ;
494+ cancelMove ( this . workspace ) ;
495+ } ) ;
496+
497+ test ( 'Cancel move restores connections' , function ( ) {
498+ Blockly . getFocusManager ( ) . focusNode ( this . block2 ) ;
499+ startMove ( this . workspace ) ;
500+ cancelMove ( this . workspace ) ;
501+ // Original stack restored
502+ assert . strictEqual ( this . block1 . nextConnection . targetBlock ( ) , this . block2 ) ;
503+ assert . strictEqual ( this . block2 . nextConnection . targetBlock ( ) , this . block3 ) ;
504+
505+ Blockly . getFocusManager ( ) . focusNode ( this . block2 ) ;
506+ startMoveStack ( this . workspace ) ;
507+ cancelMove ( this . workspace ) ;
508+ // Original stack restored
509+ assert . strictEqual ( this . block1 . nextConnection . targetBlock ( ) , this . block2 ) ;
510+ assert . strictEqual ( this . block2 . nextConnection . targetBlock ( ) , this . block3 ) ;
511+ } ) ;
512+ } ) ;
513+
410514 suite ( 'of blocks' , function ( ) {
411515 setup ( function ( ) {
412516 this . element = this . workspace . newBlock ( 'logic_boolean' ) ;
0 commit comments