mirror of
https://github.com/google/blockly.git
synced 2026-01-08 01:20:12 +01:00
Merge branch 'rc/v12.0.0' into develop-v12-merge
This commit is contained in:
@@ -1421,6 +1421,10 @@ suite('Blocks', function () {
|
||||
return Blockly.utils.Size(0, 0);
|
||||
}
|
||||
|
||||
setBubbleLocation() {}
|
||||
|
||||
getBubbleLocation() {}
|
||||
|
||||
bubbleIsVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ suite('Comment Deserialization', function () {
|
||||
test('Toolbox', function () {
|
||||
// Place from toolbox.
|
||||
const toolbox = this.workspace.getToolbox();
|
||||
simulateClick(toolbox.HtmlDiv.querySelector('.blocklyTreeRow'));
|
||||
simulateClick(toolbox.HtmlDiv.querySelector('.blocklyToolboxCategory'));
|
||||
simulateClick(
|
||||
toolbox.getFlyout().svgGroup_.querySelector('.blocklyPath'),
|
||||
);
|
||||
|
||||
@@ -141,4 +141,30 @@ suite('Comments', function () {
|
||||
assertBubbleSize(this.comment, 100, 100);
|
||||
});
|
||||
});
|
||||
suite('Set/Get Bubble Location', function () {
|
||||
teardown(function () {
|
||||
sinon.restore();
|
||||
});
|
||||
function assertBubbleLocation(comment, x, y) {
|
||||
const location = comment.getBubbleLocation();
|
||||
assert.equal(location.x, x);
|
||||
assert.equal(location.y, y);
|
||||
}
|
||||
test('Set Location While Visible', function () {
|
||||
this.comment.setBubbleVisible(true);
|
||||
|
||||
this.comment.setBubbleLocation(new Blockly.utils.Coordinate(100, 100));
|
||||
assertBubbleLocation(this.comment, 100, 100);
|
||||
|
||||
this.comment.setBubbleVisible(false);
|
||||
assertBubbleLocation(this.comment, 100, 100);
|
||||
});
|
||||
test('Set Location While Invisible', function () {
|
||||
this.comment.setBubbleLocation(new Blockly.utils.Coordinate(100, 100));
|
||||
assertBubbleLocation(this.comment, 100, 100);
|
||||
|
||||
this.comment.setBubbleVisible(true);
|
||||
assertBubbleLocation(this.comment, 100, 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import {callbackFactory} from '../../build/src/core/contextmenu.js';
|
||||
import * as xmlUtils from '../../build/src/core/utils/xml.js';
|
||||
import * as Variables from '../../build/src/core/variables.js';
|
||||
import {assert} from '../../node_modules/chai/chai.js';
|
||||
import {
|
||||
sharedTestSetup,
|
||||
@@ -32,9 +31,13 @@ suite('Context Menu', function () {
|
||||
});
|
||||
|
||||
test('callback with xml state creates block', function () {
|
||||
const xmlField = Variables.generateVariableFieldDom(
|
||||
this.forLoopBlock.getField('VAR').getVariable(),
|
||||
);
|
||||
const variable = this.forLoopBlock.getField('VAR').getVariable();
|
||||
const xmlField = document.createElement('field');
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
xmlField.setAttribute('id', variable.getId());
|
||||
xmlField.setAttribute('variabletype', variable.getType());
|
||||
xmlField.textContent = variable.getName();
|
||||
|
||||
const xmlBlock = xmlUtils.createElement('block');
|
||||
xmlBlock.setAttribute('type', 'variables_get');
|
||||
xmlBlock.appendChild(xmlField);
|
||||
|
||||
43
tests/mocha/event_var_type_change_test.js
Normal file
43
tests/mocha/event_var_type_change_test.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2024 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {assert} from '../../node_modules/chai/chai.js';
|
||||
import {
|
||||
sharedTestSetup,
|
||||
sharedTestTeardown,
|
||||
} from './test_helpers/setup_teardown.js';
|
||||
|
||||
suite('Var Type Change Event', function () {
|
||||
setup(function () {
|
||||
sharedTestSetup.call(this);
|
||||
this.workspace = new Blockly.Workspace();
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
sharedTestTeardown.call(this);
|
||||
});
|
||||
|
||||
suite('Serialization', function () {
|
||||
test('variable type change events round-trip through JSON', function () {
|
||||
const varModel = new Blockly.VariableModel(
|
||||
this.workspace,
|
||||
'name',
|
||||
'foo',
|
||||
'id',
|
||||
);
|
||||
const origEvent = new Blockly.Events.VarTypeChange(
|
||||
varModel,
|
||||
'foo',
|
||||
'bar',
|
||||
);
|
||||
|
||||
const json = origEvent.toJson();
|
||||
const newEvent = new Blockly.Events.fromJson(json, this.workspace);
|
||||
|
||||
assert.deepEqual(newEvent, origEvent);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -192,7 +192,7 @@ suite('Text Input Fields', function () {
|
||||
setup(function () {
|
||||
this.prepField = function (field) {
|
||||
const workspace = {
|
||||
getScale: function () {
|
||||
getAbsoluteScale: function () {
|
||||
return 1;
|
||||
},
|
||||
getRenderer: function () {
|
||||
|
||||
@@ -388,8 +388,7 @@ suite('Variable Fields', function () {
|
||||
fieldVariable.variableTypes = null;
|
||||
|
||||
const resultTypes = fieldVariable.getVariableTypes();
|
||||
// The empty string is always one of the options.
|
||||
assert.deepEqual(resultTypes, ['type1', 'type2', '']);
|
||||
assert.deepEqual(resultTypes, ['type1', 'type2']);
|
||||
});
|
||||
test('variableTypes is the empty list', function () {
|
||||
const fieldVariable = new Blockly.FieldVariable('name1');
|
||||
|
||||
@@ -309,16 +309,12 @@ suite('Flyout', function () {
|
||||
|
||||
function checkFlyoutInfo(flyoutSpy) {
|
||||
const flyoutInfo = flyoutSpy.returnValues[0];
|
||||
const contents = flyoutInfo.contents;
|
||||
const gaps = flyoutInfo.gaps;
|
||||
const contents = flyoutInfo;
|
||||
|
||||
const expectedGaps = [20, 24, 24];
|
||||
assert.deepEqual(gaps, expectedGaps);
|
||||
|
||||
assert.equal(contents.length, 3, 'Contents');
|
||||
assert.equal(contents.length, 6, 'Contents');
|
||||
|
||||
assert.equal(contents[0].type, 'block', 'Contents');
|
||||
const block = contents[0]['block'];
|
||||
const block = contents[0]['element'];
|
||||
assert.instanceOf(block, Blockly.BlockSvg);
|
||||
assert.equal(block.getFieldValue('OP'), 'NEQ');
|
||||
const childA = block.getInputTargetBlock('A');
|
||||
@@ -328,11 +324,20 @@ suite('Flyout', function () {
|
||||
assert.equal(childA.getFieldValue('NUM'), 1);
|
||||
assert.equal(childB.getFieldValue('NUM'), 2);
|
||||
|
||||
assert.equal(contents[1].type, 'button', 'Contents');
|
||||
assert.instanceOf(contents[1]['button'], Blockly.FlyoutButton);
|
||||
assert.equal(contents[1].type, 'sep');
|
||||
assert.equal(contents[1].element.getBoundingRectangle().getHeight(), 20);
|
||||
|
||||
assert.equal(contents[2].type, 'button', 'Contents');
|
||||
assert.instanceOf(contents[2]['button'], Blockly.FlyoutButton);
|
||||
assert.instanceOf(contents[2]['element'], Blockly.FlyoutButton);
|
||||
|
||||
assert.equal(contents[3].type, 'sep');
|
||||
assert.equal(contents[3].element.getBoundingRectangle().getHeight(), 24);
|
||||
|
||||
assert.equal(contents[4].type, 'label', 'Contents');
|
||||
assert.instanceOf(contents[4]['element'], Blockly.FlyoutButton);
|
||||
|
||||
assert.equal(contents[5].type, 'sep');
|
||||
assert.equal(contents[5].element.getBoundingRectangle().getHeight(), 24);
|
||||
}
|
||||
|
||||
suite('Direct show', function () {
|
||||
@@ -621,35 +626,5 @@ suite('Flyout', function () {
|
||||
const block = this.flyout.workspace_.getAllBlocks()[0];
|
||||
assert.equal(block.getFieldValue('NUM'), 321);
|
||||
});
|
||||
|
||||
test('Recycling enabled', function () {
|
||||
this.flyout.blockIsRecyclable_ = function () {
|
||||
return true;
|
||||
};
|
||||
this.flyout.show({
|
||||
'contents': [
|
||||
{
|
||||
'kind': 'BLOCK',
|
||||
'type': 'math_number',
|
||||
'fields': {
|
||||
'NUM': 123,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
this.flyout.show({
|
||||
'contents': [
|
||||
{
|
||||
'kind': 'BLOCK',
|
||||
'type': 'math_number',
|
||||
'fields': {
|
||||
'NUM': 321,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const block = this.flyout.workspace_.getAllBlocks()[0];
|
||||
assert.equal(block.getFieldValue('NUM'), 123);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
import './event_var_create_test.js';
|
||||
import './event_var_delete_test.js';
|
||||
import './event_var_rename_test.js';
|
||||
import './event_var_type_change_test.js';
|
||||
import './event_viewport_test.js';
|
||||
import './extensions_test.js';
|
||||
import './field_checkbox_test.js';
|
||||
@@ -94,7 +95,6 @@
|
||||
import './icon_test.js';
|
||||
import './input_test.js';
|
||||
import './insertion_marker_test.js';
|
||||
import './insertion_marker_manager_test.js';
|
||||
import './jso_deserialization_test.js';
|
||||
import './jso_serialization_test.js';
|
||||
import './json_test.js';
|
||||
|
||||
@@ -1,443 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2022 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {assert} from '../../node_modules/chai/chai.js';
|
||||
import {
|
||||
defineRowBlock,
|
||||
defineRowToStackBlock,
|
||||
defineStackBlock,
|
||||
} from './test_helpers/block_definitions.js';
|
||||
import {
|
||||
sharedTestSetup,
|
||||
sharedTestTeardown,
|
||||
} from './test_helpers/setup_teardown.js';
|
||||
|
||||
suite('Insertion marker manager', function () {
|
||||
setup(function () {
|
||||
sharedTestSetup.call(this);
|
||||
defineRowBlock();
|
||||
defineStackBlock();
|
||||
defineRowToStackBlock();
|
||||
this.workspace = Blockly.inject('blocklyDiv');
|
||||
});
|
||||
teardown(function () {
|
||||
sharedTestTeardown.call(this);
|
||||
});
|
||||
|
||||
suite('Creating markers', function () {
|
||||
function createBlocksAndManager(workspace, state) {
|
||||
Blockly.serialization.workspaces.load(state, workspace);
|
||||
const block = workspace.getBlockById('first');
|
||||
const manager = new Blockly.InsertionMarkerManager(block);
|
||||
return manager;
|
||||
}
|
||||
|
||||
test('One stack block creates one marker', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'stack_block',
|
||||
'id': 'first',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 1);
|
||||
});
|
||||
|
||||
test('Two stack blocks create two markers', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'stack_block',
|
||||
'id': 'first',
|
||||
'next': {
|
||||
'block': {
|
||||
'type': 'stack_block',
|
||||
'id': 'second',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 2);
|
||||
});
|
||||
|
||||
test('Three stack blocks create two markers', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'stack_block',
|
||||
'id': 'first',
|
||||
'next': {
|
||||
'block': {
|
||||
'type': 'stack_block',
|
||||
'id': 'second',
|
||||
'next': {
|
||||
'block': {
|
||||
'type': 'stack_block',
|
||||
'id': 'third',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 2);
|
||||
});
|
||||
|
||||
test('One value block creates one marker', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'row_block',
|
||||
'id': 'first',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 1);
|
||||
});
|
||||
|
||||
test('Two value blocks create one marker', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'row_block',
|
||||
'id': 'first',
|
||||
'inputs': {
|
||||
'INPUT': {
|
||||
'block': {
|
||||
'type': 'row_block',
|
||||
'id': 'second',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 1);
|
||||
});
|
||||
|
||||
test('One row to stack block creates one marker', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'row_to_stack_block',
|
||||
'id': 'first',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 1);
|
||||
});
|
||||
|
||||
test('Row to stack block with child creates two markers', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'row_to_stack_block',
|
||||
'id': 'first',
|
||||
'next': {
|
||||
'block': {
|
||||
'type': 'stack_block',
|
||||
'id': 'second',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 2);
|
||||
});
|
||||
|
||||
suite('children being set as insertion markers', function () {
|
||||
setup(function () {
|
||||
Blockly.Blocks['shadows_in_init'] = {
|
||||
init: function () {
|
||||
this.appendValueInput('test').connection.setShadowState({
|
||||
'type': 'math_number',
|
||||
});
|
||||
this.setPreviousStatement(true);
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['shadows_in_load'] = {
|
||||
init: function () {
|
||||
this.appendValueInput('test');
|
||||
this.setPreviousStatement(true);
|
||||
},
|
||||
|
||||
loadExtraState: function () {
|
||||
this.getInput('test').connection.setShadowState({
|
||||
'type': 'math_number',
|
||||
});
|
||||
},
|
||||
|
||||
saveExtraState: function () {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
delete Blockly.Blocks['shadows_in_init'];
|
||||
delete Blockly.Blocks['shadows_in_load'];
|
||||
});
|
||||
|
||||
test('Shadows added in init are set as insertion markers', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'id': 'first',
|
||||
'type': 'shadows_in_init',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.isTrue(
|
||||
markers[0].getChildren()[0].isInsertionMarker(),
|
||||
'Expected the shadow block to be an insertion maker',
|
||||
);
|
||||
});
|
||||
|
||||
test('Shadows added in `loadExtraState` are set as insertion markers', function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'id': 'first',
|
||||
'type': 'shadows_in_load',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const manager = createBlocksAndManager(this.workspace, state);
|
||||
const markers = manager.getInsertionMarkers();
|
||||
assert.isTrue(
|
||||
markers[0].getChildren()[0].isInsertionMarker(),
|
||||
'Expected the shadow block to be an insertion maker',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Would delete block', function () {
|
||||
setup(function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'stack_block',
|
||||
'id': 'first',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
Blockly.serialization.workspaces.load(state, this.workspace);
|
||||
this.block = this.workspace.getBlockById('first');
|
||||
this.manager = new Blockly.InsertionMarkerManager(this.block);
|
||||
|
||||
const componentManager = this.workspace.getComponentManager();
|
||||
this.stub = sinon.stub(componentManager, 'hasCapability');
|
||||
this.dxy = new Blockly.utils.Coordinate(0, 0);
|
||||
});
|
||||
|
||||
test('Over delete area and accepted would delete', function () {
|
||||
this.stub
|
||||
.withArgs(
|
||||
'fakeDragTarget',
|
||||
Blockly.ComponentManager.Capability.DELETE_AREA,
|
||||
)
|
||||
.returns(true);
|
||||
const fakeDragTarget = {
|
||||
wouldDelete: sinon.fake.returns(true),
|
||||
id: 'fakeDragTarget',
|
||||
};
|
||||
this.manager.update(this.dxy, fakeDragTarget);
|
||||
assert.isTrue(this.manager.wouldDeleteBlock);
|
||||
});
|
||||
|
||||
test('Over delete area and rejected would not delete', function () {
|
||||
this.stub
|
||||
.withArgs(
|
||||
'fakeDragTarget',
|
||||
Blockly.ComponentManager.Capability.DELETE_AREA,
|
||||
)
|
||||
.returns(true);
|
||||
const fakeDragTarget = {
|
||||
wouldDelete: sinon.fake.returns(false),
|
||||
id: 'fakeDragTarget',
|
||||
};
|
||||
this.manager.update(this.dxy, fakeDragTarget);
|
||||
assert.isFalse(this.manager.wouldDeleteBlock);
|
||||
});
|
||||
|
||||
test('Drag target is not a delete area would not delete', function () {
|
||||
this.stub
|
||||
.withArgs(
|
||||
'fakeDragTarget',
|
||||
Blockly.ComponentManager.Capability.DELETE_AREA,
|
||||
)
|
||||
.returns(false);
|
||||
const fakeDragTarget = {
|
||||
wouldDelete: sinon.fake.returns(false),
|
||||
id: 'fakeDragTarget',
|
||||
};
|
||||
this.manager.update(this.dxy, fakeDragTarget);
|
||||
assert.isFalse(this.manager.wouldDeleteBlock);
|
||||
});
|
||||
|
||||
test('Not over drag target would not delete', function () {
|
||||
this.manager.update(this.dxy, null);
|
||||
assert.isFalse(this.manager.wouldDeleteBlock);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Would connect stack blocks', function () {
|
||||
setup(function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'stack_block',
|
||||
'id': 'first',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
},
|
||||
{
|
||||
'type': 'stack_block',
|
||||
'id': 'other',
|
||||
'x': 200,
|
||||
'y': 200,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
Blockly.serialization.workspaces.load(state, this.workspace);
|
||||
this.block = this.workspace.getBlockById('first');
|
||||
this.block.setDragging(true);
|
||||
this.manager = new Blockly.InsertionMarkerManager(this.block);
|
||||
});
|
||||
|
||||
test('No other blocks nearby would not connect', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(0, 0), null);
|
||||
assert.isFalse(this.manager.wouldConnectBlock());
|
||||
});
|
||||
|
||||
test('Near other block and above would connect before', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(200, 190), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
const markers = this.manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 1);
|
||||
const marker = markers[0];
|
||||
assert.isTrue(marker.nextConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Near other block and below would connect after', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(200, 210), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
const markers = this.manager.getInsertionMarkers();
|
||||
assert.equal(markers.length, 1);
|
||||
const marker = markers[0];
|
||||
assert.isTrue(marker.previousConnection.isConnected());
|
||||
});
|
||||
|
||||
test('Near other block and left would connect', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(190, 200), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
});
|
||||
|
||||
test('Near other block and right would connect', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(210, 200), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
});
|
||||
});
|
||||
|
||||
suite('Would connect row blocks', function () {
|
||||
setup(function () {
|
||||
const state = {
|
||||
'blocks': {
|
||||
'blocks': [
|
||||
{
|
||||
'type': 'row_block',
|
||||
'id': 'first',
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
},
|
||||
{
|
||||
'type': 'row_block',
|
||||
'id': 'other',
|
||||
'x': 200,
|
||||
'y': 200,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
Blockly.serialization.workspaces.load(state, this.workspace);
|
||||
this.block = this.workspace.getBlockById('first');
|
||||
this.block.setDragging(true);
|
||||
this.manager = new Blockly.InsertionMarkerManager(this.block);
|
||||
});
|
||||
|
||||
test('No other blocks nearby would not connect', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(0, 0), null);
|
||||
assert.isFalse(this.manager.wouldConnectBlock());
|
||||
});
|
||||
|
||||
test('Near other block and above would connect', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(200, 190), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
});
|
||||
|
||||
test('Near other block and below would connect', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(200, 210), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
});
|
||||
|
||||
test('Near other block and left would connect before', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(190, 200), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
const markers = this.manager.getInsertionMarkers();
|
||||
assert.isTrue(markers[0].getInput('INPUT').connection.isConnected());
|
||||
});
|
||||
|
||||
test('Near other block and right would connect after', function () {
|
||||
this.manager.update(new Blockly.utils.Coordinate(210, 200), null);
|
||||
assert.isTrue(this.manager.wouldConnectBlock());
|
||||
const markers = this.manager.getInsertionMarkers();
|
||||
assert.isTrue(markers[0].outputConnection.isConnected());
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -42,7 +42,7 @@ suite('Key Down', function () {
|
||||
function runReadOnlyTest(keyEvent, opt_name) {
|
||||
const name = opt_name ? opt_name : 'Not called when readOnly is true';
|
||||
test(name, function () {
|
||||
this.workspace.options.readOnly = true;
|
||||
this.workspace.setIsReadOnly(true);
|
||||
this.injectionDiv.dispatchEvent(keyEvent);
|
||||
sinon.assert.notCalled(this.hideChaffSpy);
|
||||
});
|
||||
|
||||
@@ -243,9 +243,8 @@ export function getBasicToolbox() {
|
||||
}
|
||||
|
||||
export function getCollapsibleItem(toolbox) {
|
||||
const contents = toolbox.contents_;
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
const item = contents[i];
|
||||
const contents = toolbox.contents.values();
|
||||
for (const item of contents) {
|
||||
if (item.isCollapsible()) {
|
||||
return item;
|
||||
}
|
||||
@@ -253,9 +252,8 @@ export function getCollapsibleItem(toolbox) {
|
||||
}
|
||||
|
||||
export function getNonCollapsibleItem(toolbox) {
|
||||
const contents = toolbox.contents_;
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
const item = contents[i];
|
||||
const contents = toolbox.contents.values();
|
||||
for (const item of contents) {
|
||||
if (!item.isCollapsible()) {
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ suite('Toolbox', function () {
|
||||
test('Init called -> HtmlDiv is inserted before parent node', function () {
|
||||
const toolboxDiv = Blockly.common.getMainWorkspace().getInjectionDiv()
|
||||
.childNodes[0];
|
||||
assert.equal(toolboxDiv.className, 'blocklyToolboxDiv');
|
||||
assert.equal(toolboxDiv.className, 'blocklyToolbox');
|
||||
});
|
||||
test('Init called -> Toolbox is subscribed to background and foreground colour', function () {
|
||||
const themeManager = this.toolbox.workspace_.getThemeManager();
|
||||
@@ -98,7 +98,7 @@ suite('Toolbox', function () {
|
||||
{'kind': 'category', 'contents': []},
|
||||
],
|
||||
});
|
||||
assert.lengthOf(this.toolbox.contents_, 2);
|
||||
assert.equal(this.toolbox.contents.size, 2);
|
||||
sinon.assert.called(positionStub);
|
||||
});
|
||||
// TODO: Uncomment once implemented.
|
||||
@@ -153,7 +153,7 @@ suite('Toolbox', function () {
|
||||
],
|
||||
};
|
||||
this.toolbox.render(jsonDef);
|
||||
assert.lengthOf(this.toolbox.contents_, 1);
|
||||
assert.equal(this.toolbox.contents.size, 1);
|
||||
});
|
||||
test('multiple icon classes can be applied', function () {
|
||||
const jsonDef = {
|
||||
@@ -176,7 +176,7 @@ suite('Toolbox', function () {
|
||||
assert.doesNotThrow(() => {
|
||||
this.toolbox.render(jsonDef);
|
||||
});
|
||||
assert.lengthOf(this.toolbox.contents_, 1);
|
||||
assert.equal(this.toolbox.contents.size, 1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -198,11 +198,13 @@ suite('Toolbox', function () {
|
||||
sinon.assert.calledOnce(hideChaffStub);
|
||||
});
|
||||
test('Category clicked -> Should select category', function () {
|
||||
const categoryXml = document.getElementsByClassName('blocklyTreeRow')[0];
|
||||
const categoryXml = document.getElementsByClassName(
|
||||
'blocklyToolboxCategory',
|
||||
)[0];
|
||||
const evt = {
|
||||
'target': categoryXml,
|
||||
};
|
||||
const item = this.toolbox.contentMap_[categoryXml.getAttribute('id')];
|
||||
const item = this.toolbox.contents.get(categoryXml.getAttribute('id'));
|
||||
const setSelectedSpy = sinon.spy(this.toolbox, 'setSelectedItem');
|
||||
const onClickSpy = sinon.spy(item, 'onClick');
|
||||
this.toolbox.onClick_(evt);
|
||||
@@ -354,14 +356,16 @@ suite('Toolbox', function () {
|
||||
assert.isFalse(handled);
|
||||
});
|
||||
test('Next item is selectable -> Should select next item', function () {
|
||||
const item = this.toolbox.contents_[0];
|
||||
const items = [...this.toolbox.contents.values()];
|
||||
const item = items[0];
|
||||
this.toolbox.selectedItem_ = item;
|
||||
const handled = this.toolbox.selectNext();
|
||||
assert.isTrue(handled);
|
||||
assert.equal(this.toolbox.selectedItem_, this.toolbox.contents_[1]);
|
||||
assert.equal(this.toolbox.selectedItem_, items[1]);
|
||||
});
|
||||
test('Selected item is last item -> Should not handle event', function () {
|
||||
const item = this.toolbox.contents_[this.toolbox.contents_.length - 1];
|
||||
const items = [...this.toolbox.contents.values()];
|
||||
const item = items.at(-1);
|
||||
this.toolbox.selectedItem_ = item;
|
||||
const handled = this.toolbox.selectNext();
|
||||
assert.isFalse(handled);
|
||||
@@ -385,15 +389,16 @@ suite('Toolbox', function () {
|
||||
assert.isFalse(handled);
|
||||
});
|
||||
test('Selected item is first item -> Should not handle event', function () {
|
||||
const item = this.toolbox.contents_[0];
|
||||
const item = [...this.toolbox.contents.values()][0];
|
||||
this.toolbox.selectedItem_ = item;
|
||||
const handled = this.toolbox.selectPrevious();
|
||||
assert.isFalse(handled);
|
||||
assert.equal(this.toolbox.selectedItem_, item);
|
||||
});
|
||||
test('Previous item is selectable -> Should select previous item', function () {
|
||||
const item = this.toolbox.contents_[1];
|
||||
const prevItem = this.toolbox.contents_[0];
|
||||
const items = [...this.toolbox.contents.values()];
|
||||
const item = items[1];
|
||||
const prevItem = items[0];
|
||||
this.toolbox.selectedItem_ = item;
|
||||
const handled = this.toolbox.selectPrevious();
|
||||
assert.isTrue(handled);
|
||||
@@ -402,9 +407,10 @@ suite('Toolbox', function () {
|
||||
test('Previous item is collapsed -> Should skip over children of the previous item', function () {
|
||||
const childItem = getChildItem(this.toolbox);
|
||||
const parentItem = childItem.getParent();
|
||||
const parentIdx = this.toolbox.contents_.indexOf(parentItem);
|
||||
const items = [...this.toolbox.contents.values()];
|
||||
const parentIdx = items.indexOf(parentItem);
|
||||
// Gets the item after the parent.
|
||||
const item = this.toolbox.contents_[parentIdx + 1];
|
||||
const item = items[parentIdx + 1];
|
||||
this.toolbox.selectedItem_ = item;
|
||||
const handled = this.toolbox.selectPrevious();
|
||||
assert.isTrue(handled);
|
||||
@@ -726,9 +732,10 @@ suite('Toolbox', function () {
|
||||
});
|
||||
test('Child categories visible if all ancestors expanded', function () {
|
||||
this.toolbox.render(getDeeplyNestedJSON());
|
||||
const outerCategory = this.toolbox.contents_[0];
|
||||
const middleCategory = this.toolbox.contents_[1];
|
||||
const innerCategory = this.toolbox.contents_[2];
|
||||
const items = [...this.toolbox.contents.values()];
|
||||
const outerCategory = items[0];
|
||||
const middleCategory = items[1];
|
||||
const innerCategory = items[2];
|
||||
|
||||
outerCategory.toggleExpanded();
|
||||
middleCategory.toggleExpanded();
|
||||
@@ -741,8 +748,9 @@ suite('Toolbox', function () {
|
||||
});
|
||||
test('Child categories not visible if any ancestor not expanded', function () {
|
||||
this.toolbox.render(getDeeplyNestedJSON());
|
||||
const middleCategory = this.toolbox.contents_[1];
|
||||
const innerCategory = this.toolbox.contents_[2];
|
||||
const items = [...this.toolbox.contents.values()];
|
||||
const middleCategory = items[1];
|
||||
const innerCategory = items[2];
|
||||
|
||||
// Don't expand the outermost category
|
||||
// Even though the direct parent of inner is expanded, it shouldn't be visible
|
||||
|
||||
@@ -21,7 +21,7 @@ suite('Variable Map', function () {
|
||||
setup(function () {
|
||||
sharedTestSetup.call(this);
|
||||
this.workspace = new Blockly.Workspace();
|
||||
this.variableMap = new Blockly.VariableMap(this.workspace);
|
||||
this.variableMap = this.workspace.getVariableMap();
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
@@ -39,17 +39,17 @@ suite('Variable Map', function () {
|
||||
this.variableMap.createVariable('name1', 'type1', 'id1');
|
||||
|
||||
// Assert there is only one variable in the this.variableMap.
|
||||
let keys = Array.from(this.variableMap.variableMap.keys());
|
||||
let keys = this.variableMap.getTypes();
|
||||
assert.equal(keys.length, 1);
|
||||
let varMapLength = this.variableMap.variableMap.get(keys[0]).length;
|
||||
let varMapLength = this.variableMap.getVariablesOfType(keys[0]).length;
|
||||
assert.equal(varMapLength, 1);
|
||||
|
||||
this.variableMap.createVariable('name1', 'type1');
|
||||
assertVariableValues(this.variableMap, 'name1', 'type1', 'id1');
|
||||
// Check that the size of the variableMap did not change.
|
||||
keys = Array.from(this.variableMap.variableMap.keys());
|
||||
keys = this.variableMap.getTypes();
|
||||
assert.equal(keys.length, 1);
|
||||
varMapLength = this.variableMap.variableMap.get(keys[0]).length;
|
||||
varMapLength = this.variableMap.getVariablesOfType(keys[0]).length;
|
||||
assert.equal(varMapLength, 1);
|
||||
});
|
||||
|
||||
@@ -59,16 +59,16 @@ suite('Variable Map', function () {
|
||||
this.variableMap.createVariable('name1', 'type1', 'id1');
|
||||
|
||||
// Assert there is only one variable in the this.variableMap.
|
||||
let keys = Array.from(this.variableMap.variableMap.keys());
|
||||
let keys = this.variableMap.getTypes();
|
||||
assert.equal(keys.length, 1);
|
||||
const varMapLength = this.variableMap.variableMap.get(keys[0]).length;
|
||||
const varMapLength = this.variableMap.getVariablesOfType(keys[0]).length;
|
||||
assert.equal(varMapLength, 1);
|
||||
|
||||
this.variableMap.createVariable('name1', 'type2', 'id2');
|
||||
assertVariableValues(this.variableMap, 'name1', 'type1', 'id1');
|
||||
assertVariableValues(this.variableMap, 'name1', 'type2', 'id2');
|
||||
// Check that the size of the variableMap did change.
|
||||
keys = Array.from(this.variableMap.variableMap.keys());
|
||||
keys = this.variableMap.getTypes();
|
||||
assert.equal(keys.length, 2);
|
||||
});
|
||||
|
||||
@@ -187,24 +187,6 @@ suite('Variable Map', function () {
|
||||
});
|
||||
});
|
||||
|
||||
suite('getVariableTypes', function () {
|
||||
test('Trivial', function () {
|
||||
this.variableMap.createVariable('name1', 'type1', 'id1');
|
||||
this.variableMap.createVariable('name2', 'type1', 'id2');
|
||||
this.variableMap.createVariable('name3', 'type2', 'id3');
|
||||
this.variableMap.createVariable('name4', 'type3', 'id4');
|
||||
const resultArray = this.variableMap.getVariableTypes();
|
||||
// The empty string is always an option.
|
||||
assert.deepEqual(resultArray, ['type1', 'type2', 'type3', '']);
|
||||
});
|
||||
|
||||
test('None', function () {
|
||||
// The empty string is always an option.
|
||||
const resultArray = this.variableMap.getVariableTypes();
|
||||
assert.deepEqual(resultArray, ['']);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getVariablesOfType', function () {
|
||||
test('Trivial', function () {
|
||||
const var1 = this.variableMap.createVariable('name1', 'type1', 'id1');
|
||||
@@ -246,6 +228,65 @@ suite('Variable Map', function () {
|
||||
});
|
||||
});
|
||||
|
||||
suite(
|
||||
'Using changeVariableType to change the type of a variable',
|
||||
function () {
|
||||
test('updates it to a new non-empty value', function () {
|
||||
const variable = this.variableMap.createVariable(
|
||||
'name1',
|
||||
'type1',
|
||||
'id1',
|
||||
);
|
||||
this.variableMap.changeVariableType(variable, 'type2');
|
||||
const oldTypeVariables = this.variableMap.getVariablesOfType('type1');
|
||||
const newTypeVariables = this.variableMap.getVariablesOfType('type2');
|
||||
assert.deepEqual(oldTypeVariables, []);
|
||||
assert.deepEqual(newTypeVariables, [variable]);
|
||||
assert.equal(variable.getType(), 'type2');
|
||||
});
|
||||
|
||||
test('updates it to a new empty value', function () {
|
||||
const variable = this.variableMap.createVariable(
|
||||
'name1',
|
||||
'type1',
|
||||
'id1',
|
||||
);
|
||||
this.variableMap.changeVariableType(variable, '');
|
||||
const oldTypeVariables = this.variableMap.getVariablesOfType('type1');
|
||||
const newTypeVariables = this.variableMap.getVariablesOfType('');
|
||||
assert.deepEqual(oldTypeVariables, []);
|
||||
assert.deepEqual(newTypeVariables, [variable]);
|
||||
assert.equal(variable.getType(), '');
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
suite('addVariable', function () {
|
||||
test('normally', function () {
|
||||
const variable = new Blockly.VariableModel(this.workspace, 'foo', 'int');
|
||||
assert.isNull(this.variableMap.getVariableById(variable.getId()));
|
||||
this.variableMap.addVariable(variable);
|
||||
assert.equal(
|
||||
this.variableMap.getVariableById(variable.getId()),
|
||||
variable,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getTypes', function () {
|
||||
test('when map is empty', function () {
|
||||
const types = this.variableMap.getTypes();
|
||||
assert.deepEqual(types, []);
|
||||
});
|
||||
|
||||
test('with various types', function () {
|
||||
this.variableMap.createVariable('name1', 'type1', 'id1');
|
||||
this.variableMap.createVariable('name2', '', 'id2');
|
||||
const types = this.variableMap.getTypes();
|
||||
assert.deepEqual(types, ['type1', '']);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAllVariables', function () {
|
||||
test('Trivial', function () {
|
||||
const var1 = this.variableMap.createVariable('name1', 'type1', 'id1');
|
||||
|
||||
@@ -27,8 +27,8 @@ suite('Variable Model', function () {
|
||||
'test_type',
|
||||
'test_id',
|
||||
);
|
||||
assert.equal(variable.name, 'test');
|
||||
assert.equal(variable.type, 'test_type');
|
||||
assert.equal(variable.getName(), 'test');
|
||||
assert.equal(variable.getType(), 'test_type');
|
||||
assert.equal(variable.getId(), 'test_id');
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ suite('Variable Model', function () {
|
||||
null,
|
||||
'test_id',
|
||||
);
|
||||
assert.equal(variable.type, '');
|
||||
assert.equal(variable.getType(), '');
|
||||
});
|
||||
|
||||
test('Undefined type', function () {
|
||||
@@ -49,7 +49,7 @@ suite('Variable Model', function () {
|
||||
undefined,
|
||||
'test_id',
|
||||
);
|
||||
assert.equal(variable.type, '');
|
||||
assert.equal(variable.getType(), '');
|
||||
});
|
||||
|
||||
test('Null id', function () {
|
||||
@@ -59,8 +59,8 @@ suite('Variable Model', function () {
|
||||
'test_type',
|
||||
null,
|
||||
);
|
||||
assert.equal(variable.name, 'test');
|
||||
assert.equal(variable.type, 'test_type');
|
||||
assert.equal(variable.getName(), 'test');
|
||||
assert.equal(variable.getType(), 'test_type');
|
||||
assert.exists(variable.getId());
|
||||
});
|
||||
|
||||
@@ -71,15 +71,15 @@ suite('Variable Model', function () {
|
||||
'test_type',
|
||||
undefined,
|
||||
);
|
||||
assert.equal(variable.name, 'test');
|
||||
assert.equal(variable.type, 'test_type');
|
||||
assert.equal(variable.getName(), 'test');
|
||||
assert.equal(variable.getType(), 'test_type');
|
||||
assert.exists(variable.getId());
|
||||
});
|
||||
|
||||
test('Only name provided', function () {
|
||||
const variable = new Blockly.VariableModel(this.workspace, 'test');
|
||||
assert.equal(variable.name, 'test');
|
||||
assert.equal(variable.type, '');
|
||||
assert.equal(variable.getName(), 'test');
|
||||
assert.equal(variable.getType(), '');
|
||||
assert.exists(variable.getId());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -531,28 +531,6 @@ suite('XML', function () {
|
||||
teardown(function () {
|
||||
workspaceTeardown.call(this, this.workspace);
|
||||
});
|
||||
suite('Dynamic Category Blocks', function () {
|
||||
test('Untyped Variables', function () {
|
||||
this.workspace.createVariable('name1', '', 'id1');
|
||||
const blocksArray = Blockly.Variables.flyoutCategoryBlocks(
|
||||
this.workspace,
|
||||
);
|
||||
for (let i = 0, xml; (xml = blocksArray[i]); i++) {
|
||||
Blockly.Xml.domToBlock(xml, this.workspace);
|
||||
}
|
||||
});
|
||||
test('Typed Variables', function () {
|
||||
this.workspace.createVariable('name1', 'String', 'id1');
|
||||
this.workspace.createVariable('name2', 'Number', 'id2');
|
||||
this.workspace.createVariable('name3', 'Colour', 'id3');
|
||||
const blocksArray = Blockly.VariablesDynamic.flyoutCategoryBlocks(
|
||||
this.workspace,
|
||||
);
|
||||
for (let i = 0, xml; (xml = blocksArray[i]); i++) {
|
||||
Blockly.Xml.domToBlock(xml, this.workspace);
|
||||
}
|
||||
});
|
||||
});
|
||||
suite('Comments', function () {
|
||||
suite('Headless', function () {
|
||||
test('Text', function () {
|
||||
@@ -910,36 +888,4 @@ suite('XML', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('generateVariableFieldDom', function () {
|
||||
test('Case Sensitive', function () {
|
||||
const varId = 'testId';
|
||||
const type = 'testType';
|
||||
const name = 'testName';
|
||||
|
||||
const mockVariableModel = {
|
||||
type: type,
|
||||
name: name,
|
||||
getId: function () {
|
||||
return varId;
|
||||
},
|
||||
};
|
||||
|
||||
const generatedXml = Blockly.Xml.domToText(
|
||||
Blockly.Variables.generateVariableFieldDom(mockVariableModel),
|
||||
);
|
||||
const expectedXml =
|
||||
'<field xmlns="https://developers.google.com/blockly/xml"' +
|
||||
' name="VAR"' +
|
||||
' id="' +
|
||||
varId +
|
||||
'"' +
|
||||
' variabletype="' +
|
||||
type +
|
||||
'"' +
|
||||
'>' +
|
||||
name +
|
||||
'</field>';
|
||||
assert.equal(generatedXml, expectedXml);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user