mirror of
https://github.com/google/blockly.git
synced 2026-01-10 02:17:09 +01:00
Converting procedure svg tests to mocha. (#3867)
* Converting procedure svg tests to mocha. * Removing unused function. * cleanup
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"defineRowBlock": true,
|
||||
"defineStackBlock": true,
|
||||
"defineStatementBlock": true,
|
||||
"createEventsFireStub": true,
|
||||
"testAWorkspace": true
|
||||
},
|
||||
"extends": "../../.eslintrc.json"
|
||||
|
||||
@@ -555,22 +555,11 @@ suite('Events', function() {
|
||||
});
|
||||
|
||||
suite('Firing', function() {
|
||||
function temporary_fireEvent(event) {
|
||||
if (!Blockly.Events.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
Blockly.Events.FIRE_QUEUE_.push(event);
|
||||
Blockly.Events.fireNow_();
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
this.savedFireFunc_ = Blockly.Events.fire;
|
||||
Blockly.Events.fire = temporary_fireEvent;
|
||||
temporary_fireEvent.firedEvents_ = [];
|
||||
createEventsFireStub();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Blockly.Events.fire = this.savedFireFunc_;
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
@@ -578,7 +567,7 @@ suite('Events', function() {
|
||||
try {
|
||||
var toolbox = document.getElementById('toolbox-categories');
|
||||
var workspaceSvg = Blockly.inject('blocklyDiv', {toolbox: toolbox});
|
||||
temporary_fireEvent.firedEvents_ = [];
|
||||
Blockly.Events.fire.firedEvents_ = [];
|
||||
|
||||
var block = workspaceSvg.newBlock('');
|
||||
block.initSvg();
|
||||
|
||||
@@ -295,6 +295,244 @@ suite('Procedures', function() {
|
||||
}, 'name');
|
||||
});
|
||||
});
|
||||
suite('Enable/Disable', function() {
|
||||
setup(function() {
|
||||
createEventsFireStub();
|
||||
var toolbox = document.getElementById('toolbox-categories');
|
||||
this.workspaceSvg = Blockly.inject('blocklyDiv', {toolbox: toolbox});
|
||||
});
|
||||
teardown(function() {
|
||||
this.workspaceSvg.dispose();
|
||||
sinon.restore();
|
||||
});
|
||||
suite('Inherited disabled', function() {
|
||||
setup(function() {
|
||||
var dom = Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'<statement name="STACK">' +
|
||||
'<block type="procedures_callnoreturn" id="foo-c1">' +
|
||||
'<mutation name="foo"></mutation>' +
|
||||
'</block>' +
|
||||
'</statement>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_defnoreturn" id="foo-def">' +
|
||||
'<field name="NAME">foo</field>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_defreturn" id="baz-def">' +
|
||||
'<field name="NAME">baz</field>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="foo-c2">' +
|
||||
'<mutation name="foo"></mutation>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callreturn" id="baz-c1">' +
|
||||
'<mutation name="baz"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>');
|
||||
Blockly.Events.disable();
|
||||
Blockly.Xml.appendDomToWorkspace(dom, this.workspaceSvg);
|
||||
Blockly.Events.enable();
|
||||
|
||||
this.barDef = this.workspaceSvg.getBlockById('bar-def');
|
||||
this.fooDef = this.workspaceSvg.getBlockById('foo-def');
|
||||
this.bazDef = this.workspaceSvg.getBlockById('baz-def');
|
||||
|
||||
this.barCalls = [
|
||||
this.workspaceSvg.getBlockById('bar-c1'),
|
||||
this.workspaceSvg.getBlockById('bar-c2')];
|
||||
this.fooCalls = [
|
||||
this.workspaceSvg.getBlockById('foo-c1'),
|
||||
this.workspaceSvg.getBlockById('foo-c2')];
|
||||
this.bazCall = this.workspaceSvg.getBlockById('baz-c1');
|
||||
});
|
||||
test('Nested caller', function() {
|
||||
this.barDef.setEnabled(false);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isFalse(this.barCalls[i].isEnabled(),
|
||||
'Callers are disabled when their definition is disabled ' +
|
||||
'(bar call ' + i + ')');
|
||||
}
|
||||
chai.assert.isTrue(this.fooCalls[0].isEnabled(),
|
||||
'Callers in definitions are disabled by inheritance');
|
||||
chai.assert.isTrue(this.fooCalls[0].getInheritedDisabled(),
|
||||
'Callers in definitions are disabled by inheritance');
|
||||
|
||||
this.fooDef.setEnabled(false);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isFalse(this.fooCalls[i].isEnabled(),
|
||||
'Callers are disabled when their definition is disabled ' +
|
||||
'(foo call ' + i + ')');
|
||||
}
|
||||
|
||||
this.barDef.setEnabled(true);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isTrue(this.barCalls[i].isEnabled(),
|
||||
'Callers are reenabled with their definition ' +
|
||||
'(bar call ' + i + ')');
|
||||
}
|
||||
chai.assert.isFalse(this.fooCalls[0].isEnabled(),
|
||||
'Nested disabled callers remain disabled');
|
||||
chai.assert.isFalse(this.fooCalls[0].getInheritedDisabled(),
|
||||
'Nested disabled callers remain disabled, not by inheritance');
|
||||
});
|
||||
test('Caller in return', function() {
|
||||
this.bazDef.setEnabled(false);
|
||||
|
||||
chai.assert.isFalse(this.bazCall.isEnabled(),
|
||||
'Caller is disabled with its definition');
|
||||
|
||||
chai.assert.isTrue(this.barCalls[1].isEnabled(),
|
||||
'Caller in the return is disabled by inheritance');
|
||||
chai.assert.isTrue(this.barCalls[1].getInheritedDisabled(),
|
||||
'Caller in the return is disabled by inheritance');
|
||||
|
||||
this.barDef.setEnabled(false);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isFalse(this.barCalls[i].isEnabled(),
|
||||
'Callers are disabled when their definition is disabled ' +
|
||||
'(bar call ' + i + ')');
|
||||
}
|
||||
|
||||
this.bazDef.setEnabled(true);
|
||||
|
||||
chai.assert.isFalse(this.barCalls[1].isEnabled(),
|
||||
'Caller in return remains disabled');
|
||||
chai.assert.isFalse(this.barCalls[1].getInheritedDisabled(),
|
||||
'Caller in return remains disabled, not by inheritance');
|
||||
});
|
||||
});
|
||||
var testCases = [
|
||||
['procedures_defnoreturn',
|
||||
('<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defnoreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>')],
|
||||
['procedures_defreturn',
|
||||
('<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>')]];
|
||||
testCases.forEach(function(testCase) {
|
||||
var suiteName = testCase[0];
|
||||
var domText = testCase[1];
|
||||
suite(suiteName, function() {
|
||||
setup(function() {
|
||||
var dom = Blockly.Xml.textToDom(domText);
|
||||
|
||||
Blockly.Xml.appendDomToWorkspace(dom, this.workspaceSvg);
|
||||
this.barDef = this.workspaceSvg.getBlockById('bar-def');
|
||||
this.barCalls = [
|
||||
this.workspaceSvg.getBlockById('bar-c1'),
|
||||
this.workspaceSvg.getBlockById('bar-c2')
|
||||
];
|
||||
});
|
||||
|
||||
test('Set disabled updates callers', function() {
|
||||
this.workspaceSvg.clearUndo();
|
||||
Blockly.Events.setGroup('g1');
|
||||
this.barDef.setEnabled(false);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isFalse(this.barCalls[i].isEnabled(),
|
||||
'Callers are disabled when their definition is disabled (call ' +
|
||||
i + ')');
|
||||
}
|
||||
var firedEvents = this.workspaceSvg.undoStack_;
|
||||
chai.assert.equal(firedEvents.length, 3,
|
||||
'An event was fired for the definition and each caller');
|
||||
for (var i = 0; i < 3; i++) {
|
||||
chai.assert.equal(firedEvents[i].group, 'g1',
|
||||
'Disable events are in the same group (event ' + i + ')');
|
||||
}
|
||||
|
||||
this.workspaceSvg.clearUndo();
|
||||
Blockly.Events.setGroup('g2');
|
||||
this.barDef.setEnabled(true);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isTrue(this.barCalls[i].isEnabled(),
|
||||
'Callers are enabled when their definition is enabled (call ' +
|
||||
i + ')');
|
||||
}
|
||||
chai.assert.equal(firedEvents.length,3,
|
||||
'An event was fired for the definition and each caller');
|
||||
for (var i = 0; i < 3; i++) {
|
||||
chai.assert.equal(firedEvents[i].group, 'g2',
|
||||
'Enable events are in the same group (event ' + i + ')');
|
||||
}
|
||||
});
|
||||
test('Set disabled updates callers while remembering old caller state', function() {
|
||||
this.barCalls[0].setEnabled(false);
|
||||
this.workspaceSvg.clearUndo();
|
||||
Blockly.Events.setGroup('g1');
|
||||
this.barDef.setEnabled(false);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.isFalse(this.barCalls[i].isEnabled(),
|
||||
'Callers are disabled when their definition is disabled (call ' +
|
||||
i + ')');
|
||||
}
|
||||
var firedEvents = this.workspaceSvg.undoStack_;
|
||||
chai.assert.equal(firedEvents.length, 2,
|
||||
'An event was fired for the definition and the enabled caller');
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.equal(firedEvents[i].group, 'g1',
|
||||
'Disable events are in the same group (event ' + i + ')');
|
||||
}
|
||||
|
||||
this.workspaceSvg.clearUndo();
|
||||
Blockly.Events.setGroup('g2');
|
||||
this.barDef.setEnabled(true);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
chai.assert.isFalse(this.barCalls[0].isEnabled(),
|
||||
'Caller remains in disabled state when the definition is enabled');
|
||||
chai.assert.isTrue(this.barCalls[1].isEnabled(),
|
||||
'Caller returns to previous enabled state when the definition is enabled');
|
||||
chai.assert.equal(firedEvents.length,2,
|
||||
'An event was fired for the definition and the enabled caller');
|
||||
for (var i = 0; i < 2; i++) {
|
||||
chai.assert.equal(firedEvents[i].group, 'g2',
|
||||
'Enable events are in the same group (event ' + i + ')');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('Mutation', function() {
|
||||
setup(function() {
|
||||
this.findParentStub = sinon.stub(Blockly.Mutator, 'findParentWs')
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
*/
|
||||
|
||||
/* exported assertArrayEquals, assertVariableValues, captureWarnings
|
||||
defineRowBlock, defineStackBlock, defineStatementBlock, createTestBlock */
|
||||
defineRowBlock, defineStackBlock, defineStatementBlock, createTestBlock,
|
||||
createEventsFireStub */
|
||||
|
||||
/**
|
||||
* Check that two arrays have the same content.
|
||||
@@ -59,6 +60,25 @@ function captureWarnings(innerFunc) {
|
||||
return msgs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates stub for Blockly.Events.fire that fires events immediately instead of
|
||||
* with timeout.
|
||||
* @return {sinon.stub} The created stub.
|
||||
*/
|
||||
function createEventsFireStub() {
|
||||
var stub = sinon.stub(Blockly.Events, 'fire');
|
||||
stub.callsFake(function(event) {
|
||||
if (!Blockly.Events.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
Blockly.Events.FIRE_QUEUE_.push(event);
|
||||
Blockly.Events.fireNow_();
|
||||
});
|
||||
stub.firedEvents_ = [];
|
||||
return stub;
|
||||
}
|
||||
|
||||
function defineStackBlock() {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "stack_block",
|
||||
|
||||
@@ -162,25 +162,15 @@ suite('Workspace comment', function() {
|
||||
});
|
||||
|
||||
suite('Content', function() {
|
||||
function temporary_fireEvent(event) {
|
||||
if (!Blockly.Events.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
Blockly.Events.FIRE_QUEUE_.push(event);
|
||||
Blockly.Events.fireNow_();
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
this.savedFireFunc_ = Blockly.Events.fire;
|
||||
Blockly.Events.fire = temporary_fireEvent;
|
||||
temporary_fireEvent.firedEvents_ = [];
|
||||
createEventsFireStub();
|
||||
|
||||
this.comment = new Blockly.WorkspaceComment(
|
||||
this.workspace, 'comment text', 0, 0, 'comment id');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Blockly.Events.fire = this.savedFireFunc_;
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
test('After creation', function() {
|
||||
|
||||
@@ -682,22 +682,8 @@ function testAWorkspace() {
|
||||
});
|
||||
|
||||
suite('Undo/Redo', function() {
|
||||
function temporary_fireEvent(event) {
|
||||
if (!Blockly.Events.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
Blockly.Events.FIRE_QUEUE_.push(event);
|
||||
Blockly.Events.fireNow_();
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
this.savedFireFunc_ = Blockly.Events.fire;
|
||||
Blockly.Events.fire = temporary_fireEvent;
|
||||
temporary_fireEvent.firedEvents_ = [];
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
Blockly.Events.fire = this.savedFireFunc_;
|
||||
createEventsFireStub();
|
||||
});
|
||||
|
||||
function createTwoVarsDifferentTypes(workspace) {
|
||||
|
||||
@@ -1,419 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Blockly Workspace SVG testing</title>
|
||||
<script src="../../blockly_uncompressed.js"></script>
|
||||
<script src="../../msg/messages.js"></script>
|
||||
<script src="../../blocks/logic.js"></script>
|
||||
<script src="../../blocks/loops.js"></script>
|
||||
<script src="../../blocks/math.js"></script>
|
||||
<script src="../../blocks/text.js"></script>
|
||||
<script src="../../blocks/lists.js"></script>
|
||||
<script src="../../blocks/colour.js"></script>
|
||||
<script src="../../blocks/variables.js"></script>
|
||||
<script src="../../blocks/procedures.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background-color: #fff;
|
||||
font-family: sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
h1 {
|
||||
font-weight: normal;
|
||||
font-size: 140%;
|
||||
}
|
||||
#blocklyDiv {
|
||||
float: right;
|
||||
height: 95%;
|
||||
width: 70%;
|
||||
}
|
||||
#importExport {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.ioLabel>.blocklyFlyoutLabelText {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="blocklyDiv"></div>
|
||||
|
||||
<h1>Blockly Workspace testing</h1>
|
||||
|
||||
<script src="https://unpkg.com/chai/chai.js"></script>
|
||||
<script src="https://unpkg.com/mocha@5.2.0/mocha.js"></script>
|
||||
<script src="https://unpkg.com/sinon/pkg/sinon.js"></script>
|
||||
<script src="../mocha/test_helpers.js"></script>
|
||||
|
||||
<script src="../jsunit/test_utilities.js"></script>
|
||||
<script src="procedure_svg_test.js"></script>
|
||||
|
||||
<script src="../jsunit/mocha_jsunit_test_runner.js"></script>
|
||||
|
||||
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox-simple" style="display: none">
|
||||
<block type="controls_ifelse"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<!-- <block type="control_repeat"></block> -->
|
||||
<block type="logic_operation"></block>
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">10</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
<block type="logic_null" disabled="true"></block>
|
||||
<block type="logic_ternary"></block>
|
||||
</xml>
|
||||
|
||||
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox-categories" style="display: none">
|
||||
<category name="Logic" colour="210">
|
||||
<block type="controls_if"></block>
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
<block type="logic_null" disabled="true"></block>
|
||||
<block type="logic_ternary"></block>
|
||||
</category>
|
||||
<category name="Loops" colour="120">
|
||||
<block type="controls_repeat_ext">
|
||||
<value name="TIMES">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">10</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="controls_repeat" disabled="true"></block>
|
||||
<block type="controls_whileUntil"></block>
|
||||
<block type="controls_for">
|
||||
<value name="FROM">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="TO">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">10</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="BY">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="controls_forEach"></block>
|
||||
<block type="controls_flow_statements"></block>
|
||||
</category>
|
||||
<category name="Math" colour="230">
|
||||
<block type="math_number" gap="32"></block>
|
||||
<block type="math_arithmetic">
|
||||
<value name="A">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="B">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_single">
|
||||
<value name="NUM">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">9</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_trig">
|
||||
<value name="NUM">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">45</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_constant"></block>
|
||||
<block type="math_number_property">
|
||||
<value name="NUMBER_TO_CHECK">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_round">
|
||||
<value name="NUM">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">3.1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_on_list"></block>
|
||||
<block type="math_modulo">
|
||||
<value name="DIVIDEND">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">64</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="DIVISOR">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">10</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_constrain">
|
||||
<value name="VALUE">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">50</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="LOW">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="HIGH">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">100</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_random_int">
|
||||
<value name="FROM">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="TO">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">100</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_random_float"></block>
|
||||
<block type="math_atan2">
|
||||
<value name="X">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="Y">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<category name="Text" colour="160">
|
||||
<block type="text"></block>
|
||||
<block type="text_join"></block>
|
||||
<block type="text_append">
|
||||
<value name="TEXT">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_length">
|
||||
<value name="VALUE">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">abc</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_isEmpty">
|
||||
<value name="VALUE">
|
||||
<shadow type="text">
|
||||
<field name="TEXT"></field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_indexOf">
|
||||
<value name="VALUE">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">text</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="FIND">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">abc</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_charAt">
|
||||
<value name="VALUE">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">text</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_getSubstring">
|
||||
<value name="STRING">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">text</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_changeCase">
|
||||
<value name="TEXT">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">abc</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_trim">
|
||||
<value name="TEXT">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">abc</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_count">
|
||||
<value name="SUB">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
<value name="TEXT">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_replace">
|
||||
<value name="FROM">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
<value name="TO">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
<value name="TEXT">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_reverse">
|
||||
<value name="TEXT">
|
||||
<shadow type="text"></shadow>
|
||||
</value>
|
||||
</block>
|
||||
<label text="Input/Output:" web-class="ioLabel"></label>
|
||||
<block type="text_print">
|
||||
<value name="TEXT">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">abc</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="text_prompt_ext">
|
||||
<value name="TEXT">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">abc</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<category name="Lists" colour="260">
|
||||
<block type="lists_create_with">
|
||||
<mutation items="0"></mutation>
|
||||
</block>
|
||||
<block type="lists_create_with"></block>
|
||||
<block type="lists_repeat">
|
||||
<value name="NUM">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="lists_length"></block>
|
||||
<block type="lists_isEmpty"></block>
|
||||
<block type="lists_indexOf">
|
||||
<value name="VALUE">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">list</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="lists_getIndex">
|
||||
<value name="VALUE">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">list</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="lists_setIndex">
|
||||
<value name="LIST">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">list</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="lists_getSublist">
|
||||
<value name="LIST">
|
||||
<block type="variables_get">
|
||||
<field name="VAR">list</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="lists_split">
|
||||
<value name="DELIM">
|
||||
<shadow type="text">
|
||||
<field name="TEXT">,</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="lists_sort"></block>
|
||||
<block type="lists_reverse"></block>
|
||||
</category>
|
||||
<category name="Colour" colour="20">
|
||||
<block type="colour_picker"></block>
|
||||
<block type="colour_random"></block>
|
||||
<block type="colour_rgb">
|
||||
<value name="RED">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">100</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="GREEN">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">50</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="BLUE">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="colour_blend">
|
||||
<value name="COLOUR1">
|
||||
<shadow type="colour_picker">
|
||||
<field name="COLOUR">#ff0000</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="COLOUR2">
|
||||
<shadow type="colour_picker">
|
||||
<field name="COLOUR">#3333ff</field>
|
||||
</shadow>
|
||||
</value>
|
||||
<value name="RATIO">
|
||||
<shadow type="math_number">
|
||||
<field name="NUM">0.5</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
</category>
|
||||
<sep></sep>
|
||||
<category name="Variables" colour="330" custom="VARIABLE"></category>
|
||||
<category name="Functions" colour="290" custom="PROCEDURE"></category>
|
||||
</xml>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,356 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var savedFireFunc = Blockly.Events.fire;
|
||||
var workspace;
|
||||
|
||||
function procedureSvgTest_setup() {
|
||||
Blockly.Events.fire = temporary_fireEvent;
|
||||
temporary_fireEvent.firedEvents_ = [];
|
||||
workspace = procedureSvgTest_createWorkspaceWithToolbox();
|
||||
}
|
||||
|
||||
function procedureSvgTest_teardown() {
|
||||
Blockly.Events.fire = savedFireFunc;
|
||||
workspace.dispose();
|
||||
}
|
||||
|
||||
function procedureSvgTest_createWorkspaceWithToolbox() {
|
||||
var toolbox = document.getElementById('toolbox-categories');
|
||||
return Blockly.inject('blocklyDiv', {toolbox: toolbox});
|
||||
}
|
||||
|
||||
function test_procedureReturnSetDisabledUpdatesCallers() {
|
||||
procedureSvgTest_setup();
|
||||
try {
|
||||
var dom = Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>');
|
||||
|
||||
|
||||
Blockly.Xml.appendDomToWorkspace(dom, workspace);
|
||||
var barDef = workspace.getBlockById('bar-def');
|
||||
var barCalls = [workspace.getBlockById('bar-c1'), workspace.getBlockById('bar-c2')];
|
||||
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g1');
|
||||
barDef.setEnabled(false);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
assertTrue('Callers are disabled when their definition is disabled.',
|
||||
barCalls[0].disabled && barCalls[1].disabled);
|
||||
|
||||
var firedEvents = workspace.undoStack_;
|
||||
assertEquals('An event was fired for the definition and each caller.',
|
||||
3, firedEvents.length);
|
||||
assertTrue('Disable events are in the same group.',
|
||||
'g1' == firedEvents[0].group
|
||||
&& 'g1' == firedEvents[1].group
|
||||
&& 'g1' == firedEvents[2].group);
|
||||
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g2');
|
||||
barDef.setEnabled(true);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
assertTrue('Callers are enabled when their definition is enabled.',
|
||||
!barCalls[0].disabled && !barCalls[1].disabled);
|
||||
|
||||
assertEquals('An event was fired for the definition and each caller.',
|
||||
3, firedEvents.length);
|
||||
assertTrue('Enable events are in the same group.',
|
||||
'g2' == firedEvents[0].group
|
||||
&& 'g2' == firedEvents[1].group
|
||||
&& 'g2' == firedEvents[2].group);
|
||||
|
||||
|
||||
} finally {
|
||||
procedureSvgTest_teardown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_procedureReturnEnablingRemembersOldCallerState() {
|
||||
procedureSvgTest_setup();
|
||||
try {
|
||||
var dom = Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>');
|
||||
|
||||
|
||||
Blockly.Xml.appendDomToWorkspace(dom, workspace);
|
||||
var barDef = workspace.getBlockById('bar-def');
|
||||
var barCalls = [workspace.getBlockById('bar-c1'), workspace.getBlockById('bar-c2')];
|
||||
|
||||
barCalls[0].setEnabled(false);
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g1');
|
||||
barDef.setEnabled(false);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
assertTrue('Callers are disabled when their definition is disabled.',
|
||||
barCalls[0].disabled && barCalls[1].disabled);
|
||||
|
||||
var firedEvents = workspace.undoStack_;
|
||||
assertEquals('An event was fired for the definition and the enabled caller.',
|
||||
2, firedEvents.length);
|
||||
assertTrue('Disable events are in the same group.',
|
||||
'g1' == firedEvents[0].group
|
||||
&& 'g1' == firedEvents[1].group);
|
||||
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g2');
|
||||
barDef.setEnabled(true);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
|
||||
assertTrue('Callers return to their previous state when the definition is enabled.',
|
||||
barCalls[0].disabled && !barCalls[1].disabled);
|
||||
|
||||
assertEquals('An event was fired for the definition and the enabled caller.',
|
||||
2, firedEvents.length);
|
||||
assertTrue('Disable events are in the same group.',
|
||||
'g2' == firedEvents[0].group
|
||||
&& 'g2' == firedEvents[1].group);
|
||||
|
||||
} finally {
|
||||
procedureSvgTest_teardown();
|
||||
}
|
||||
}
|
||||
|
||||
function test_procedureNoReturnSetDisabledUpdatesCallers() {
|
||||
procedureSvgTest_setup();
|
||||
try {
|
||||
var dom = Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defnoreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>');
|
||||
|
||||
|
||||
Blockly.Xml.appendDomToWorkspace(dom, workspace);
|
||||
var barDef = workspace.getBlockById('bar-def');
|
||||
var barCalls = [workspace.getBlockById('bar-c1'), workspace.getBlockById('bar-c2')];
|
||||
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g1');
|
||||
barDef.setEnabled(false);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
assertTrue('Callers are disabled when their definition is disabled.',
|
||||
barCalls[0].disabled && barCalls[1].disabled);
|
||||
|
||||
var firedEvents = workspace.undoStack_;
|
||||
assertEquals('An event was fired for the definition and each caller.',
|
||||
3, firedEvents.length);
|
||||
assertTrue('Disable events are in the same group.',
|
||||
'g1' == firedEvents[0].group
|
||||
&& 'g1' == firedEvents[1].group
|
||||
&& 'g1' == firedEvents[2].group);
|
||||
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g2');
|
||||
barDef.setEnabled(true);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
assertTrue('Callers are enabled when their definition is enabled.',
|
||||
!barCalls[0].disabled && !barCalls[1].disabled);
|
||||
|
||||
assertEquals('An event was fired for the definition and each caller.',
|
||||
3, firedEvents.length);
|
||||
assertTrue('Enable events are in the same group.',
|
||||
'g2' == firedEvents[0].group
|
||||
&& 'g2' == firedEvents[1].group
|
||||
&& 'g2' == firedEvents[2].group);
|
||||
|
||||
|
||||
} finally {
|
||||
procedureSvgTest_teardown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function test_procedureNoReturnEnablingRemembersOldCallerState() {
|
||||
procedureSvgTest_setup();
|
||||
try {
|
||||
var dom = Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defnoreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>');
|
||||
|
||||
|
||||
Blockly.Xml.appendDomToWorkspace(dom, workspace);
|
||||
var barDef = workspace.getBlockById('bar-def');
|
||||
var barCalls = [workspace.getBlockById('bar-c1'), workspace.getBlockById('bar-c2')];
|
||||
|
||||
barCalls[0].setEnabled(false);
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g1');
|
||||
barDef.setEnabled(false);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
assertTrue('Callers are disabled when their definition is disabled.',
|
||||
barCalls[0].disabled && barCalls[1].disabled);
|
||||
|
||||
var firedEvents = workspace.undoStack_;
|
||||
assertEquals('An event was fired for the definition and the enabled caller.',
|
||||
2, firedEvents.length);
|
||||
assertTrue('Disable events are in the same group.',
|
||||
'g1' == firedEvents[0].group
|
||||
&& 'g1' == firedEvents[1].group);
|
||||
|
||||
workspace.clearUndo();
|
||||
Blockly.Events.setGroup('g2');
|
||||
barDef.setEnabled(true);
|
||||
Blockly.Events.setGroup(false);
|
||||
|
||||
|
||||
assertTrue('Callers return to their previous state when the definition is enabled.',
|
||||
barCalls[0].disabled && !barCalls[1].disabled);
|
||||
|
||||
assertEquals('An event was fired for the definition and the enabled caller.',
|
||||
2, firedEvents.length);
|
||||
assertTrue('Disable events are in the same group.',
|
||||
'g2' == firedEvents[0].group
|
||||
&& 'g2' == firedEvents[1].group);
|
||||
|
||||
} finally {
|
||||
procedureSvgTest_teardown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a somewhat large test as it's checking interactions between
|
||||
* three procedure definitions.
|
||||
*/
|
||||
function test_procedureEnableDisableInteractions() {
|
||||
procedureSvgTest_setup();
|
||||
try {
|
||||
var dom = Blockly.Xml.textToDom(
|
||||
'<xml xmlns="https://developers.google.com/blockly/xml">' +
|
||||
'<block type="procedures_defreturn" id="bar-def">' +
|
||||
'<field name="NAME">bar</field>' +
|
||||
'<statement name="STACK">' +
|
||||
'<block type="procedures_callnoreturn" id="foo-c1">' +
|
||||
'<mutation name="foo"></mutation>' +
|
||||
'</block>' +
|
||||
'</statement>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c1">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_defnoreturn" id="foo-def">' +
|
||||
'<field name="NAME">foo</field>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_defreturn" id="baz-def">' +
|
||||
'<field name="NAME">baz</field>' +
|
||||
'<value name="RETURN">' +
|
||||
'<block type="procedures_callreturn" id="bar-c2">' +
|
||||
'<mutation name="bar"></mutation>' +
|
||||
'</block>' +
|
||||
'</value>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callnoreturn" id="foo-c2">' +
|
||||
'<mutation name="foo"></mutation>' +
|
||||
'</block>' +
|
||||
'<block type="procedures_callreturn" id="baz-c1">' +
|
||||
'<mutation name="baz"></mutation>' +
|
||||
'</block>' +
|
||||
'</xml>');
|
||||
Blockly.Events.disable();
|
||||
Blockly.Xml.appendDomToWorkspace(dom, workspace);
|
||||
Blockly.Events.enable();
|
||||
|
||||
var barDef = workspace.getBlockById('bar-def');
|
||||
var fooDef = workspace.getBlockById('foo-def');
|
||||
var bazDef = workspace.getBlockById('baz-def');
|
||||
|
||||
var barCalls = [workspace.getBlockById('bar-c1'), workspace.getBlockById('bar-c2')];
|
||||
var fooCalls = [workspace.getBlockById('foo-c1'), workspace.getBlockById('foo-c2')];
|
||||
var bazCall = workspace.getBlockById('baz-c1');
|
||||
|
||||
barDef.setEnabled(false);
|
||||
|
||||
assertTrue('Callers are disabled when their definition is disabled.',
|
||||
barCalls[0].disabled && barCalls[1].disabled);
|
||||
assertTrue('Callers in definitions are disabled by inheritance.',
|
||||
!fooCalls[0].disabled && fooCalls[0].getInheritedDisabled());
|
||||
|
||||
fooDef.setEnabled(false);
|
||||
|
||||
assertTrue('Callers are disabled when their definition is disabled',
|
||||
fooCalls[0].disabled && fooCalls[1].disabled);
|
||||
|
||||
barDef.setEnabled(true);
|
||||
|
||||
assertTrue('Callers are reenabled with their definition',
|
||||
!barCalls[0].disabled && !barCalls[0].disabled);
|
||||
|
||||
assertTrue('Nested disabled callers remain disabled, not by inheritance.',
|
||||
fooCalls[0].disabled && !fooCalls[0].getInheritedDisabled());
|
||||
|
||||
bazDef.setEnabled(false);
|
||||
|
||||
assertTrue('Caller is disabled with its definition',
|
||||
bazCall.disabled);
|
||||
|
||||
assertTrue('Caller in the return is disabled by inheritance.',
|
||||
!barCalls[1].disabled && barCalls[1].getInheritedDisabled());
|
||||
|
||||
barDef.setEnabled(false);
|
||||
assertTrue('Callers are disabled when their definition is disabled.',
|
||||
barCalls[0].disabled && barCalls[1].disabled);
|
||||
|
||||
bazDef.setEnabled(true);
|
||||
|
||||
assertTrue('Caller in the return remains disabled, not by inheritance.',
|
||||
barCalls[1].disabled && !barCalls[1].getInheritedDisabled());
|
||||
|
||||
} finally {
|
||||
procedureSvgTest_teardown();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user