mirror of
https://github.com/google/blockly.git
synced 2026-01-08 01:20:12 +01:00
feat: add serialization of child blocks (#5120)
* Add tests for serializing connected blocks * Add serialization of child blocks * Add tests for not serializing children * Add options for not serializing children * Fix types * Change addNextBlocks to default to true * Cleanup * Fix types
This commit is contained in:
committed by
alschmiedt
parent
8faa360b74
commit
56d3cb6c8f
@@ -15,11 +15,25 @@ goog.module.declareLegacyNamespace();
|
|||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
const Block = goog.requireType('Blockly.Block');
|
const Block = goog.requireType('Blockly.Block');
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const Connection = goog.requireType('Blockly.Connection');
|
||||||
|
const Xml = goog.require('Blockly.Xml');
|
||||||
|
const inputTypes = goog.require('Blockly.inputTypes');
|
||||||
|
|
||||||
|
|
||||||
// TODO: Remove this once lint is fixed.
|
// TODO: Remove this once lint is fixed.
|
||||||
/* eslint-disable no-use-before-define */
|
/* eslint-disable no-use-before-define */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the state of a connection.
|
||||||
|
* @typedef {{
|
||||||
|
* shadow: (!State|undefined),
|
||||||
|
* block: (!State|undefined)
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
var ConnectionState;
|
||||||
|
exports.ConnectionState = ConnectionState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the state of a given block.
|
* Represents the state of a given block.
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
@@ -35,7 +49,9 @@ const Block = goog.requireType('Blockly.Block');
|
|||||||
* inline: (boolean|undefined),
|
* inline: (boolean|undefined),
|
||||||
* data: (string|undefined),
|
* data: (string|undefined),
|
||||||
* extra-state: *,
|
* extra-state: *,
|
||||||
* fields: (Object<string, *>|undefined),
|
* fields: (!Object<string, *>|undefined),
|
||||||
|
* inputs: (!Object<string, !ConnectionState>|undefined),
|
||||||
|
* next: (!ConnectionState|undefined)
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
var State;
|
var State;
|
||||||
@@ -44,14 +60,27 @@ exports.State = State;
|
|||||||
/**
|
/**
|
||||||
* Returns the state of the given block as a plain JavaScript object.
|
* Returns the state of the given block as a plain JavaScript object.
|
||||||
* @param {!Block} block The block to serialize.
|
* @param {!Block} block The block to serialize.
|
||||||
* @param {{addCoordinates: (boolean|undefined)}=} param1
|
* @param {{addCoordinates: (boolean|undefined), addInputBlocks:
|
||||||
* addCoordinates: If true the coordinates of the block are added to the
|
* (boolean|undefined), addNextBlocks: (boolean|undefined)}=} param1
|
||||||
|
* addCoordinates: If true, the coordinates of the block are added to the
|
||||||
* serialized state. False by default.
|
* serialized state. False by default.
|
||||||
|
* addinputBlocks: If true, children of the block which are connected to
|
||||||
|
* inputs will be serialized. True by default.
|
||||||
|
* addNextBlocks: If true, children of the block which are connected to the
|
||||||
|
* block's next connection (if it exists) will be serialized.
|
||||||
|
* True by default.
|
||||||
* @return {?State} The serialized state of the
|
* @return {?State} The serialized state of the
|
||||||
* block, or null if the block could not be serialied (eg it was an
|
* block, or null if the block could not be serialied (eg it was an
|
||||||
* insertion marker).
|
* insertion marker).
|
||||||
*/
|
*/
|
||||||
const save = function(block, {addCoordinates = false} = {}) {
|
const save = function(
|
||||||
|
block,
|
||||||
|
{
|
||||||
|
addCoordinates = false,
|
||||||
|
addInputBlocks = true,
|
||||||
|
addNextBlocks = true
|
||||||
|
} = {}
|
||||||
|
) {
|
||||||
if (block.isInsertionMarker()) {
|
if (block.isInsertionMarker()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -62,11 +91,17 @@ const save = function(block, {addCoordinates = false} = {}) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (addCoordinates) {
|
if (addCoordinates) {
|
||||||
addCoords(block, state);
|
saveCoords(block, state);
|
||||||
|
}
|
||||||
|
saveAttributes(block, state);
|
||||||
|
saveExtraState(block, state);
|
||||||
|
saveFields(block, state);
|
||||||
|
if (addInputBlocks) {
|
||||||
|
saveInputBlocks(block, state);
|
||||||
|
}
|
||||||
|
if (addNextBlocks) {
|
||||||
|
saveNextBlocks(block, state);
|
||||||
}
|
}
|
||||||
addAttributes(block, state);
|
|
||||||
addExtraState(block, state);
|
|
||||||
addFields(block, state);
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
@@ -78,7 +113,7 @@ exports.save = save;
|
|||||||
* @param {!Block} block The block to base the attributes on.
|
* @param {!Block} block The block to base the attributes on.
|
||||||
* @param {!State} state The state object to append to.
|
* @param {!State} state The state object to append to.
|
||||||
*/
|
*/
|
||||||
const addAttributes = function(block, state) {
|
const saveAttributes = function(block, state) {
|
||||||
if (block.isCollapsed()) {
|
if (block.isCollapsed()) {
|
||||||
state['collapsed'] = true;
|
state['collapsed'] = true;
|
||||||
}
|
}
|
||||||
@@ -111,7 +146,7 @@ const addAttributes = function(block, state) {
|
|||||||
* @param {!Block} block The block to base the coordinates on
|
* @param {!Block} block The block to base the coordinates on
|
||||||
* @param {!State} state The state object to append to
|
* @param {!State} state The state object to append to
|
||||||
*/
|
*/
|
||||||
const addCoords = function(block, state) {
|
const saveCoords = function(block, state) {
|
||||||
const workspace = block.workspace;
|
const workspace = block.workspace;
|
||||||
const xy = block.getRelativeToSurfaceXY();
|
const xy = block.getRelativeToSurfaceXY();
|
||||||
state['x'] = Math.round(workspace.RTL ? workspace.getWidth() - xy.x : xy.x);
|
state['x'] = Math.round(workspace.RTL ? workspace.getWidth() - xy.x : xy.x);
|
||||||
@@ -123,7 +158,7 @@ const addCoords = function(block, state) {
|
|||||||
* @param {!Block} block The block to serialize the extra state of.
|
* @param {!Block} block The block to serialize the extra state of.
|
||||||
* @param {!State} state The state object to append to.
|
* @param {!State} state The state object to append to.
|
||||||
*/
|
*/
|
||||||
const addExtraState = function(block, state) {
|
const saveExtraState = function(block, state) {
|
||||||
if (block.saveExtraState) {
|
if (block.saveExtraState) {
|
||||||
const extraState = block.saveExtraState();
|
const extraState = block.saveExtraState();
|
||||||
if (extraState !== null) {
|
if (extraState !== null) {
|
||||||
@@ -137,7 +172,7 @@ const addExtraState = function(block, state) {
|
|||||||
* @param {!Block} block The block to serialize the field state of.
|
* @param {!Block} block The block to serialize the field state of.
|
||||||
* @param {!State} state The state object to append to.
|
* @param {!State} state The state object to append to.
|
||||||
*/
|
*/
|
||||||
const addFields = function(block, state) {
|
const saveFields = function(block, state) {
|
||||||
let hasFieldState = false;
|
let hasFieldState = false;
|
||||||
let fields = Object.create(null);
|
let fields = Object.create(null);
|
||||||
for (let i = 0; i < block.inputList.length; i++) {
|
for (let i = 0; i < block.inputList.length; i++) {
|
||||||
@@ -154,3 +189,69 @@ const addFields = function(block, state) {
|
|||||||
state['fields'] = fields;
|
state['fields'] = fields;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the state of all of the child blocks of the given block (which are
|
||||||
|
* connected to inputs) to the given state object.
|
||||||
|
* @param {!Block} block The block to serialize the input blocks of.
|
||||||
|
* @param {!State} state The state object to append to.
|
||||||
|
*/
|
||||||
|
const saveInputBlocks = function(block, state) {
|
||||||
|
const inputs = Object.create(null);
|
||||||
|
for (let i = 0; i < block.inputList.length; i++) {
|
||||||
|
const input = block.inputList[i];
|
||||||
|
if (input.type === inputTypes.DUMMY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const connectionState =
|
||||||
|
saveConnection(/** @type {!Connection} */ (input.connection));
|
||||||
|
if (connectionState) {
|
||||||
|
inputs[input.name] = connectionState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(inputs).length) {
|
||||||
|
state['inputs'] = inputs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the state of all of the next blocks of the given block to the given
|
||||||
|
* state object.
|
||||||
|
* @param {!Block} block The block to serialize the next blocks of.
|
||||||
|
* @param {!State} state The state object to append to.
|
||||||
|
*/
|
||||||
|
const saveNextBlocks = function(block, state) {
|
||||||
|
if (!block.nextConnection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const connectionState = saveConnection(block.nextConnection);
|
||||||
|
if (connectionState) {
|
||||||
|
state['next'] = connectionState;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the state of the given connection (ie the state of any connected
|
||||||
|
* shadow or real blocks).
|
||||||
|
* @param {!Connection} connection The connection to serialize the connected
|
||||||
|
* blocks of.
|
||||||
|
* @return {?ConnectionState} An object containing the state of any connected
|
||||||
|
* shadow block, or any connected real block.
|
||||||
|
*/
|
||||||
|
const saveConnection = function(connection) {
|
||||||
|
const shadow = connection.getShadowDom();
|
||||||
|
const child = connection.targetBlock();
|
||||||
|
if (!shadow && !child) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var state = Object.create(null);
|
||||||
|
if (shadow) {
|
||||||
|
state['shadow'] = Xml.domToText(shadow)
|
||||||
|
.replace('xmlns="https://developers.google.com/blockly/xml"', '');
|
||||||
|
}
|
||||||
|
if (child) {
|
||||||
|
state['block'] = save(child);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Ren
|
|||||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.blocks', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.serialization.blocks', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||||
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar'], ['Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||||
goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
goog.addDependency('../../core/scrollbar_pair.js', ['Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Scrollbar', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||||
goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], [], {'lang': 'es6', 'module': 'goog'});
|
goog.addDependency('../../core/serialization/blocks.js', ['Blockly.serialization.blocks'], ['Blockly.Xml', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'});
|
||||||
goog.addDependency('../../core/serialization/serialization.js', ['Blockly.serialization'], [], {'module': 'goog'});
|
goog.addDependency('../../core/serialization/serialization.js', ['Blockly.serialization'], [], {'module': 'goog'});
|
||||||
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.common', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'});
|
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.common', 'Blockly.utils.KeyCodes'], {'lang': 'es6', 'module': 'goog'});
|
||||||
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||||
|
|||||||
@@ -343,5 +343,295 @@ suite('JSO', function() {
|
|||||||
assertProperty(jso, 'fields', {'FIELD': ['state1', 42, true]});
|
assertProperty(jso, 'fields', {'FIELD': ['state1', 42, true]});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
suite('Connected blocks', function() {
|
||||||
|
setup(function() {
|
||||||
|
this.assertInput = function(jso, name, value) {
|
||||||
|
chai.assert.deepInclude(jso['inputs'][name], value);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.createBlockWithChild = function(blockType, inputName) {
|
||||||
|
const block = this.workspace.newBlock(blockType);
|
||||||
|
const childBlock = this.workspace.newBlock(blockType);
|
||||||
|
block.getInput(inputName).connection.connect(
|
||||||
|
childBlock.outputConnection || childBlock.previousConnection);
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.createBlockWithShadow = function(blockType, inputName) {
|
||||||
|
const block = this.workspace.newBlock(blockType);
|
||||||
|
block.getInput(inputName).connection.setShadowDom(
|
||||||
|
Blockly.Xml.textToDom(
|
||||||
|
'<block type="' + blockType + '" id="test"></block>'));
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.createBlockWithShadowAndChild = function(blockType, inputName) {
|
||||||
|
const block = this.workspace.newBlock(blockType);
|
||||||
|
const childBlock = this.workspace.newBlock(blockType);
|
||||||
|
block.getInput(inputName).connection.connect(
|
||||||
|
childBlock.outputConnection || childBlock.previousConnection);
|
||||||
|
block.getInput(inputName).connection.setShadowDom(
|
||||||
|
Blockly.Xml.textToDom(
|
||||||
|
'<block type="' + blockType + '" id="test"></block>'));
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertChild = function(blockType, inputName) {
|
||||||
|
const block = this.createBlockWithChild(blockType, inputName);
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
this.assertInput(
|
||||||
|
jso, inputName, {'block': { 'type': blockType, 'id': 'id2'}});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertShadow = function(blockType, inputName) {
|
||||||
|
const block = this.createBlockWithShadow(blockType, inputName);
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
this.assertInput(
|
||||||
|
jso, inputName, {'shadow': { 'type': blockType, 'id': 'test'}});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertOverwrittenShadow = function(blockType, inputName) {
|
||||||
|
const block =
|
||||||
|
this.createBlockWithShadowAndChild(blockType, inputName);
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
this.assertInput(
|
||||||
|
jso,
|
||||||
|
inputName,
|
||||||
|
{
|
||||||
|
'block': {
|
||||||
|
'type': blockType,
|
||||||
|
'id': 'id2'
|
||||||
|
},
|
||||||
|
'shadow': {
|
||||||
|
'type': blockType,
|
||||||
|
'id': 'test'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertNoChild = function(blockType, inputName) {
|
||||||
|
const block = this.createBlockWithChild(blockType, inputName);
|
||||||
|
const jso =
|
||||||
|
Blockly.serialization.blocks.save(block, {addInputBlocks: false});
|
||||||
|
chai.assert.isUndefined(jso['inputs']);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertNoShadow = function(blockType, inputName) {
|
||||||
|
const block = this.createBlockWithShadow(blockType, inputName);
|
||||||
|
const jso =
|
||||||
|
Blockly.serialization.blocks.save(block, {addInputBlocks: false});
|
||||||
|
chai.assert.isUndefined(jso['inputs']);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.assertNoOverwrittenShadow = function(blockType, inputName) {
|
||||||
|
const block =
|
||||||
|
this.createBlockWithShadowAndChild(blockType, inputName);
|
||||||
|
const jso =
|
||||||
|
Blockly.serialization.blocks.save(block, {addInputBlocks: false});
|
||||||
|
chai.assert.isUndefined(jso['inputs']);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('Value', function() {
|
||||||
|
suite('With serialization', function() {
|
||||||
|
test('Child', function() {
|
||||||
|
this.assertChild('row_block', 'INPUT');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip('Shadow', function() {
|
||||||
|
this.assertShadow('row_block', 'INPUT');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip('Overwritten shadow', function() {
|
||||||
|
this.assertOverwrittenShadow('row_block', 'INPUT');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('Without serialization', function() {
|
||||||
|
test('Child', function() {
|
||||||
|
this.assertNoChild('row_block', 'INPUT');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Shadow', function() {
|
||||||
|
this.assertNoShadow('row_block', 'INPUT');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Overwritten shadow', function() {
|
||||||
|
this.assertNoOverwrittenShadow('row_block', 'INPUT');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('Statement', function() {
|
||||||
|
suite('With serialization', function() {
|
||||||
|
test('Child', function() {
|
||||||
|
this.assertChild('statement_block', 'NAME');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip('Shadow', function() {
|
||||||
|
this.assertShadow('statement_block', 'NAME');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip('Overwritten shadow', function() {
|
||||||
|
this.assertOverwrittenShadow('statement_block', 'NAME');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Child with next blocks', function() {
|
||||||
|
const block = this.workspace.newBlock('statement_block');
|
||||||
|
const childBlock = this.workspace.newBlock('stack_block');
|
||||||
|
const grandChildBlock = this.workspace.newBlock('stack_block');
|
||||||
|
block.getInput('NAME').connection
|
||||||
|
.connect(childBlock.previousConnection);
|
||||||
|
childBlock.nextConnection
|
||||||
|
.connect(grandChildBlock.previousConnection);
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
this.assertInput(
|
||||||
|
jso,
|
||||||
|
'NAME',
|
||||||
|
{
|
||||||
|
'block': {
|
||||||
|
'type': 'stack_block',
|
||||||
|
'id': 'id2',
|
||||||
|
'next': {
|
||||||
|
'block': {
|
||||||
|
'type': 'stack_block',
|
||||||
|
'id': 'id4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('Without serialization', function() {
|
||||||
|
test('Child', function() {
|
||||||
|
this.assertNoChild('statement_block', 'NAME');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Shadow', function() {
|
||||||
|
this.assertNoShadow('statement_block', 'NAME');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Overwritten shadow', function() {
|
||||||
|
this.assertNoOverwrittenShadow('statement_block', 'NAME');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('Next', function() {
|
||||||
|
setup(function() {
|
||||||
|
this.createNextWithChild = function() {
|
||||||
|
const block = this.workspace.newBlock('stack_block');
|
||||||
|
const childBlock = this.workspace.newBlock('stack_block');
|
||||||
|
block.nextConnection.connect(childBlock.previousConnection);
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.createNextWithShadow = function() {
|
||||||
|
const block = this.workspace.newBlock('stack_block');
|
||||||
|
block.nextConnection.setShadowDom(
|
||||||
|
Blockly.Xml.textToDom(
|
||||||
|
'<block type="stack_block" id="test"></block>'));
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.createNextWithShadowAndChild = function() {
|
||||||
|
const block = this.workspace.newBlock('stack_block');
|
||||||
|
const childBlock = this.workspace.newBlock('stack_block');
|
||||||
|
block.nextConnection.connect(childBlock.previousConnection);
|
||||||
|
block.nextConnection.setShadowDom(
|
||||||
|
Blockly.Xml.textToDom(
|
||||||
|
'<block type="stack_block" id="test"></block>'));
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('With serialization', function() {
|
||||||
|
test('Child', function() {
|
||||||
|
const block = this.createNextWithChild();
|
||||||
|
const jso =
|
||||||
|
Blockly.serialization.blocks.save(block);
|
||||||
|
chai.assert.deepInclude(
|
||||||
|
jso['next'], {'block': { 'type': 'stack_block', 'id': 'id2'}});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip('Shadow', function() {
|
||||||
|
const block = this.createNextWithShadow();
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
chai.assert.deepInclude(
|
||||||
|
jso['next'], {'shadow': { 'type': 'stack_block', 'id': 'test'}});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip('Overwritten shadow', function() {
|
||||||
|
const block = this.createNextWithShadowAndChild();
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
chai.assert.deepInclude(
|
||||||
|
jso['next'],
|
||||||
|
{
|
||||||
|
'block': {
|
||||||
|
'type': 'stack_block',
|
||||||
|
'id': 'id2'
|
||||||
|
},
|
||||||
|
'shadow': {
|
||||||
|
'type': 'stack_block',
|
||||||
|
'id': 'test'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Next block with inputs', function() {
|
||||||
|
const block = this.workspace.newBlock('stack_block');
|
||||||
|
const childBlock = this.workspace.newBlock('statement_block');
|
||||||
|
const grandChildBlock = this.workspace.newBlock('stack_block');
|
||||||
|
block.nextConnection.connect(childBlock.previousConnection);
|
||||||
|
childBlock.getInput('NAME').connection
|
||||||
|
.connect(grandChildBlock.previousConnection);
|
||||||
|
const jso = Blockly.serialization.blocks.save(block);
|
||||||
|
chai.assert.deepInclude(
|
||||||
|
jso['next'],
|
||||||
|
{
|
||||||
|
'block': {
|
||||||
|
'type': 'statement_block',
|
||||||
|
'id': 'id2',
|
||||||
|
'inputs': {
|
||||||
|
'NAME': {
|
||||||
|
'block': {
|
||||||
|
'type': 'stack_block',
|
||||||
|
'id': 'id4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite('Without serialization', function() {
|
||||||
|
test('Child', function() {
|
||||||
|
const block = this.createNextWithChild();
|
||||||
|
const jso = Blockly.serialization.blocks.save(
|
||||||
|
block, {addNextBlocks: false});
|
||||||
|
chai.assert.isUndefined(jso['next']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Shadow', function() {
|
||||||
|
const block = this.createNextWithShadow();
|
||||||
|
const jso = Blockly.serialization.blocks.save(
|
||||||
|
block, {addNextBlocks: false});
|
||||||
|
chai.assert.isUndefined(jso['next']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Overwritten shadow', function() {
|
||||||
|
const block = this.createNextWithShadowAndChild();
|
||||||
|
const jso = Blockly.serialization.blocks.save(
|
||||||
|
block, {addNextBlocks: false});
|
||||||
|
chai.assert.isUndefined(jso['next']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user