feat: add throwing errors for bad shadows (#5330)

* fix: add throwing errors for bad shadows

* tests: add tests for setShadowDom
This commit is contained in:
Beka Westberg
2021-08-23 17:33:20 +00:00
committed by alschmiedt
parent 9aecac3339
commit fd12dcf1e7
2 changed files with 122 additions and 13 deletions

View File

@@ -122,8 +122,8 @@ Connection.prototype.connect_ = function(childConnection) {
// Make sure the parentConnection is available.
let orphan;
if (parentConnection.isConnected()) {
let shadowState = parentConnection.stashShadowState_();
var target = parentConnection.targetBlock();
const shadowState = parentConnection.stashShadowState_();
const target = parentConnection.targetBlock();
if (target.isShadow()) {
target.dispose(false);
} else {
@@ -717,7 +717,7 @@ Connection.prototype.setShadowStateInternal_ =
this.shadowDom_ = shadowDom;
this.shadowState_ = shadowState;
var target = this.targetBlock();
const target = this.targetBlock();
if (!target) {
this.respawnShadow_();
if (this.targetBlock() && this.targetBlock().isShadow()) {
@@ -730,7 +730,7 @@ Connection.prototype.setShadowStateInternal_ =
this.serializeShadow_(this.targetBlock());
}
} else {
var shadow = this.createShadowBlock_(false);
const shadow = this.createShadowBlock_(false);
this.serializeShadow_(shadow);
if (shadow) {
shadow.dispose(false);
@@ -748,15 +748,16 @@ Connection.prototype.setShadowStateInternal_ =
* @private
*/
Connection.prototype.createShadowBlock_ = function(attemptToConnect) {
var parentBlock = this.getSourceBlock();
var shadowState = this.getShadowState();
var shadowDom = this.getShadowDom();
const parentBlock = this.getSourceBlock();
const shadowState = this.getShadowState();
const shadowDom = this.getShadowDom();
if (!parentBlock.workspace || (!shadowState && !shadowDom)) {
return null;
}
let blockShadow;
if (shadowState) {
var blockShadow = blocks.loadInternal(
blockShadow = blocks.loadInternal(
shadowState,
parentBlock.workspace,
attemptToConnect ? this : undefined,
@@ -767,12 +768,23 @@ Connection.prototype.createShadowBlock_ = function(attemptToConnect) {
if (shadowDom) {
blockShadow = Xml.domToBlock(shadowDom, parentBlock.workspace);
if (attemptToConnect) {
if (blockShadow.outputConnection) {
this.connect(blockShadow.outputConnection);
} else if (blockShadow.previousConnection) {
this.connect(blockShadow.previousConnection);
if (this.type == Blockly.connectionTypes.INPUT_VALUE) {
if (!blockShadow.outputConnection) {
throw new Error('Shadow block is missing an output connection');
}
if (!this.connect(blockShadow.outputConnection)) {
throw new Error('Could not connect shadow block to connection');
}
} else if (this.type == Blockly.connectionTypes.NEXT_STATEMENT) {
if (!blockShadow.previousConnection) {
throw new Error('Shadow block is missing previous connection');
}
if (!this.connect(blockShadow.previousConnection)) {
throw new Error('Could not connect shadow block to connection');
}
} else {
throw Error('Shadow block does not have output or previous statement.');
throw new Error(
'Cannot connect a shadow block to a previous/output connection');
}
}
return blockShadow;

View File

@@ -1296,6 +1296,56 @@ suite('Connection', function() {
assertNextNotHasBlock(parent);
});
});
suite('Invalid', function() {
test('Attach to output', function() {
const block = this.workspace.newBlock('row_block');
chai.assert.throws(() =>
block.outputConnection.setShadowDom(Blockly.Xml.textToDom(
'<block type="row_block">')));
});
test('Attach to previous', function() {
const block = this.workspace.newBlock('stack_block');
chai.assert.throws(() =>
block.previousConnection.setShadowDom(Blockly.Xml.textToDom(
'<block type="stack_block">')));
});
test('Missing output', function() {
const block = this.workspace.newBlock('row_block');
chai.assert.throws(() =>
block.outputConnection.setShadowDom(Blockly.Xml.textToDom(
'<block type="stack_block">')));
});
test('Missing previous', function() {
const block = this.workspace.newBlock('stack_block');
chai.assert.throws(() =>
block.previousConnection.setShadowDom(Blockly.Xml.textToDom(
'<block type="row_block">')));
});
test('Invalid connection checks, output', function() {
const block = this.workspace.newBlock('logic_operation');
chai.assert.throws(() =>
block.getInput('A').connection.setShadowDom(
Blockly.Xml.textToDom('<block type="stack_block">')));
});
test('Invalid connection checks, previous', function() {
Blockly.defineBlocksWithJsonArray([{
"type": "stack_checks_block",
"message0": "",
"previousStatement": "check 1",
"nextStatement": "check 2"
}]);
const block = this.workspace.newBlock('stack_checks_block');
chai.assert.throws(() =>
block.nextConnection.setShadowDom(Blockly.Xml.textToDom(
'<block type="stack_checks_block">')));
});
});
});
suite('setShadowState', function() {
@@ -2516,6 +2566,53 @@ suite('Connection', function() {
assertNextNotHasBlock(parent);
});
});
suite('Invalid', function() {
test('Attach to output', function() {
const block = this.workspace.newBlock('row_block');
chai.assert.throws(() =>
block.outputConnection.setShadowState({'type': 'row_block'}));
});
test('Attach to previous', function() {
const block = this.workspace.newBlock('stack_block');
chai.assert.throws(() =>
block.previousConnection.setShadowState(
{'type': 'stack_block'}));
});
test('Missing output', function() {
const block = this.workspace.newBlock('row_block');
chai.assert.throws(() =>
block.outputConnection.setShadowState({'type': 'stack_block'}));
});
test('Missing previous', function() {
const block = this.workspace.newBlock('stack_block');
chai.assert.throws(() =>
block.previousConnection.setShadowState({'type': 'row_block'}));
});
test('Invalid connection checks, output', function() {
const block = this.workspace.newBlock('logic_operation');
chai.assert.throws(() =>
block.getInput('A').connection.setShadowState(
{'type': 'math_number'}));
});
test('Invalid connection checks, previous', function() {
Blockly.defineBlocksWithJsonArray([{
"type": "stack_checks_block",
"message0": "",
"previousStatement": "check 1",
"nextStatement": "check 2"
}]);
const block = this.workspace.newBlock('stack_checks_block');
chai.assert.throws(() =>
block.nextConnection.setShadowState(
{'type': 'stack_checks_block'}));
});
});
});
});
});