Files
blockly/tests/mocha/flyout_test.js
Rachel Fenichel 48bdeb3bdb chore: remove underscores from private properties and methods for flyout (#6960)
* chore: remove underscores in flyout files

* chore: remove underscores in flyout_button
2023-04-07 15:40:56 -07:00

588 lines
19 KiB
JavaScript

/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
goog.declareModuleId('Blockly.test.flyout');
import {sharedTestSetup, sharedTestTeardown, workspaceTeardown} from './test_helpers/setup_teardown.js';
import {defineStackBlock} from './test_helpers/block_definitions.js';
import {getBasicToolbox, getChildItem, getCollapsibleItem, getDeeplyNestedJSON, getInjectedToolbox, getNonCollapsibleItem, getProperSimpleJson, getSeparator, getSimpleJson, getXmlArray} from './test_helpers/toolbox_definitions.js';
suite('Flyout', function() {
setup(function() {
sharedTestSetup.call(this);
Blockly.defineBlocksWithJsonArray([{
"type": "basic_block",
"message0": "%1",
"args0": [
{
"type": "field_input",
"name": "TEXT",
"text": "default",
},
],
}]);
this.toolboxXml = document.getElementById('toolbox-simple');
this.workspace = Blockly.inject('blocklyDiv',
{
toolbox: this.toolboxXml,
});
});
teardown(function() {
sharedTestTeardown.call(this);
});
suite('position', function() {
suite('vertical flyout', function() {
suite('simple flyout', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
});
test('y is always 0', function() {
chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout should be 0');
});
test('x is right of workspace if flyout at right', function() {
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
width: 100,
});
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.RIGHT;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT;
chai.assert.equal(this.flyout.getX(), 100, 'x should be right of workspace');
});
test('x is 0 if flyout at left', function() {
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.LEFT;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT;
chai.assert.equal(this.flyout.getX(), 0, 'x should be 0 if the flyout is on the left');
});
});
suite('toolbox flyout', function() {
setup(function() {
const toolbox = document.getElementById('toolbox-categories');
this.workspace = Blockly.inject('blocklyDiv',
{
toolbox: toolbox,
});
this.flyout = this.workspace.getToolbox().getFlyout();
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
});
teardown(function() {
workspaceTeardown.call(this, this.workspace);
});
test('x is aligned with toolbox at left', function() {
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
width: 20,
});
this.flyout.setVisible(true);
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.LEFT;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT;
chai.assert.equal(this.flyout.getX(), 20, 'x should be aligned with toolbox');
});
test('x is aligned with toolbox at right', function() {
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
width: 20,
});
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
width: 100,
});
this.flyout.width_ = 10;
this.flyout.setVisible(true);
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.RIGHT;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT;
chai.assert.equal(this.flyout.getX(), 90, 'x + width should be aligned with toolbox');
});
});
// These tests simulate a trashcan flyout, i.e. the flyout under test is on the
// opposite side of the workspace toolbox setting.
suite('trashcan flyout', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
});
test('x is 0 if trashcan on left', function() {
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
viewWidth: 100,
});
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.RIGHT;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT;
chai.assert.equal(this.flyout.getX(), 0, 'x should be aligned with left edge');
});
test('trashcan on right covers right edge of workspace', function() {
this.flyout.width_ = 20;
sinon.stub(this.targetMetricsManager, 'getAbsoluteMetrics').returns({
left: 10,
});
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
width: 100,
});
this.flyout.setVisible(true);
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.LEFT;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT;
chai.assert.equal(this.flyout.getX(), 90, 'x + width should be aligned with right edge');
});
});
});
suite('horizontal flyout', function() {
setup(function() {
this.workspace = Blockly.inject('blocklyDiv',
{
toolbox: this.toolboxXml,
horizontalLayout: true,
});
});
teardown(function() {
workspaceTeardown.call(this, this.workspace);
});
suite('simple flyout', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
});
test('x is always 0', function() {
chai.assert.equal(this.flyout.getX(), 0, 'x coordinate in horizontal flyout should be 0');
});
test('y is 0 if flyout at top', function() {
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.TOP;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP;
chai.assert.equal(this.flyout.getY(), 0, 'y should be 0 if flyout is at the top');
});
test('y is below workspace if flyout at bottom', function() {
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.BOTTOM;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM;
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
height: 50,
});
chai.assert.equal(this.flyout.getY(), 50, 'y should be below the workspace');
});
});
suite('toolbox flyout', function() {
setup(function() {
const toolbox = document.getElementById('toolbox-categories');
this.workspace = Blockly.inject('blocklyDiv',
{
toolbox: toolbox,
horizontalLayout: true,
});
this.flyout = this.workspace.getToolbox().getFlyout();
this.targetMetricsManager =
this.flyout.targetWorkspace.getMetricsManager();
});
teardown(function() {
workspaceTeardown.call(this, this.workspace);
});
test('y is aligned with toolbox at top', function() {
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
height: 20,
});
this.flyout.setVisible(true);
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.TOP;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP;
chai.assert.equal(this.flyout.getY(), 20, 'y should be aligned with toolbox');
});
test('y is aligned with toolbox at bottom', function() {
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
height: 20,
});
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
height: 100,
});
this.flyout.height_ = 30;
this.flyout.setVisible(true);
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.BOTTOM;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM;
chai.assert.equal(this.flyout.getY(), 70, 'y + height should be aligned with toolbox');
});
});
// These tests simulate a trashcan flyout, i.e. the flyout under test is on the
// opposite side of the workspace toolbox setting.
suite('trashcan flyout', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
this.targetMetricsManager =
this.flyout.targetWorkspace.getMetricsManager();
});
test('y is 0 if trashcan at top', function() {
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.BOTTOM;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP;
chai.assert.equal(this.flyout.getY(), 0, 'y should be aligned with top');
});
test('trashcan on bottom covers bottom of workspace', function() {
this.flyout.targetWorkspace.toolboxPosition =
Blockly.utils.toolbox.Position.TOP;
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM;
sinon.stub(this.targetMetricsManager, 'getAbsoluteMetrics').returns({
top: 10,
});
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
height: 50,
});
this.flyout.setVisible(true);
this.flyout.height_ = 20;
chai.assert.equal(this.flyout.getY(), 40, 'y + height should be aligned with bottom');
});
});
});
});
suite('createFlyoutInfo', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
this.createFlyoutSpy = sinon.spy(this.flyout, 'createFlyoutInfo');
});
function checkFlyoutInfo(flyoutSpy) {
const flyoutInfo = flyoutSpy.returnValues[0];
const contents = flyoutInfo.contents;
const gaps = flyoutInfo.gaps;
const expectedGaps = [20, 24, 24];
chai.assert.deepEqual(gaps, expectedGaps);
chai.assert.equal(contents.length, 3, 'Contents');
chai.assert.equal(contents[0].type, 'block', 'Contents');
const block = contents[0]['block'];
chai.assert.instanceOf(block, Blockly.BlockSvg);
chai.assert.equal(block.getFieldValue('OP'), 'NEQ');
const childA = block.getInputTargetBlock('A');
const childB = block.getInputTargetBlock('B');
chai.assert.isTrue(childA.isShadow());
chai.assert.isFalse(childB.isShadow());
chai.assert.equal(childA.getFieldValue('NUM'), 1);
chai.assert.equal(childB.getFieldValue('NUM'), 2);
chai.assert.equal(contents[1].type, 'button', 'Contents');
chai.assert.instanceOf(contents[1]['button'], Blockly.FlyoutButton);
chai.assert.equal(contents[2].type, 'button', 'Contents');
chai.assert.instanceOf(contents[2]['button'], Blockly.FlyoutButton);
}
suite('Direct show', function() {
test('Node', function() {
this.flyout.show(this.toolboxXml);
checkFlyoutInfo(this.createFlyoutSpy);
});
test('NodeList', function() {
const nodeList = document.getElementById('toolbox-simple').childNodes;
this.flyout.show(nodeList);
checkFlyoutInfo(this.createFlyoutSpy);
});
test('Array of JSON', function() {
this.flyout.show(getSimpleJson());
checkFlyoutInfo(this.createFlyoutSpy);
});
test('Array of Proper JSON', function() {
this.flyout.show(getProperSimpleJson());
checkFlyoutInfo(this.createFlyoutSpy);
});
test('Array of XML', function() {
this.flyout.show(getXmlArray());
checkFlyoutInfo(this.createFlyoutSpy);
});
});
suite('Dynamic category', function() {
setup(function() {
this.stubAndAssert = function(val) {
sinon.stub(
this.flyout.workspace_.targetWorkspace,
'getToolboxCategoryCallback')
.returns(function() {return val;});
this.flyout.show('someString');
checkFlyoutInfo(this.createFlyoutSpy);
};
});
test('No category available', function() {
chai.assert.throws(
function() {
this.flyout.show('someString');
}.bind(this),
'Couldn\'t find a callback function when opening ' +
'a toolbox category.');
});
test('Node', function() {
this.stubAndAssert(this.toolboxXml);
});
test('NodeList', function() {
this.stubAndAssert(
document.getElementById('toolbox-simple').childNodes);
});
test('Array of JSON', function() {
this.stubAndAssert(getSimpleJson());
});
test('Array of Proper JSON', function() {
this.stubAndAssert(getProperSimpleJson());
});
test('Array of XML', function() {
this.stubAndAssert(getXmlArray());
});
});
});
suite('Creating blocks', function() {
suite('Enabled/Disabled', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
this.assertDisabled = function(disabled) {
const block = this.flyout.getWorkspace().getTopBlocks(false)[0];
chai.assert.equal(!block.isEnabled(), disabled);
};
});
suite('XML', function() {
test('True string', function() {
const xml = Blockly.utils.xml.textToDom(
'<xml>' +
'<block type="text_print" disabled="true"></block>' +
'</xml>'
);
this.flyout.show(xml);
this.assertDisabled(true);
});
test('False string', function() {
const xml = Blockly.utils.xml.textToDom(
'<xml>' +
'<block type="text_print" disabled="false"></block>' +
'</xml>'
);
this.flyout.show(xml);
this.assertDisabled(false);
});
test('Disabled string', function() {
// The XML system supports this for some reason!?
const xml = Blockly.utils.xml.textToDom(
'<xml>' +
'<block type="text_print" disabled="disabled"></block>' +
'</xml>'
);
this.flyout.show(xml);
this.assertDisabled(true);
});
test('Different string', function() {
const xml = Blockly.utils.xml.textToDom(
'<xml>' +
'<block type="text_print" disabled="random"></block>' +
'</xml>'
);
this.flyout.show(xml);
this.assertDisabled(false);
});
});
suite('JSON', function() {
test('All undefined', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
test('Enabled true', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'enabled': true,
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
test('Enabled false', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'enabled': false,
},
];
this.flyout.show(json);
this.assertDisabled(true);
});
test('Disabled true string', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': 'true',
},
];
this.flyout.show(json);
this.assertDisabled(true);
});
test('Disabled false string', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': 'false',
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
test('Disabled string', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': 'disabled', // This is not respected by the JSON!
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
test('Disabled true value', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': true,
},
];
this.flyout.show(json);
this.assertDisabled(true);
});
test('Disabled false value', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': false,
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
test('Disabled different string', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': 'random',
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
test('Disabled empty string', function() {
const json = [
{
'kind': 'block',
'type': 'text_print',
'disabled': '',
},
];
this.flyout.show(json);
this.assertDisabled(false);
});
});
});
});
suite('Recycling', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
});
test('Recycling disabled', function() {
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];
chai.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];
chai.assert.equal(block.getFieldValue('NUM'), 123);
});
});
});