diff --git a/core/connection.js b/core/connection.js
index 427a6ed68..a144e1b8c 100644
--- a/core/connection.js
+++ b/core/connection.js
@@ -108,7 +108,7 @@ Blockly.Connection.prototype.connect_ = function(childConnection) {
var orphanBlock = parentConnection.targetBlock();
var shadowDom = parentConnection.getShadowDom();
// Temporarily set the shadow DOM to null so it does not respawn.
- parentConnection.setShadowDom(null);
+ parentConnection.shadowDom_ = null;
// Displaced shadow blocks dissolve rather than reattaching or bumping.
if (orphanBlock.isShadow()) {
// Save the shadow block so that field values are preserved.
@@ -175,7 +175,7 @@ Blockly.Connection.prototype.connect_ = function(childConnection) {
}
}
// Restore the shadow DOM.
- parentConnection.setShadowDom(shadowDom);
+ parentConnection.shadowDom_ = shadowDom;
}
var event;
@@ -200,12 +200,11 @@ Blockly.Connection.prototype.dispose = function() {
// isConnected returns true for shadows and non-shadows.
if (this.isConnected()) {
+ // Destroy the attached shadow block & its children (if it exists).
this.setShadowDom(null);
+
var targetBlock = this.targetBlock();
- if (targetBlock.isShadow()) {
- // Destroy the attached shadow block & its children.
- targetBlock.dispose(false);
- } else {
+ if (targetBlock) {
// Disconnect the attached normal block.
targetBlock.unplug();
}
@@ -672,15 +671,22 @@ Blockly.Connection.prototype.getCheck = function() {
};
/**
- * Change a connection's shadow block.
+ * Changes the connection's shadow block.
* @param {Element} shadow DOM representation of a block or null.
*/
Blockly.Connection.prototype.setShadowDom = function(shadow) {
this.shadowDom_ = shadow;
+ var target = this.targetBlock();
+ if (!target) {
+ this.respawnShadow_();
+ } else if (target.isShadow()) {
+ // The disconnect from dispose will automatically generate the new shadow.
+ target.dispose(false);
+ }
};
/**
- * Return a connection's shadow block.
+ * Returns the xml representation of the connection's shadow block.
* @return {Element} Shadow DOM representation of a block or null.
*/
Blockly.Connection.prototype.getShadowDom = function() {
diff --git a/core/input.js b/core/input.js
index aeb60a9de..dd56adf6a 100644
--- a/core/input.js
+++ b/core/input.js
@@ -231,6 +231,30 @@ Blockly.Input.prototype.setAlign = function(align) {
return this;
};
+/**
+ * Changes the connection's shadow block.
+ * @param {Element} shadow DOM representation of a block or null.
+ * @return {Blockly.Input} The input being modified (to allow chaining).
+ */
+Blockly.Input.prototype.setShadowDom = function(shadow) {
+ if (!this.connection) {
+ throw Error('This input does not have a connection.');
+ }
+ this.connection.setShadowDom(shadow);
+ return this;
+};
+
+/**
+ * Returns the xml representation of the connection's shadow block.
+ * @return {Element} Shadow DOM representation of a block or null.
+ */
+Blockly.Input.prototype.getShadowDom = function() {
+ if (!this.connection) {
+ throw Error('This input does not have a connection.');
+ }
+ return this.connection.getShadowDom();
+};
+
/**
* Initialize the fields on this input.
*/
diff --git a/core/xml.js b/core/xml.js
index 45b3e0ca6..e2ce6974e 100644
--- a/core/xml.js
+++ b/core/xml.js
@@ -661,10 +661,6 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
}
}
}
- // Use the shadow block if there is no child block.
- if (!childBlockElement && childShadowElement) {
- childBlockElement = childShadowElement;
- }
var name = xmlChild.getAttribute('name');
var xmlChildElement = /** @type {!Element} */ (xmlChild);
@@ -719,9 +715,6 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
prototypeName);
break;
}
- if (childShadowElement) {
- input.connection.setShadowDom(childShadowElement);
- }
if (childBlockElement) {
blockChild = Blockly.Xml.domToBlockHeadless_(childBlockElement,
workspace);
@@ -734,11 +727,12 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
'Child block does not have output or previous statement.');
}
}
+ // Set shadow after so we don't create a shadow we delete immediately.
+ if (childShadowElement) {
+ input.connection.setShadowDom(childShadowElement);
+ }
break;
case 'next':
- if (childShadowElement && block.nextConnection) {
- block.nextConnection.setShadowDom(childShadowElement);
- }
if (childBlockElement) {
if (!block.nextConnection) {
throw TypeError('Next statement does not exist.');
@@ -754,6 +748,10 @@ Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) {
}
block.nextConnection.connect(blockChild.previousConnection);
}
+ // Set shadow after so we don't create a shadow we delete immediately.
+ if (childShadowElement && block.nextConnection) {
+ block.nextConnection.setShadowDom(childShadowElement);
+ }
break;
default:
// Unknown tag; ignore. Same principle as HTML parsers.
diff --git a/tests/mocha/connection_test.js b/tests/mocha/connection_test.js
index f78584cfa..33f785756 100644
--- a/tests/mocha/connection_test.js
+++ b/tests/mocha/connection_test.js
@@ -184,4 +184,1027 @@ suite('Connections', function() {
chai.assert.isFalse(this.con1.checkType((this.con2)));
});
});
+ suite('Set Shadow Dom', function() {
+ setup(function() {
+ Blockly.defineBlocksWithJsonArray([
+ {
+ "type": "stack_block",
+ "message0": "",
+ "previousStatement": null,
+ "nextStatement": null
+ },
+ {
+ "type": "row_block",
+ "message0": "%1",
+ "args0": [
+ {
+ "type": "input_value",
+ "name": "INPUT"
+ }
+ ],
+ "output": null
+ },
+ {
+ "type": "statement_block",
+ "message0": "%1",
+ "args0": [
+ {
+ "type": "input_statement",
+ "name": "STATEMENT"
+ }
+ ],
+ "previousStatement": null,
+ "nextStatement": null
+ }]);
+
+ this.runHeadlessAndRendered = function(func, context) {
+ var workspace = new Blockly.Workspace();
+ func.call(context, workspace);
+ workspace.clear();
+ workspace.dispose();
+
+ workspace = Blockly.inject('blocklyDiv');
+ func.call(context, workspace);
+ workspace.clear();
+ workspace.dispose();
+ };
+ });
+ teardown(function() {
+ delete this.runHeadlessAndRendered;
+ delete Blockly.Blocks['stack_block'];
+ delete Blockly.Blocks['row_block'];
+ delete Blockly.Blocks['statement_block'];
+ });
+ suite('Add - No Block Connected', function() {
+ setup(function() {
+ // These are defined separately in each suite.
+ this.createRowBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStatementBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStackBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+ });
+ teardown(function() {
+ delete this.createRowBlock;
+ delete this.createStatementBlock;
+ delete this.createStackBlock;
+ });
+ test('Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getNextBlock();
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ });
+ suite('Add - With Block Connected', function() {
+ setup(function() {
+ // These are defined separately in each suite.
+ this.createRowBlocks = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStatementBlocks = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStackBlocks = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+ });
+ teardown(function() {
+ delete this.createRowBlocks;
+ delete this.createStatementBlock;
+ delete this.createStackBlock;
+ });
+ test('Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlocks(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('INPUT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlocks(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNull(target2);
+
+ parent.getInput('INPUT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlocks(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('STATEMENT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlocks(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNull(target2);
+
+ parent.getInput('STATEMENT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlocks(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.nextConnection.disconnect();
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlocks(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+ var target2 = target.getNextBlock();
+ chai.assert.isNull(target2);
+
+ parent.nextConnection.disconnect();
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getNextBlock();
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ });
+ suite('Add - With Shadow Connected', function() {
+ setup(function() {
+ // These are defined separately in each suite.
+ this.createRowBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStatementBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStackBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+ });
+ teardown(function() {
+ delete this.createRowBlock;
+ delete this.createStatementBlock;
+ delete this.createStackBlock;
+ });
+ test('Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '1');
+
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target2 = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, '2');
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '1');
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, 'a');
+
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '2');
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, 'b');
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '1');
+
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '2');
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '1');
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, 'a');
+
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '2');
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, 'b');
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '1');
+
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '2');
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '1');
+ var target2 = target.getNextBlock();
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, 'a');
+
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ chai.assert.equal(target.id, '2');
+ var target2 = target.getNextBlock();
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+ chai.assert.equal(target2.id, 'b');
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ });
+ suite('Remove - No Block Connected', function() {
+ setup(function() {
+ // These are defined separately in each suite.
+ this.createRowBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStatementBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStackBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+ });
+ teardown(function() {
+ delete this.createRowBlock;
+ delete this.createStatementBlock;
+ delete this.createStackBlock;
+ });
+ test('Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ parent.getInput('INPUT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ parent.getInput('STATEMENT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ parent.nextConnection.setShadowDom(null);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ });
+ suite('Remove - Block Connected', function() {
+ setup(function() {
+ // These are defined separately in each suite.
+ this.createRowBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStatementBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStackBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ ), workspace);
+ return block;
+ };
+ });
+ teardown(function() {
+ delete this.createRowBlock;
+ delete this.createStatementBlock;
+ delete this.createStackBlock;
+ });
+ test('Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ parent.getInput('INPUT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('INPUT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ parent.getInput('STATEMENT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('STATEMENT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ parent.nextConnection.setShadowDom(null);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.nextConnection.disconnect();
+
+ var target = parent.getNextBlock();
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ });
+ suite('Add - Connect & Disconnect - Remove', function() {
+ setup(function() {
+ // These are defined separately in each suite.
+ this.createRowBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStatementBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+
+ this.createStackBlock = function(workspace) {
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ ''
+ ), workspace);
+ return block;
+ };
+ });
+ teardown(function() {
+ delete this.createRowBlock;
+ delete this.createStatementBlock;
+ delete this.createStackBlock;
+ });
+ test('Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+
+ var child = this.createRowBlock(workspace);
+ parent.getInput('INPUT').connection.connect(child.outputConnection);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('INPUT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+
+ parent.getInput('INPUT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Value', function() {
+ var func = function(workspace) {
+ var parent = this.createRowBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('INPUT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+
+ var child = this.createRowBlock(workspace);
+ parent.getInput('INPUT').connection.connect(child.outputConnection);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('INPUT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('INPUT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+
+ parent.getInput('INPUT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('INPUT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+
+ var child = this.createStatementBlock(workspace);
+ parent.getInput('STATEMENT').connection
+ .connect(child.previousConnection);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('STATEMENT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+
+ parent.getInput('STATEMENT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Statement', function() {
+ var func = function(workspace) {
+ var parent = this.createStatementBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.getInput('STATEMENT').connection.setShadowDom(xml);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+
+ var child = this.createStatementBlock(workspace);
+ parent.getInput('STATEMENT').connection
+ .connect(child.previousConnection);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.getInput('STATEMENT').connection.disconnect();
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getInputTargetBlock('STATEMENT');
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+
+ parent.getInput('STATEMENT').connection.setShadowDom(null);
+
+ var target = parent.getInputTargetBlock('STATEMENT');
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+
+ var child = this.createStatementBlock(workspace);
+ parent.nextConnection.connect(child.previousConnection);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.nextConnection.disconnect();
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+
+ parent.nextConnection.setShadowDom(null);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ test('Multiple Next', function() {
+ var func = function(workspace) {
+ var parent = this.createStackBlock(workspace);
+ var xml = Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ' ' +
+ ' ' +
+ ''
+ );
+ parent.nextConnection.setShadowDom(xml);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getNextBlock();
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+
+ var child = this.createStatementBlock(workspace);
+ parent.nextConnection.connect(child.previousConnection);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isFalse(target.isShadow());
+
+ parent.nextConnection.disconnect();
+
+ var target = parent.getNextBlock();
+ chai.assert.isNotNull(target);
+ chai.assert.isTrue(target.isShadow());
+ var target2 = target.getNextBlock();
+ chai.assert.isNotNull(target2);
+ chai.assert.isTrue(target2.isShadow());
+
+ parent.nextConnection.setShadowDom(null);
+
+ var target = parent.getNextBlock();
+ chai.assert.isNull(target);
+ };
+ this.runHeadlessAndRendered(func, this);
+ });
+ });
+ });
});