mirror of
https://github.com/google/blockly.git
synced 2026-01-08 01:20:12 +01:00
* refactor(xml): Move textToDom to core/utils/xml.ts This function being in core/xml.ts was the cause for the last remaining circular import in core/ (between variables.ts and xml.ts). Moving it to utils/xml.ts makes sense anyway, since there is nothing Blockly-specific about this function. Fixes #6817. * fix(closure): Reenable goog.declareModuleId multiple-call check Reenable an assertion which check to make sure that goog.declareModuleId is not called more than once in a module (and which also catches circular imports amongst ES modules, which are not detected by closure-make-deps). * chore(tests,demos): Augo-migrate use of textToDom Testing the migration file entry by auto-migrating all uses of Blockly.Xml.textToDom to Blockly.utils.xml.textToDom. * chore(blocks): Manually migrate remaining use of textToDom Update the one remaining call to textToDom (in blocks/lists.ts) to the function's new location - also removing the last use of the Blockly.Xml / core/xml.ts) module from this file. * docs(xml): Remove unneeded @alias per comments on PR #6818 * fix(imports): Remove unused import
3472 lines
133 KiB
JavaScript
3472 lines
133 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2019 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.declareModuleId('Blockly.test.connection');
|
|
|
|
import {createGenUidStubWithReturns, sharedTestSetup, sharedTestTeardown, workspaceTeardown} from './test_helpers/setup_teardown.js';
|
|
import {defineRowBlock, defineStatementBlock, defineStackBlock} from './test_helpers/block_definitions.js';
|
|
|
|
|
|
suite('Connection', function() {
|
|
setup(function() {
|
|
sharedTestSetup.call(this);
|
|
this.workspace = sinon.createStubInstance(Blockly.Workspace);
|
|
this.workspace.connectionChecker = new Blockly.ConnectionChecker();
|
|
this.createConnection = function(type) {
|
|
const block = {
|
|
workspace: this.workspace,
|
|
isShadow: function() {return false;},
|
|
};
|
|
const connection = new Blockly.Connection(block, type);
|
|
return connection;
|
|
};
|
|
});
|
|
|
|
teardown(function() {
|
|
sharedTestTeardown.call(this);
|
|
});
|
|
|
|
suite('Set Shadow', function() {
|
|
function assertBlockMatches(block, isShadow, opt_id) {
|
|
chai.assert.equal(block.isShadow(), isShadow,
|
|
`expected block ${block.id} to ${isShadow ? '' : 'not'} be a shadow`);
|
|
if (opt_id) {
|
|
chai.assert.equal(block.id, opt_id);
|
|
}
|
|
}
|
|
|
|
function assertInputHasBlock(parent, inputName, isShadow, opt_name) {
|
|
const block = parent.getInputTargetBlock(inputName);
|
|
chai.assert.exists(block,
|
|
`expected block ${opt_name || ''} to be attached to ${inputName}`);
|
|
assertBlockMatches(block, isShadow, opt_name);
|
|
}
|
|
|
|
function assertNextHasBlock(parent, isShadow, opt_name) {
|
|
const block = parent.getNextBlock();
|
|
chai.assert.exists(block,
|
|
`expected block ${opt_name || ''} to be attached to next connection`);
|
|
assertBlockMatches(block, isShadow, opt_name);
|
|
}
|
|
|
|
function assertInputNotHasBlock(parent, inputName) {
|
|
const block = parent.getInputTargetBlock(inputName);
|
|
chai.assert.notExists(block,
|
|
`expected block ${block && block.id} to not be attached to ${inputName}`);
|
|
}
|
|
|
|
function assertNextNotHasBlock(parent) {
|
|
const block = parent.getNextBlock();
|
|
chai.assert.notExists(block,
|
|
`expected block ${block && block.id} to not be attached to next connection`);
|
|
}
|
|
|
|
function assertSerialization(block, jso, xmlText) {
|
|
const actualJso = Blockly.serialization.blocks
|
|
.save(block, {addNextBlocks: true});
|
|
const actualXml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block));
|
|
chai.assert.deepEqual(actualJso, jso);
|
|
chai.assert.equal(actualXml, xmlText);
|
|
}
|
|
|
|
const testSuites = [
|
|
{
|
|
title: 'Rendered',
|
|
createWorkspace: () => {
|
|
return Blockly.inject('blocklyDiv');
|
|
},
|
|
},
|
|
{
|
|
title: 'Headless',
|
|
createWorkspace: () => {
|
|
return new Blockly.Workspace();
|
|
},
|
|
},
|
|
];
|
|
|
|
testSuites.forEach((testSuite) => {
|
|
// Create a suite for each suite.
|
|
suite(testSuite.title, function() {
|
|
setup(function() {
|
|
this.workspace = testSuite.createWorkspace();
|
|
|
|
defineRowBlock();
|
|
defineStatementBlock();
|
|
defineStackBlock();
|
|
|
|
createGenUidStubWithReturns(
|
|
new Array(30).fill().map((_, i) => 'id' + i));
|
|
});
|
|
|
|
teardown(function() {
|
|
workspaceTeardown.call(this, this.workspace);
|
|
});
|
|
|
|
suite('setShadowDom', function() {
|
|
suite('Add - No Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="row_block" id="id0"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="statement_block" id="id0"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block" id="id0"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="id1"/>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1"></shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="id1">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block" id="id2"/>' +
|
|
' </value>' +
|
|
'</shadow>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id2"></shadow>' +
|
|
'</value>' +
|
|
'</shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="id1"/>'
|
|
);
|
|
parent.getInput('NAME').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1"></shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="id1">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block" id="id2"/>' +
|
|
' </statement>' +
|
|
'</shadow>'
|
|
);
|
|
parent.getInput('NAME').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id2"></shadow>' +
|
|
'</statement>' +
|
|
'</shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="id1"/>'
|
|
);
|
|
parent.nextConnection.setShadowDom(xml);
|
|
assertNextHasBlock(parent, true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1"></shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="id1">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="id2"/>' +
|
|
' </next>' +
|
|
'</shadow>'
|
|
);
|
|
parent.nextConnection.setShadowDom(xml);
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id2"></shadow>' +
|
|
'</next>' +
|
|
'</shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Add - With Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlocks(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="row_block" id="id0">' +
|
|
' <value name="INPUT">' +
|
|
' <block type="row_block" id="idA"/>' +
|
|
' </value>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStatementBlocks(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="statement_block" id="id0">' +
|
|
' <statement name="NAME">' +
|
|
' <block type="statement_block" id="idA"/>' +
|
|
' </statement>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStackBlocks(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block" id="id0">' +
|
|
' <next>' +
|
|
' <block type="stack_block" id="idA"/>' +
|
|
' </next>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlocks(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="id1"/>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1"></shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlocks(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="id1">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block" id="id2"/>' +
|
|
' </value>' +
|
|
'</shadow>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
assertInputNotHasBlock(parent.getInputTargetBlock('INPUT'), 'INPUT');
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id2"></shadow>' +
|
|
'</value>' +
|
|
'</shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlocks(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="id1"/>'
|
|
);
|
|
parent.getInput('NAME').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1"></shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlocks(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="id1">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block" id="id2"/>' +
|
|
' </statement>' +
|
|
'</shadow>'
|
|
);
|
|
parent.getInput('NAME').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
assertInputNotHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME');
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id2"></shadow>' +
|
|
'</statement>' +
|
|
'</shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlocks(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="id1"/>'
|
|
);
|
|
parent.nextConnection.setShadowDom(xml);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1"></shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlocks(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="id1">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="id2"/>' +
|
|
' </next>' +
|
|
'</shadow>'
|
|
);
|
|
parent.nextConnection.setShadowDom(xml);
|
|
assertNextHasBlock(parent, false);
|
|
assertNextNotHasBlock(parent.getNextBlock());
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id2"></shadow>' +
|
|
'</next>' +
|
|
'</shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Add - With Shadow Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="row_block" id="id0"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="statement_block" id="id0"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block" id="id0"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
const xml1 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="1"/>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml1);
|
|
assertInputHasBlock(parent, 'INPUT', true, '1');
|
|
const xml2 =
|
|
Blockly.utils.xml.textToDom('<shadow type="row_block" id="2"/>');
|
|
parent.getInput('INPUT').connection.setShadowDom(xml2);
|
|
assertInputHasBlock(parent, 'INPUT', true, '2');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': '2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="2"></shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
const xml1 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="1">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block" id="a"/>' +
|
|
' </value>' +
|
|
'</shadow>');
|
|
parent.getInput('INPUT').connection.setShadowDom(xml1);
|
|
assertInputHasBlock(parent, 'INPUT', true, '1');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'a');
|
|
const xml2 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block" id="2">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block" id="b"/>' +
|
|
' </value>' +
|
|
'</shadow>');
|
|
parent.getInput('INPUT').connection.setShadowDom(xml2);
|
|
assertInputHasBlock(parent, 'INPUT', true, '2');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'b');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': '2',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="2">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="b"></shadow>' +
|
|
'</value>' +
|
|
'</shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
const xml1 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="1"/>');
|
|
parent.getInput('NAME').connection.setShadowDom(xml1);
|
|
assertInputHasBlock(parent, 'NAME', true, '1');
|
|
const xml2 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="2"/>');
|
|
parent.getInput('NAME').connection.setShadowDom(xml2);
|
|
assertInputHasBlock(parent, 'NAME', true, '2');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': '2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="2"></shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
const xml1 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="1">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block" id="a"/>' +
|
|
' </statement>' +
|
|
'</shadow>');
|
|
parent.getInput('NAME').connection.setShadowDom(xml1);
|
|
assertInputHasBlock(parent, 'NAME', true, '1');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true, 'a');
|
|
const xml2 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block" id="2">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block" id="b"/>' +
|
|
' </statement>' +
|
|
'</shadow>');
|
|
parent.getInput('NAME').connection.setShadowDom(xml2);
|
|
assertInputHasBlock(parent, 'NAME', true, '2');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true, 'b');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': '2',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="2">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="b"></shadow>' +
|
|
'</statement>' +
|
|
'</shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
const xml1 =
|
|
Blockly.utils.xml.textToDom('<shadow type="stack_block" id="1"/>');
|
|
parent.nextConnection.setShadowDom(xml1);
|
|
assertNextHasBlock(parent, true, '1');
|
|
const xml2 =
|
|
Blockly.utils.xml.textToDom('<shadow type="stack_block" id="2"/>');
|
|
parent.nextConnection.setShadowDom(xml2);
|
|
assertNextHasBlock(parent, true, '2');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': '2',
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="2"></shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
const xml1 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="1">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="a"/>' +
|
|
' </next>' +
|
|
'</shadow>');
|
|
parent.nextConnection.setShadowDom(xml1);
|
|
assertNextHasBlock(parent, true, '1');
|
|
assertNextHasBlock(parent.getNextBlock(), true, 'a');
|
|
const xml2 = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="2">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="b"/>' +
|
|
' </next>' +
|
|
'</shadow>');
|
|
parent.nextConnection.setShadowDom(xml2);
|
|
assertNextHasBlock(parent, true, '2');
|
|
assertNextHasBlock(parent.getNextBlock(), true, 'b');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': '2',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="2">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="b"></shadow>' +
|
|
'</next>' +
|
|
'</shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Remove - No Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="row_block" id="id0">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block" id="idA"/>' +
|
|
' </value>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="statement_block" id="id0">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block" id="idA"/>' +
|
|
' </statement>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block" id="id0">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="idA"/>' +
|
|
' </next>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowDom(null);
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowDom(null);
|
|
assertInputNotHasBlock(parent, 'STATEMENT');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection.setShadowDom(null);
|
|
assertNextNotHasBlock(parent);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Remove - Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="row_block" id="id0">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block" id="idA"/>' +
|
|
' <block type="row_block" id="idB"/>' +
|
|
' </value>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="statement_block" id="id0">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block" id="idA"/>' +
|
|
' <block type="statement_block" id="idB"/>' +
|
|
' </statement>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block" id="id0">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="idA"/>' +
|
|
' <block type="stack_block" id="idB"/>' +
|
|
' </next>' +
|
|
'</block>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowDom(null);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowDom(null);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection.setShadowDom(null);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextNotHasBlock(parent);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Add - Connect & Disconnect - Remove', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="row_block"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="statement_block"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
const block = Blockly.Xml.domToBlock(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block"/>'
|
|
), workspace);
|
|
return block;
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block"/>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
const child = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
parent.getInput('INPUT').connection.setShadowDom(null);
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block">' +
|
|
' <value name="INPUT">' +
|
|
' <shadow type="row_block"/>' +
|
|
' </value>' +
|
|
'</shadow>'
|
|
);
|
|
parent.getInput('INPUT').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
const child = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
parent.getInput('INPUT').connection.setShadowDom(null);
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block"/>'
|
|
);
|
|
parent.getInput('NAME').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
parent.getInput('NAME').connection.setShadowDom(null);
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="statement_block">' +
|
|
' <statement name="NAME">' +
|
|
' <shadow type="statement_block"/>' +
|
|
' </statement>' +
|
|
'</shadow>'
|
|
);
|
|
parent.getInput('NAME').connection.setShadowDom(xml);
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
parent.getInput('NAME').connection.setShadowDom(null);
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
parent.nextConnection.setShadowDom(xml);
|
|
assertNextHasBlock(parent, true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.nextConnection.connect(child.previousConnection);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
parent.nextConnection.setShadowDom(null);
|
|
assertNextNotHasBlock(parent);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block" id="parent">' +
|
|
' <next>' +
|
|
' <shadow type="stack_block" id="child"/>' +
|
|
' </next>' +
|
|
'</shadow>'
|
|
);
|
|
parent.nextConnection.setShadowDom(xml);
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.nextConnection.connect(child.previousConnection);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
parent.nextConnection.setShadowDom(null);
|
|
assertNextNotHasBlock(parent);
|
|
});
|
|
});
|
|
|
|
suite('Invalid', function() {
|
|
test('Attach to output', function() {
|
|
const block = this.workspace.newBlock('row_block');
|
|
chai.assert.throws(() =>
|
|
block.outputConnection.setShadowDom(Blockly.utils.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.utils.xml.textToDom(
|
|
'<block type="stack_block">')));
|
|
});
|
|
|
|
test('Missing output', function() {
|
|
const block = this.workspace.newBlock('row_block');
|
|
chai.assert.throws(() =>
|
|
block.outputConnection.setShadowDom(Blockly.utils.xml.textToDom(
|
|
'<block type="stack_block">')));
|
|
});
|
|
|
|
test('Missing previous', function() {
|
|
const block = this.workspace.newBlock('stack_block');
|
|
chai.assert.throws(() =>
|
|
block.previousConnection.setShadowDom(Blockly.utils.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.utils.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.utils.xml.textToDom(
|
|
'<block type="stack_checks_block">')));
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('setShadowState', function() {
|
|
suite('Add - No Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'row_block', 'id': 'id0'}, workspace);
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'statement_block', 'id': 'id0'}, workspace);
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'stack_block', 'id': 'id0'}, workspace);
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection
|
|
.setShadowState({'type': 'row_block', 'id': 'id1'});
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1"></shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowState({
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id2"></shadow>' +
|
|
'</value>' +
|
|
'</shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.setShadowState({'type': 'statement_block', 'id': 'id1'});
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1"></shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Statment', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowState({
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id2"></shadow>' +
|
|
'</statement>' +
|
|
'</shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection
|
|
.setShadowState({'type': 'stack_block', 'id': 'id1'});
|
|
assertNextHasBlock(parent, true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1"></shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection.setShadowState({
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
});
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id2"></shadow>' +
|
|
'</next>' +
|
|
'</shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Add - With Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'block': {
|
|
'type': 'row_block',
|
|
'id': 'idA',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
function createStatementBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'block': {
|
|
'type': 'statement_block',
|
|
'id': 'idA',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
function createStackBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'block': {
|
|
'type': 'stack_block',
|
|
'id': 'idA',
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlocks(this.workspace);
|
|
parent.getInput('INPUT').connection
|
|
.setShadowState({'type': 'row_block', 'id': 'id1'});
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1"></shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlocks(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowState(
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
assertInputNotHasBlock(parent.getInputTargetBlock('INPUT'), 'INPUT');
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id1">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="id2"></shadow>' +
|
|
'</value>' +
|
|
'</shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlocks(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.setShadowState({'type': 'statement_block', 'id': 'id1'});
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1"></shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlocks(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowState(
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
assertInputNotHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME');
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id1">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="id2"></shadow>' +
|
|
'</statement>' +
|
|
'</shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlocks(this.workspace);
|
|
parent.nextConnection
|
|
.setShadowState({'type': 'stack_block', 'id': 'id1'});
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1"></shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlocks(this.workspace);
|
|
parent.nextConnection.setShadowState(
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertNextHasBlock(parent, false);
|
|
assertNextNotHasBlock(parent.getNextBlock());
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id1">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="id2"></shadow>' +
|
|
'</next>' +
|
|
'</shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Add - With Shadow Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'row_block', 'id': 'id0'}, workspace);
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'statement_block', 'id': 'id0'}, workspace);
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'stack_block', 'id': 'id0'}, workspace);
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection
|
|
.setShadowState({'type': 'row_block', 'id': '1'});
|
|
assertInputHasBlock(parent, 'INPUT', true, '1');
|
|
parent.getInput('INPUT').connection
|
|
.setShadowState({'type': 'row_block', 'id': '2'});
|
|
assertInputHasBlock(parent, 'INPUT', true, '2');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': '2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="2"></shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowState(
|
|
{
|
|
'type': 'row_block',
|
|
'id': '1',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'a',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertInputHasBlock(parent, 'INPUT', true, '1');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'a');
|
|
parent.getInput('INPUT').connection.setShadowState(
|
|
{
|
|
'type': 'row_block',
|
|
'id': '2',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertInputHasBlock(parent, 'INPUT', true, '2');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true, 'b');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': '2',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="2">' +
|
|
'<value name="INPUT">' +
|
|
'<shadow type="row_block" id="b"></shadow>' +
|
|
'</value>' +
|
|
'</shadow>' +
|
|
'</value>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.setShadowState({'type': 'statement_block', 'id': '1'});
|
|
assertInputHasBlock(parent, 'NAME', true, '1');
|
|
parent.getInput('NAME').connection
|
|
.setShadowState({'type': 'statement_block', 'id': '2'});
|
|
assertInputHasBlock(parent, 'NAME', true, '2');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': '2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="2"></shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowState(
|
|
{
|
|
'type': 'statement_block',
|
|
'id': '1',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'a',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertInputHasBlock(parent, 'NAME', true, '1');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true, 'a');
|
|
parent.getInput('NAME').connection.setShadowState(
|
|
{
|
|
'type': 'statement_block',
|
|
'id': '2',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertInputHasBlock(parent, 'NAME', true, '2');
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true, 'b');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': '2',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="2">' +
|
|
'<statement name="NAME">' +
|
|
'<shadow type="statement_block" id="b"></shadow>' +
|
|
'</statement>' +
|
|
'</shadow>' +
|
|
'</statement>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection
|
|
.setShadowState({'type': 'stack_block', 'id': '1'});
|
|
assertNextHasBlock(parent, true, '1');
|
|
parent.nextConnection
|
|
.setShadowState({'type': 'stack_block', 'id': '2'});
|
|
assertNextHasBlock(parent, true, '2');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': '2',
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="2"></shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection.setShadowState(
|
|
{
|
|
'type': 'stack_block',
|
|
'id': '1',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'a',
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertNextHasBlock(parent, true, '1');
|
|
assertNextHasBlock(parent.getNextBlock(), true, 'a');
|
|
parent.nextConnection.setShadowState(
|
|
{
|
|
'type': 'stack_block',
|
|
'id': '2',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
}
|
|
);
|
|
assertNextHasBlock(parent, true, '2');
|
|
assertNextHasBlock(parent.getNextBlock(), true, 'b');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': '2',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'b',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="2">' +
|
|
'<next>' +
|
|
'<shadow type="stack_block" id="b"></shadow>' +
|
|
'</next>' +
|
|
'</shadow>' +
|
|
'</next>' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Remove - No Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
function createStatementBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
function createStackBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlocks(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowState(null);
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlocks(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowState(null);
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlocks(this.workspace);
|
|
parent.nextConnection.setShadowState(null);
|
|
assertNextNotHasBlock(parent);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Remove - Block Connected', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
'id': 'id1',
|
|
},
|
|
'block': {
|
|
'type': 'row_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
function createStatementBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
'id': 'id1',
|
|
},
|
|
'block': {
|
|
'type': 'statement_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
function createStackBlocks(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
'id': 'id1',
|
|
},
|
|
'block': {
|
|
'type': 'stack_block',
|
|
'id': 'id2',
|
|
},
|
|
},
|
|
},
|
|
workspace);
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlocks(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowState(null);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'row_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="row_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlocks(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowState(null);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'statement_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="statement_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlocks(this.workspace);
|
|
parent.nextConnection.setShadowState(null);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextNotHasBlock(parent);
|
|
assertSerialization(
|
|
parent,
|
|
{
|
|
'type': 'stack_block',
|
|
'id': 'id0',
|
|
},
|
|
'<block xmlns="https://developers.google.com/blockly/xml" ' +
|
|
'type="stack_block" id="id0">' +
|
|
'</block>'
|
|
);
|
|
});
|
|
});
|
|
|
|
suite('Add - Connect & Disconnect - Remove', function() {
|
|
// These are defined separately in each suite.
|
|
function createRowBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'row_block'}, workspace);
|
|
}
|
|
|
|
function createStatementBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'statement_block'}, workspace);
|
|
}
|
|
|
|
function createStackBlock(workspace) {
|
|
return Blockly.serialization.blocks.append(
|
|
{'type': 'stack_block'}, workspace);
|
|
}
|
|
|
|
test('Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection
|
|
.setShadowState({'type': 'row_block'});
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
const child = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
parent.getInput('INPUT').connection.setShadowState(null);
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
});
|
|
|
|
test('Multiple Value', function() {
|
|
const parent = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.setShadowState({
|
|
'type': 'row_block',
|
|
'inputs': {
|
|
'INPUT': {
|
|
'shadow': {
|
|
'type': 'row_block',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
const child = createRowBlock(this.workspace);
|
|
parent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
assertInputHasBlock(parent, 'INPUT', false);
|
|
parent.getInput('INPUT').connection.disconnect();
|
|
assertInputHasBlock(parent, 'INPUT', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('INPUT'), 'INPUT', true);
|
|
parent.getInput('INPUT').connection.setShadowState(null);
|
|
assertInputNotHasBlock(parent, 'INPUT');
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.setShadowState({'type': 'statement_block'});
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
parent.getInput('NAME').connection.setShadowState(null);
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
});
|
|
|
|
test('Multiple Statement', function() {
|
|
const parent = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection.setShadowState({
|
|
'type': 'statement_block',
|
|
'inputs': {
|
|
'NAME': {
|
|
'shadow': {
|
|
'type': 'statement_block',
|
|
},
|
|
},
|
|
},
|
|
});
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
assertInputHasBlock(parent, 'NAME', false);
|
|
parent.getInput('NAME').connection.disconnect();
|
|
assertInputHasBlock(parent, 'NAME', true);
|
|
assertInputHasBlock(
|
|
parent.getInputTargetBlock('NAME'), 'NAME', true);
|
|
parent.getInput('NAME').connection.setShadowState(null);
|
|
assertInputNotHasBlock(parent, 'NAME');
|
|
});
|
|
|
|
test('Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection.setShadowState({'type': 'stack_block'});
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.nextConnection.connect(child.previousConnection);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
parent.nextConnection.setShadowState(null);
|
|
assertNextNotHasBlock(parent);
|
|
});
|
|
|
|
test('Multiple Next', function() {
|
|
const parent = createStackBlock(this.workspace);
|
|
parent.nextConnection.setShadowState({
|
|
'type': 'stack_block',
|
|
'next': {
|
|
'shadow': {
|
|
'type': 'stack_block',
|
|
},
|
|
},
|
|
});
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
const child = createStatementBlock(this.workspace);
|
|
parent.nextConnection.connect(child.previousConnection);
|
|
assertNextHasBlock(parent, false);
|
|
parent.nextConnection.disconnect();
|
|
assertNextHasBlock(parent, true);
|
|
assertNextHasBlock(parent.getNextBlock(), true);
|
|
parent.nextConnection.setShadowState(null);
|
|
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'}));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Connect', function() {
|
|
setup(function() {
|
|
this.workspace = new Blockly.Workspace();
|
|
Blockly.defineBlocksWithJsonArray([
|
|
{
|
|
"type": "stack_block",
|
|
"message0": "%1",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "FIELD",
|
|
"text": "default",
|
|
},
|
|
],
|
|
"previousStatement": 'check1',
|
|
"nextStatement": 'check1',
|
|
},
|
|
{
|
|
"type": "stack_block_1to2",
|
|
"message0": "",
|
|
"previousStatement": 'check1',
|
|
"nextStatement": 'check2',
|
|
},
|
|
{
|
|
"type": "stack_block_2to1",
|
|
"message0": "",
|
|
"previousStatement": 'check2',
|
|
"nextStatement": 'check1',
|
|
},
|
|
{
|
|
"type": "stack_block_noend",
|
|
"message0": "",
|
|
"previousStatement": 'check1',
|
|
},
|
|
{
|
|
"type": "row_block",
|
|
"message0": "%1 %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "FIELD",
|
|
"text": "default",
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "INPUT",
|
|
"check": 'check1',
|
|
},
|
|
],
|
|
"output": 'check1',
|
|
},
|
|
{
|
|
"type": "row_block_1to2",
|
|
"message0": "%1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "INPUT",
|
|
"check": 'check1',
|
|
},
|
|
],
|
|
"output": 'check2',
|
|
},
|
|
{
|
|
"type": "row_block_2to1",
|
|
"message0": "%1",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "INPUT",
|
|
"check": 'check2',
|
|
},
|
|
],
|
|
"output": 'check1',
|
|
},
|
|
{
|
|
"type": "row_block_noend",
|
|
"message0": "",
|
|
"output": 'check1',
|
|
},
|
|
{
|
|
"type": "row_block_multiple_inputs",
|
|
"message0": "%1 %2",
|
|
"args0": [
|
|
{
|
|
"type": "input_value",
|
|
"name": "INPUT",
|
|
"check": 'check1',
|
|
},
|
|
{
|
|
"type": "input_value",
|
|
"name": "INPUT2",
|
|
"check": 'check1',
|
|
},
|
|
],
|
|
"output": 'check1',
|
|
},
|
|
{
|
|
'type': 'output_to_statements',
|
|
'message0': '%1 %2',
|
|
'args0': [
|
|
{
|
|
'type': 'input_statement',
|
|
'name': 'INPUT',
|
|
'check': 'check1',
|
|
},
|
|
{
|
|
'type': 'input_statement',
|
|
'name': 'INPUT2',
|
|
'check': 'check1',
|
|
},
|
|
],
|
|
'output': 'check1',
|
|
},
|
|
{
|
|
"type": "statement_block",
|
|
"message0": "%1 %2",
|
|
"args0": [
|
|
{
|
|
"type": "field_input",
|
|
"name": "FIELD",
|
|
"text": "default",
|
|
},
|
|
{
|
|
"type": "input_statement",
|
|
"name": "NAME",
|
|
"check": 'check1',
|
|
},
|
|
],
|
|
"previousStatement": 'check1',
|
|
"nextStatement": 'check1',
|
|
},
|
|
{
|
|
"type": "statement_block_1to2",
|
|
"message0": "%1",
|
|
"args0": [
|
|
{
|
|
"type": "input_statement",
|
|
"name": "NAME",
|
|
"check": 'check1',
|
|
},
|
|
],
|
|
"previousStatement": 'check1',
|
|
"nextStatement": 'check2',
|
|
},
|
|
{
|
|
"type": "statement_block_2to1",
|
|
"message0": "%1",
|
|
"args0": [
|
|
{
|
|
"type": "input_statement",
|
|
"name": "NAME",
|
|
"check": 'check2',
|
|
},
|
|
],
|
|
"previousStatement": 'check2',
|
|
"nextStatement": 'check1',
|
|
},
|
|
{
|
|
"type": "statement_block_noend",
|
|
"message0": "%1",
|
|
"args0": [
|
|
{
|
|
"type": "input_statement",
|
|
"name": "NAME",
|
|
"check": 'check1',
|
|
},
|
|
],
|
|
"previousStatement": 'check1',
|
|
},
|
|
]);
|
|
|
|
// Used to make sure we don't get stray shadow blocks or anything.
|
|
this.assertBlockCount = function(count) {
|
|
chai.assert.equal(this.workspace.getAllBlocks().length, count);
|
|
};
|
|
});
|
|
|
|
suite('Disconnect from old parent', function() {
|
|
test('Value', function() {
|
|
const oldParent = this.workspace.newBlock('row_block');
|
|
const newParent = this.workspace.newBlock('row_block');
|
|
const child = this.workspace.newBlock('row_block');
|
|
|
|
oldParent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
newParent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
|
|
chai.assert.isFalse(
|
|
oldParent.getInput('INPUT').connection.isConnected());
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const oldParent = this.workspace.newBlock('statement_block');
|
|
const newParent = this.workspace.newBlock('statement_block');
|
|
const child = this.workspace.newBlock('stack_block');
|
|
|
|
oldParent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
newParent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
|
|
chai.assert.isFalse(
|
|
oldParent.getInput('NAME').connection.isConnected());
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const oldParent = this.workspace.newBlock('stack_block');
|
|
const newParent = this.workspace.newBlock('stack_block');
|
|
const child = this.workspace.newBlock('stack_block');
|
|
|
|
oldParent.nextConnection.connect(child.previousConnection);
|
|
newParent.nextConnection.connect(child.previousConnection);
|
|
|
|
chai.assert.isFalse(oldParent.nextConnection.isConnected());
|
|
this.assertBlockCount(3);
|
|
});
|
|
});
|
|
|
|
suite('Shadow dissolves', function() {
|
|
test('Value', function() {
|
|
const newParent = this.workspace.newBlock('row_block');
|
|
const child = this.workspace.newBlock('row_block');
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block"/>'
|
|
);
|
|
newParent.getInput('INPUT').connection.setShadowDom(xml);
|
|
chai.assert.isTrue(newParent.getInputTargetBlock('INPUT').isShadow());
|
|
|
|
newParent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
|
|
chai.assert.isFalse(newParent.getInputTargetBlock('INPUT').isShadow());
|
|
this.assertBlockCount(2);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const newParent = this.workspace.newBlock('statement_block');
|
|
const child = this.workspace.newBlock('stack_block');
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newParent.getInput('NAME').connection.setShadowDom(xml);
|
|
chai.assert.isTrue(
|
|
newParent.getInputTargetBlock('NAME').isShadow());
|
|
|
|
newParent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
|
|
chai.assert.isFalse(
|
|
newParent.getInputTargetBlock('NAME').isShadow());
|
|
this.assertBlockCount(2);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const newParent = this.workspace.newBlock('stack_block');
|
|
const child = this.workspace.newBlock('stack_block');
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newParent.nextConnection.setShadowDom(xml);
|
|
chai.assert.isTrue(newParent.getNextBlock().isShadow());
|
|
|
|
newParent.nextConnection.connect(child.previousConnection);
|
|
|
|
chai.assert.isFalse(newParent.getNextBlock().isShadow());
|
|
this.assertBlockCount(2);
|
|
});
|
|
});
|
|
|
|
suite('Saving shadow values', function() {
|
|
test('Value', function() {
|
|
const newParent = this.workspace.newBlock('row_block');
|
|
const child = this.workspace.newBlock('row_block');
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="row_block"/>'
|
|
);
|
|
newParent.getInput('INPUT').connection.setShadowDom(xml);
|
|
newParent.getInputTargetBlock('INPUT').setFieldValue('new', 'FIELD');
|
|
|
|
newParent.getInput('INPUT').connection.connect(child.outputConnection);
|
|
newParent.getInput('INPUT').connection.disconnect();
|
|
|
|
const target = newParent.getInputTargetBlock('INPUT');
|
|
chai.assert.isTrue(target.isShadow());
|
|
chai.assert.equal(target.getFieldValue('FIELD'), 'new');
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Statement', function() {
|
|
const newParent = this.workspace.newBlock('statement_block');
|
|
const child = this.workspace.newBlock('stack_block');
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newParent.getInput('NAME').connection.setShadowDom(xml);
|
|
newParent.getInputTargetBlock('NAME')
|
|
.setFieldValue('new', 'FIELD');
|
|
|
|
newParent.getInput('NAME').connection
|
|
.connect(child.previousConnection);
|
|
newParent.getInput('NAME').connection.disconnect();
|
|
|
|
const target = newParent.getInputTargetBlock('NAME');
|
|
chai.assert.isTrue(target.isShadow());
|
|
chai.assert.equal(target.getFieldValue('FIELD'), 'new');
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Next', function() {
|
|
const newParent = this.workspace.newBlock('stack_block');
|
|
const child = this.workspace.newBlock('stack_block');
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newParent.nextConnection.setShadowDom(xml);
|
|
newParent.getNextBlock().setFieldValue('new', 'FIELD');
|
|
|
|
newParent.nextConnection.connect(child.previousConnection);
|
|
newParent.nextConnection.disconnect();
|
|
|
|
const target = newParent.getNextBlock();
|
|
chai.assert.isTrue(target.isShadow());
|
|
chai.assert.equal(target.getFieldValue('FIELD'), 'new');
|
|
this.assertBlockCount(3);
|
|
});
|
|
});
|
|
|
|
suite('Reattach or bump orphan', function() {
|
|
suite('Value', function() {
|
|
suite('No available spots', function() {
|
|
test('No connection', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock('row_block_noend');
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('All statements', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock('output_to_statements');
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('Bad checks', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock('row_block_2to1');
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('Through different types', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock('row_block_2to1');
|
|
const otherChild = this.workspace.newBlock('row_block_1to2');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection
|
|
.connect(otherChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
});
|
|
|
|
suite('Multiple available spots', function() {
|
|
suite('No shadows', function() {
|
|
test('Top block', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock(
|
|
'row_block_multiple_inputs');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('Child blocks', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock(
|
|
'row_block_multiple_inputs');
|
|
const childX = this.workspace.newBlock('row_block');
|
|
const childY = this.workspace.newBlock('row_block');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection
|
|
.connect(childX.outputConnection);
|
|
newChild.getInput('INPUT2').connection
|
|
.connect(childY.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('Spots filled', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock(
|
|
'row_block_multiple_inputs');
|
|
const otherChild = this.workspace.newBlock('row_block_noend');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection
|
|
.connect(otherChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
});
|
|
|
|
suite('Shadows', function() {
|
|
test('Top block', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock(
|
|
'row_block_multiple_inputs');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection.setShadowDom(
|
|
Blockly.utils.xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
|
.firstChild);
|
|
newChild.getInput('INPUT2').connection.setShadowDom(
|
|
Blockly.utils.xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
|
.firstChild);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('Child blocks', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock(
|
|
'row_block_multiple_inputs');
|
|
const childX = this.workspace.newBlock('row_block');
|
|
const childY = this.workspace.newBlock('row_block');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection
|
|
.connect(childX.outputConnection);
|
|
newChild.getInput('INPUT2').connection
|
|
.connect(childY.outputConnection);
|
|
childX.getInput('INPUT').connection.setShadowDom(
|
|
Blockly.utils.xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
|
.firstChild);
|
|
childY.getInput('INPUT').connection.setShadowDom(
|
|
Blockly.utils.xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
|
.firstChild);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
|
|
test('Spots filled', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock(
|
|
'row_block_multiple_inputs');
|
|
const otherChild = this.workspace.newBlock('row_block_noend');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection
|
|
.connect(otherChild.outputConnection);
|
|
newChild.getInput('INPUT2').connection.setShadowDom(
|
|
Blockly.utils.xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
|
.firstChild);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isFalse(
|
|
oldChild.outputConnection.isConnected());
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Single available spot', function() {
|
|
test('No shadows', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock('row_block');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isTrue(
|
|
newChild.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
newChild.getInputTargetBlock('INPUT'), oldChild);
|
|
});
|
|
|
|
test('Shadows', function() {
|
|
const parent = this.workspace.newBlock('row_block');
|
|
const oldChild = this.workspace.newBlock('row_block');
|
|
const newChild = this.workspace.newBlock('row_block');
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(oldChild.outputConnection);
|
|
newChild.getInput('INPUT').connection.setShadowDom(
|
|
Blockly.utils.xml.textToDom('<xml><shadow type="row_block"/></xml>')
|
|
.firstChild);
|
|
|
|
parent.getInput('INPUT').connection
|
|
.connect(newChild.outputConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('INPUT'), newChild);
|
|
chai.assert.isTrue(
|
|
newChild.getInput('INPUT').connection.isConnected());
|
|
chai.assert.equal(
|
|
newChild.getInputTargetBlock('INPUT'), oldChild);
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Statement', function() {
|
|
suite('No shadows', function() {
|
|
test('Simple', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild);
|
|
chai.assert.isTrue(newChild.nextConnection.isConnected());
|
|
chai.assert.equal(newChild.getNextBlock(), oldChild);
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Bad check in between', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild1 = this.workspace.newBlock('stack_block_1to2');
|
|
const newChild2 = this.workspace.newBlock('stack_block_2to1');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
newChild1.nextConnection.connect(newChild2.previousConnection);
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild1.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild1);
|
|
chai.assert.isTrue(newChild2.nextConnection.isConnected());
|
|
chai.assert.equal(newChild2.getNextBlock(), oldChild);
|
|
this.assertBlockCount(4);
|
|
});
|
|
|
|
test('Bad check at end', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block_1to2');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
const spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect');
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild);
|
|
chai.assert.isFalse(newChild.nextConnection.isConnected());
|
|
chai.assert.isTrue(spy.calledOnce);
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('No end connection', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block_noend');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
const spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect');
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild);
|
|
chai.assert.isTrue(spy.calledOnce);
|
|
this.assertBlockCount(3);
|
|
});
|
|
});
|
|
|
|
suite('Shadows', function() {
|
|
test('Simple', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newChild.nextConnection.setShadowDom(xml);
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild);
|
|
chai.assert.isTrue(newChild.nextConnection.isConnected());
|
|
chai.assert.equal(newChild.getNextBlock(), oldChild);
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Bad check in between', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild1 = this.workspace.newBlock('stack_block_1to2');
|
|
const newChild2 = this.workspace.newBlock('stack_block_2to1');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
newChild1.nextConnection.connect(newChild2.previousConnection);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newChild2.nextConnection.setShadowDom(xml);
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild1.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild1);
|
|
chai.assert.isTrue(newChild2.nextConnection.isConnected());
|
|
chai.assert.equal(newChild2.getNextBlock(), oldChild);
|
|
this.assertBlockCount(4);
|
|
});
|
|
|
|
test('Bad check at end', function() {
|
|
const parent = this.workspace.newBlock('statement_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block_1to2');
|
|
parent.getInput('NAME').connection
|
|
.connect(oldChild.previousConnection);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block_2to1"/>'
|
|
);
|
|
newChild.nextConnection.setShadowDom(xml);
|
|
const spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect');
|
|
|
|
parent.getInput('NAME').connection
|
|
.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(
|
|
parent.getInput('NAME').connection.isConnected());
|
|
chai.assert.equal(
|
|
parent.getInputTargetBlock('NAME'), newChild);
|
|
chai.assert.isTrue(newChild.nextConnection.isConnected());
|
|
chai.assert.isTrue(newChild.getNextBlock().isShadow());
|
|
chai.assert.isTrue(spy.calledOnce);
|
|
this.assertBlockCount(4);
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Next', function() {
|
|
suite('No shadows', function() {
|
|
test('Simple', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
|
|
parent.nextConnection.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild);
|
|
chai.assert.isTrue(newChild.nextConnection.isConnected());
|
|
chai.assert.equal(newChild.getNextBlock(), oldChild);
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Bad check in between', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild1 = this.workspace.newBlock('stack_block_1to2');
|
|
const newChild2 = this.workspace.newBlock('stack_block_2to1');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
newChild1.nextConnection.connect(newChild2.previousConnection);
|
|
|
|
parent.nextConnection.connect(newChild1.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild1);
|
|
chai.assert.isTrue(newChild2.nextConnection.isConnected());
|
|
chai.assert.equal(newChild2.getNextBlock(), oldChild);
|
|
this.assertBlockCount(4);
|
|
});
|
|
|
|
test('Bad check at end', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block_1to2');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
const spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect');
|
|
|
|
parent.nextConnection.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild);
|
|
chai.assert.isFalse(newChild.nextConnection.isConnected());
|
|
chai.assert.isTrue(spy.calledOnce);
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('No end connection', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block_noend');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
const spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect');
|
|
|
|
parent.nextConnection.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild);
|
|
chai.assert.isTrue(spy.calledOnce);
|
|
this.assertBlockCount(3);
|
|
});
|
|
});
|
|
|
|
suite('Shadows', function() {
|
|
test('Simple', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newChild.nextConnection.setShadowDom(xml);
|
|
|
|
parent.nextConnection.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild);
|
|
chai.assert.isTrue(newChild.nextConnection.isConnected());
|
|
chai.assert.equal(newChild.getNextBlock(), oldChild);
|
|
this.assertBlockCount(3);
|
|
});
|
|
|
|
test('Bad check in between', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild1 = this.workspace.newBlock('stack_block_1to2');
|
|
const newChild2 = this.workspace.newBlock('stack_block_2to1');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
newChild1.nextConnection.connect(newChild2.previousConnection);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block"/>'
|
|
);
|
|
newChild2.nextConnection.setShadowDom(xml);
|
|
|
|
parent.nextConnection.connect(newChild1.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild1);
|
|
chai.assert.isTrue(newChild2.nextConnection.isConnected());
|
|
chai.assert.equal(newChild2.getNextBlock(), oldChild);
|
|
this.assertBlockCount(4);
|
|
});
|
|
|
|
test('Bad check at end', function() {
|
|
const parent = this.workspace.newBlock('stack_block');
|
|
const oldChild = this.workspace.newBlock('stack_block');
|
|
const newChild = this.workspace.newBlock('stack_block_1to2');
|
|
parent.nextConnection.connect(oldChild.previousConnection);
|
|
const xml = Blockly.utils.xml.textToDom(
|
|
'<shadow type="stack_block_2to1"/>'
|
|
);
|
|
newChild.nextConnection.setShadowDom(xml);
|
|
const spy = sinon.spy(oldChild.previousConnection, 'onFailedConnect');
|
|
|
|
parent.nextConnection.connect(newChild.previousConnection);
|
|
|
|
chai.assert.isTrue(parent.nextConnection.isConnected());
|
|
chai.assert.equal(parent.getNextBlock(), newChild);
|
|
chai.assert.isTrue(newChild.nextConnection.isConnected());
|
|
chai.assert.isTrue(newChild.getNextBlock().isShadow());
|
|
chai.assert.isTrue(spy.calledOnce);
|
|
this.assertBlockCount(4);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|