Merge branch 'rc/v12.0.0' into develop-v12-merge

This commit is contained in:
Aaron Dodson
2025-03-11 09:42:25 -07:00
committed by GitHub
148 changed files with 3869 additions and 3295 deletions

View File

@@ -1421,6 +1421,10 @@ suite('Blocks', function () {
return Blockly.utils.Size(0, 0);
}
setBubbleLocation() {}
getBubbleLocation() {}
bubbleIsVisible() {
return true;
}

View File

@@ -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'),
);

View File

@@ -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);
});
});
});

View File

@@ -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);

View 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);
});
});
});

View File

@@ -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 () {

View File

@@ -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');

View File

@@ -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);
});
});
});

View File

@@ -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';

View File

@@ -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());
});
});
});

View File

@@ -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);
});

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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');

View File

@@ -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());
});
});

View File

@@ -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);
});
});
});