diff --git a/core/connection_checker.ts b/core/connection_checker.ts index 599da547f7b..662037a9358 100644 --- a/core/connection_checker.ts +++ b/core/connection_checker.ts @@ -250,8 +250,9 @@ export class ConnectionChecker implements IConnectionChecker { } // Don't offer to splice into a stack where the connected block is - // immovable. - if (b.targetBlock() && !b.targetBlock()!.isMovable()) { + // immovable, unless the block is a shadow block. + if (b.targetBlock() && !b.targetBlock()!.isMovable() && + !b.targetBlock()!.isShadow()) { return false; } break; diff --git a/tests/mocha/connection_checker_test.js b/tests/mocha/connection_checker_test.js index 11b9545c184..918476ecefa 100644 --- a/tests/mocha/connection_checker_test.js +++ b/tests/mocha/connection_checker_test.js @@ -367,6 +367,31 @@ suite('Connection checker', function() { 'Should connect two compatible stack blocks'); }); + test('Connect to unmovable shadow block', function() { + // Remove original test blocks. + this.workspace.clear(); + + // Add the same test blocks, but this time block B is a shadow block. + Blockly.Xml.domToWorkspace(Blockly.utils.xml.textToDom(` + + + + + + + + `), this.workspace); + [this.blockA, this.blockB, this.blockC] = this.workspace.getAllBlocks(true); + + // Try to connect blockC into the input connection of blockA, replacing blockB. + // This is allowed because shadow blocks can always be replaced, even though + // they are unmovable. + chai.assert.isTrue( + this.checker.doDragChecks( + this.blockC.previousConnection, this.blockA.nextConnection, 9000), + 'Should connect in place of a shadow block'); + }); + test('Do not splice into unmovable stack', function() { // Try to connect blockC above blockB. It shouldn't work because B is not movable // and is already connected to A's nextConnection.