mirror of
https://github.com/google/blockly.git
synced 2026-01-10 10:27:08 +01:00
Merge pull request #3123 from BeksOmega/tests/Connections
Connection Tracking Pt 1: Added a bunch of connection related tests
This commit is contained in:
@@ -681,8 +681,8 @@ Blockly.Connection.prototype.onCheckChanged_ = function() {
|
||||
|
||||
/**
|
||||
* Change a connection's compatibility.
|
||||
* @param {*} check Compatible value type or list of value types.
|
||||
* Null if all types are compatible.
|
||||
* @param {string|!Array<string>} check Compatible value type or list of value
|
||||
* types. Null if all types are compatible.
|
||||
* @return {!Blockly.Connection} The connection being modified
|
||||
* (to allow chaining).
|
||||
*/
|
||||
|
||||
@@ -178,6 +178,9 @@ Blockly.Input.prototype.isVisible = function() {
|
||||
* @package
|
||||
*/
|
||||
Blockly.Input.prototype.setVisible = function(visible) {
|
||||
// Note: Currently there are only unit tests for block.setCollapsed()
|
||||
// because this function is package. If this function goes back to being a
|
||||
// public API tests (lots of tests) should be added.
|
||||
var renderList = [];
|
||||
if (this.visible_ == visible) {
|
||||
return renderList;
|
||||
|
||||
@@ -1,310 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Blockly Tests
|
||||
*
|
||||
* Copyright 2015 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
function verify_DB_(msg, expected, db) {
|
||||
var equal = (expected.length == db.connections_.length);
|
||||
if (equal) {
|
||||
for (var i = 0; i < expected.length; i++) {
|
||||
if (expected[i] != db.connections_[i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (equal) {
|
||||
assertTrue(msg, true);
|
||||
} else {
|
||||
assertEquals(msg, expected, db.connections_);
|
||||
}
|
||||
}
|
||||
|
||||
function test_DB_addConnection() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
var o2 = {y_: 2, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o2);
|
||||
verify_DB_('Adding connection #2', [o2], db);
|
||||
|
||||
var o4 = {y_: 4, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o4);
|
||||
verify_DB_('Adding connection #4', [o2, o4], db);
|
||||
|
||||
var o1 = {y_: 1, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o1);
|
||||
verify_DB_('Adding connection #1', [o1, o2, o4], db);
|
||||
|
||||
var o3a = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o3a);
|
||||
verify_DB_('Adding connection #3a', [o1, o2, o3a, o4], db);
|
||||
|
||||
var o3b = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o3b);
|
||||
verify_DB_('Adding connection #3b', [o1, o2, o3b, o3a, o4], db);
|
||||
}
|
||||
|
||||
function test_DB_removeConnection() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
var o1 = {y_: 1, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o2 = {y_: 2, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o3a = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o3b = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o3c = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o4 = {y_: 4, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o1);
|
||||
db.addConnection(o2);
|
||||
db.addConnection(o3c);
|
||||
db.addConnection(o3b);
|
||||
db.addConnection(o3a);
|
||||
db.addConnection(o4);
|
||||
verify_DB_('Adding connections 1-4', [o1, o2, o3a, o3b, o3c, o4], db);
|
||||
|
||||
db.removeConnection_(o2);
|
||||
verify_DB_('Removing connection #2', [o1, o3a, o3b, o3c, o4], db);
|
||||
|
||||
db.removeConnection_(o4);
|
||||
verify_DB_('Removing connection #4', [o1, o3a, o3b, o3c], db);
|
||||
|
||||
db.removeConnection_(o1);
|
||||
verify_DB_('Removing connection #1', [o3a, o3b, o3c], db);
|
||||
|
||||
db.removeConnection_(o3a);
|
||||
verify_DB_('Removing connection #3a', [o3b, o3c], db);
|
||||
|
||||
db.removeConnection_(o3c);
|
||||
verify_DB_('Removing connection #3c', [o3b], db);
|
||||
|
||||
db.removeConnection_(o3b);
|
||||
verify_DB_('Removing connection #3b', [], db);
|
||||
}
|
||||
|
||||
function test_DB_getNeighbours() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
|
||||
// Search an empty list.
|
||||
assertEquals(helper_getNeighbours(db,
|
||||
10 /* x */, 10 /* y */, 100 /* radius */).length, 0);
|
||||
|
||||
// Set up some connections.
|
||||
for (var i = 0; i < 10; i++) {
|
||||
db.addConnection(helper_createConnection(0, i,
|
||||
Blockly.PREVIOUS_STATEMENT, null, true));
|
||||
}
|
||||
|
||||
// Test block belongs at beginning.
|
||||
var result = helper_getNeighbours(db, 0, 0, 4);
|
||||
assertEquals(5, result.length);
|
||||
for (i = 0; i < result.length; i++) {
|
||||
assertNotEquals(result.indexOf(db.connections_[i]), -1); // contains
|
||||
}
|
||||
|
||||
// Test block belongs at middle.
|
||||
result = helper_getNeighbours(db, 0, 4, 2);
|
||||
assertEquals(5, result.length);
|
||||
for (i = 0; i < result.length; i++) {
|
||||
assertNotEquals(result.indexOf(db.connections_[i + 2]), -1); // contains
|
||||
}
|
||||
|
||||
// Test block belongs at end.
|
||||
result = helper_getNeighbours(db, 0, 9, 4);
|
||||
assertEquals(5, result.length);
|
||||
for (i = 0; i < result.length; i++) {
|
||||
assertNotEquals(result.indexOf(db.connections_[i + 5]), -1); // contains
|
||||
}
|
||||
|
||||
// Test block has no neighbours due to being out of range in the x direction.
|
||||
result = helper_getNeighbours(db, 10, 9, 4);
|
||||
assertEquals(result.length, 0);
|
||||
|
||||
// Test block has no neighbours due to being out of range in the y direction.
|
||||
result = helper_getNeighbours(db, 0, 19, 4);
|
||||
assertEquals(result.length, 0);
|
||||
|
||||
// Test block has no neighbours due to being out of range diagonally.
|
||||
result = helper_getNeighbours(db, -2, -2, 2);
|
||||
assertEquals(result.length, 0);
|
||||
}
|
||||
|
||||
function test_DB_findPositionForConnection() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
db.addConnection(helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 1, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 2, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 4, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 5, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
|
||||
assertEquals(5, db.connections_.length);
|
||||
var conn = helper_createConnection(0, 3, Blockly.PREVIOUS_STATEMENT, null,
|
||||
true);
|
||||
assertEquals(3, db.findPositionForConnection_(conn));
|
||||
}
|
||||
|
||||
function test_DB_findConnection() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
db.addConnection(helper_createConnection(i, 0,
|
||||
Blockly.PREVIOUS_STATEMENT, null, true));
|
||||
db.addConnection(helper_createConnection(0, i,
|
||||
Blockly.PREVIOUS_STATEMENT, null, true));
|
||||
}
|
||||
|
||||
var conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null,
|
||||
true);
|
||||
db.addConnection(conn);
|
||||
assertEquals(conn, db.connections_[db.findConnection(conn)]);
|
||||
|
||||
conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null, true);
|
||||
assertEquals(-1, db.findConnection(conn));
|
||||
}
|
||||
|
||||
function test_DB_ordering() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
db.addConnection(helper_createConnection(0, 9 - i,
|
||||
Blockly.PREVIOUS_STATEMENT), null, true);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
assertEquals(i, db.connections_[i].y_);
|
||||
}
|
||||
|
||||
// quasi-random
|
||||
var xCoords = [-29, -47, -77, 2, 43, 34, -59, -52, -90, -36, -91, 38, 87, -20,
|
||||
60, 4, -57, 65, -37, -81, 57, 58, -96, 1, 67, -79, 34, 93, -90, -99, -62,
|
||||
4, 11, -36, -51, -72, 3, -50, -24, -45, -92, -38, 37, 24, -47, -73, 79,
|
||||
-20, 99, 43, -10, -87, 19, 35, -62, -36, 49, 86, -24, -47, -89, 33, -44,
|
||||
25, -73, -91, 85, 6, 0, 89, -94, 36, -35, 84, -9, 96, -21, 52, 10, -95, 7,
|
||||
-67, -70, 62, 9, -40, -95, -9, -94, 55, 57, -96, 55, 8, -48, -57, -87, 81,
|
||||
23, 65];
|
||||
var yCoords = [-81, 82, 5, 47, 30, 57, -12, 28, 38, 92, -25, -20, 23, -51, 73,
|
||||
-90, 8, 28, -51, -15, 81, -60, -6, -16, 77, -62, -42, -24, 35, 95, -46,
|
||||
-7, 61, -16, 14, 91, 57, -38, 27, -39, 92, 47, -98, 11, -33, -72, 64, 38,
|
||||
-64, -88, -35, -59, -76, -94, 45, -25, -100, -95, 63, -97, 45, 98, 99, 34,
|
||||
27, 52, -18, -45, 66, -32, -38, 70, -73, -23, 5, -2, -13, -9, 48, 74, -97,
|
||||
-11, 35, -79, -16, -77, 83, -57, -53, 35, -44, 100, -27, -15, 5, 39, 33,
|
||||
-19, -20, -95];
|
||||
for (i = 0; i < xCoords.length; i++) {
|
||||
db.addConnection(helper_createConnection(xCoords[i], yCoords[i],
|
||||
Blockly.PREVIOUS_STATEMENT), null, true);
|
||||
}
|
||||
|
||||
for (i = 1; i < xCoords.length; i++) {
|
||||
assertTrue(db.connections_[i].y_ >= db.connections_[i - 1].y_);
|
||||
}
|
||||
}
|
||||
|
||||
function test_SearchForClosest() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
var sharedWorkspace = {id: "Shared workspace"};
|
||||
|
||||
// Search an empty list.
|
||||
assertEquals(null, helper_searchDB(db, 10 /* x */, 10 /* y */,
|
||||
100 /* radius */));
|
||||
|
||||
db.addConnection(helper_createConnection(100, 0, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true));
|
||||
assertEquals(null, helper_searchDB(db, 0, 0, 5, sharedWorkspace));
|
||||
|
||||
db = new Blockly.ConnectionDB();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var tempConn = helper_createConnection(0, i, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
db.addConnection(tempConn);
|
||||
}
|
||||
|
||||
// Should be at 0, 9.
|
||||
var last = db.connections_[db.connections_.length - 1];
|
||||
// Correct connection is last in db; many connections in radius.
|
||||
assertEquals(last, helper_searchDB(db, 0, 10, 15, sharedWorkspace));
|
||||
// Nothing nearby.
|
||||
assertEquals(null, helper_searchDB(db, 100, 100, 3, sharedWorkspace));
|
||||
// First in db, exact match.
|
||||
assertEquals(db.connections_[0], helper_searchDB(db, 0, 0, 0, sharedWorkspace));
|
||||
|
||||
tempConn = helper_createConnection(6, 6, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
db.addConnection(tempConn);
|
||||
tempConn = helper_createConnection(5, 5, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
db.addConnection(tempConn);
|
||||
|
||||
var result = helper_searchDB(db, 4, 6, 3, sharedWorkspace);
|
||||
assertEquals(5, result.x_);
|
||||
assertEquals(5, result.y_);
|
||||
}
|
||||
|
||||
|
||||
function helper_getNeighbours(db, x, y, radius) {
|
||||
return db.getNeighbours(helper_createConnection(x, y, Blockly.NEXT_STATEMENT,
|
||||
null, true),
|
||||
radius);
|
||||
}
|
||||
|
||||
function helper_searchDB(db, x, y, radius, shared_workspace) {
|
||||
var tempConn = helper_createConnection(x, y,
|
||||
Blockly.NEXT_STATEMENT, shared_workspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(shared_workspace);
|
||||
tempConn.sourceBlock_.nextConnection = tempConn;
|
||||
var closest = db.searchForClosest(tempConn, radius, {x: 0, y: 0});
|
||||
return closest.connection;
|
||||
}
|
||||
|
||||
function helper_makeSourceBlock(sharedWorkspace) {
|
||||
return {workspace: sharedWorkspace,
|
||||
parentBlock_: null,
|
||||
getParent: function() { return null; },
|
||||
movable_: true,
|
||||
isMovable: function() { return true; },
|
||||
isShadow: function() { return false; },
|
||||
isInsertionMarker: function() { return false; },
|
||||
getFirstStatementConnection: function() { return null; }
|
||||
};
|
||||
}
|
||||
|
||||
function helper_createConnection(x, y, type, opt_shared_workspace,
|
||||
opt_rendered) {
|
||||
var workspace = opt_shared_workspace ? opt_shared_workspace : {};
|
||||
if (opt_rendered) {
|
||||
var conn = new Blockly.RenderedConnection({workspace: workspace}, type);
|
||||
} else {
|
||||
var conn = new Blockly.Connection({workspace: workspace}, type);
|
||||
}
|
||||
conn.x_ = x;
|
||||
conn.y_ = y;
|
||||
return conn;
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Blockly Tests
|
||||
*
|
||||
* Copyright 2016 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Tests for connection logic.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var input;
|
||||
var output;
|
||||
var previous;
|
||||
var next;
|
||||
|
||||
var dummyWorkspace;
|
||||
|
||||
function connectionTest_setUp() {
|
||||
dummyWorkspace = {};
|
||||
function createDummyBlock() {
|
||||
return {
|
||||
workspace: dummyWorkspace,
|
||||
isShadow: function() {return false;}
|
||||
};
|
||||
}
|
||||
input = new Blockly.Connection(createDummyBlock(),
|
||||
Blockly.INPUT_VALUE);
|
||||
output = new Blockly.Connection(createDummyBlock(),
|
||||
Blockly.OUTPUT_VALUE);
|
||||
previous = new Blockly.Connection(createDummyBlock(),
|
||||
Blockly.PREVIOUS_STATEMENT);
|
||||
next = new Blockly.Connection(createDummyBlock(),
|
||||
Blockly.NEXT_STATEMENT);
|
||||
}
|
||||
|
||||
function connectionTest_tearDown() {
|
||||
input = null;
|
||||
output = null;
|
||||
previous = null;
|
||||
next = null;
|
||||
dummyWorkspace = null;
|
||||
}
|
||||
|
||||
var isMovableFn = function() { return true; };
|
||||
/**
|
||||
* These tests check that the reasons for failures to connect are consistent
|
||||
* (internal view of error states).
|
||||
*/
|
||||
function testCanConnectWithReason_TargetNull() {
|
||||
connectionTest_setUp();
|
||||
|
||||
assertEquals(Blockly.Connection.REASON_TARGET_NULL,
|
||||
input.canConnectWithReason_(null));
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCanConnectWithReason_Disconnect() {
|
||||
connectionTest_setUp();
|
||||
|
||||
var tempConnection = new Blockly.Connection({workspace: dummyWorkspace, isMovable: isMovableFn},
|
||||
Blockly.OUTPUT_VALUE);
|
||||
Blockly.Connection.connectReciprocally_(input, tempConnection);
|
||||
assertEquals(Blockly.Connection.CAN_CONNECT,
|
||||
input.canConnectWithReason_(output));
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCanConnectWithReason_DifferentWorkspaces() {
|
||||
connectionTest_setUp();
|
||||
|
||||
input = new Blockly.Connection({workspace: {}}, Blockly.INPUT_VALUE);
|
||||
output = new Blockly.Connection({workspace: dummyWorkspace},
|
||||
Blockly.OUTPUT_VALUE);
|
||||
|
||||
assertEquals(Blockly.Connection.REASON_DIFFERENT_WORKSPACES,
|
||||
input.canConnectWithReason_(output));
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
|
||||
function testCanConnectWithReason_Self() {
|
||||
connectionTest_setUp();
|
||||
|
||||
var block = {type_: "test block"};
|
||||
input.sourceBlock_ = block;
|
||||
assertEquals(Blockly.Connection.REASON_SELF_CONNECTION,
|
||||
input.canConnectWithReason_(input));
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCanConnectWithReason_Type() {
|
||||
connectionTest_setUp();
|
||||
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
input.canConnectWithReason_(previous));
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
input.canConnectWithReason_(next));
|
||||
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
output.canConnectWithReason_(previous));
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
output.canConnectWithReason_(next));
|
||||
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
previous.canConnectWithReason_(input));
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
previous.canConnectWithReason_(output));
|
||||
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
next.canConnectWithReason_(input));
|
||||
assertEquals(Blockly.Connection.REASON_WRONG_TYPE,
|
||||
next.canConnectWithReason_(output));
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCanConnectWithReason_CanConnect() {
|
||||
connectionTest_setUp();
|
||||
|
||||
assertEquals(Blockly.Connection.CAN_CONNECT,
|
||||
previous.canConnectWithReason_(next));
|
||||
assertEquals(Blockly.Connection.CAN_CONNECT,
|
||||
next.canConnectWithReason_(previous));
|
||||
assertEquals(Blockly.Connection.CAN_CONNECT,
|
||||
input.canConnectWithReason_(output));
|
||||
assertEquals(Blockly.Connection.CAN_CONNECT,
|
||||
output.canConnectWithReason_(input));
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The next set of tests checks that exceptions are being thrown at the correct
|
||||
* times (external view of errors).
|
||||
*/
|
||||
function testCheckConnection_Self() {
|
||||
connectionTest_setUp();
|
||||
var block = {type_: "test block"};
|
||||
input.sourceBlock_ = block;
|
||||
try {
|
||||
input.checkConnection_(input);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypeInputPrev() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
input.checkConnection_(previous);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypeInputNext() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
input.checkConnection_(next);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypeOutputPrev() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
output.checkConnection_(previous);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypePrevInput() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
previous.checkConnection_(input);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypePrevOutput() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
previous.checkConnection_(output);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypeNextInput() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
next.checkConnection_(input);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function testCheckConnection_TypeNextOutput() {
|
||||
connectionTest_setUp();
|
||||
try {
|
||||
next.checkConnection_(output);
|
||||
fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
|
||||
function test_isConnectionAllowed_Distance() {
|
||||
var sharedWorkspace = {};
|
||||
// Two connections of opposite types near each other.
|
||||
var one = helper_createConnection(5 /* x */, 10 /* y */,
|
||||
Blockly.INPUT_VALUE, null, true);
|
||||
one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
|
||||
var two = helper_createConnection(10 /* x */, 15 /* y */,
|
||||
Blockly.OUTPUT_VALUE, null, true);
|
||||
two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
|
||||
assertTrue(one.isConnectionAllowed(two, 20.0));
|
||||
// Move connections farther apart.
|
||||
two.x_ = 100;
|
||||
two.y_ = 100;
|
||||
assertFalse(one.isConnectionAllowed(two, 20.0));
|
||||
}
|
||||
|
||||
function test_isConnectionAllowed_Unrendered() {
|
||||
var sharedWorkspace = {};
|
||||
|
||||
var one = helper_createConnection(5 /* x */, 10 /* y */,
|
||||
Blockly.INPUT_VALUE);
|
||||
one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
|
||||
// Don't offer to connect an already connected left (male) value plug to
|
||||
// an available right (female) value plug.
|
||||
var two = helper_createConnection(0, 0, Blockly.OUTPUT_VALUE);
|
||||
two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
|
||||
assertTrue(one.isConnectionAllowed(two));
|
||||
var three = helper_createConnection(0, 0, Blockly.INPUT_VALUE);
|
||||
three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
|
||||
Blockly.Connection.connectReciprocally_(two, three);
|
||||
assertFalse(one.isConnectionAllowed(two));
|
||||
|
||||
// Don't connect two connections on the same block.
|
||||
two.sourceBlock_ = one.sourceBlock_;
|
||||
assertFalse(one.isConnectionAllowed(two));
|
||||
}
|
||||
|
||||
function test_isConnectionAllowed_NoNext() {
|
||||
var sharedWorkspace = {};
|
||||
var one = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
one.sourceBlock_.nextConnection = one;
|
||||
|
||||
var two = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
|
||||
assertTrue(two.isConnectionAllowed(one));
|
||||
|
||||
var three = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
three.sourceBlock_.previousConnection = three;
|
||||
Blockly.Connection.connectReciprocally_(one, three);
|
||||
|
||||
// A terminal block is allowed to replace another terminal block.
|
||||
assertTrue(two.isConnectionAllowed(one));
|
||||
}
|
||||
|
||||
function test_canConnectToPrevious_alreadyConnected() {
|
||||
var sharedWorkspace = {};
|
||||
var one = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
one.sourceBlock_.nextConnection = one;
|
||||
|
||||
var two = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
two.sourceBlock_.previousConnection = two;
|
||||
|
||||
Blockly.Connection.connectReciprocally_(one, two);
|
||||
|
||||
var three = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
three.sourceBlock_.previousConnection = three;
|
||||
|
||||
// The next connection is already occupied and cannot disconnect itself
|
||||
// mid-drag.
|
||||
assertFalse(one.canConnectToPrevious_(three));
|
||||
}
|
||||
|
||||
function test_canConnect_dragging() {
|
||||
var sharedWorkspace = {};
|
||||
var one = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
one.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
one.sourceBlock_.nextConnection = one;
|
||||
|
||||
var two = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
two.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
two.sourceBlock_.previousConnection = two;
|
||||
|
||||
Blockly.Connection.connectReciprocally_(one, two);
|
||||
|
||||
Blockly.draggingConnections_.push(one);
|
||||
Blockly.draggingConnections_.push(two);
|
||||
|
||||
assertFalse(two.isConnectionAllowed(one));
|
||||
assertFalse(one.isConnectionAllowed(two));
|
||||
}
|
||||
|
||||
function test_canConnect_stackStart() {
|
||||
var sharedWorkspace = {};
|
||||
var block1Next = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
var block1 = helper_makeSourceBlock(sharedWorkspace);
|
||||
block1Next.sourceBlock_ = block1
|
||||
block1.nextConnection = block1Next;
|
||||
|
||||
var block1Prev = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
block1Prev.sourceBlock_ = block1;
|
||||
block1.previousConnection = block1Prev
|
||||
|
||||
var block2Prev = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
block2Prev.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
block2Prev.sourceBlock_.previousConnection = block2Prev;
|
||||
|
||||
Blockly.Connection.connectReciprocally_(block1Next, block2Prev);
|
||||
|
||||
var three = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
three.sourceBlock_.nextConnection = three;
|
||||
|
||||
// Can connect at the beginning of the stack.
|
||||
assertTrue(three.canConnectToPrevious_(block1Prev));
|
||||
// But not in the middle of the stack.
|
||||
assertFalse(three.canConnectToPrevious_(block2Prev));
|
||||
}
|
||||
|
||||
function test_canConnect_stackStart_insertionMarker() {
|
||||
var sharedWorkspace = {};
|
||||
var block1Next = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
var block1 = helper_makeSourceBlock(sharedWorkspace);
|
||||
block1.isInsertionMarker = function() {
|
||||
return true;
|
||||
}
|
||||
block1.getPreviousBlock = function() {
|
||||
return false;
|
||||
}
|
||||
block1Next.sourceBlock_ = block1
|
||||
block1.nextConnection = block1Next;
|
||||
|
||||
var block1Prev = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
block1Prev.sourceBlock_ = block1;
|
||||
block1.previousConnection = block1Prev
|
||||
|
||||
var block2Prev = helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT);
|
||||
var block2 = helper_makeSourceBlock(sharedWorkspace);
|
||||
block2Prev.sourceBlock_ = block2;
|
||||
block2.previousConnection = block2Prev;
|
||||
block2.getPreviousBlock = function() {
|
||||
return block1;
|
||||
}
|
||||
|
||||
|
||||
Blockly.Connection.connectReciprocally_(block1Next, block2Prev);
|
||||
|
||||
var three = helper_createConnection(0, 0, Blockly.NEXT_STATEMENT);
|
||||
three.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
three.sourceBlock_.nextConnection = three;
|
||||
|
||||
// Can't connect to the previous connection of an insertion marker.
|
||||
assertFalse(three.isConnectionAllowed(block1Prev));
|
||||
// But can connect to a previous connection that is already connected to an
|
||||
// insertion marker.
|
||||
assertTrue(three.isConnectionAllowed(block2Prev));
|
||||
}
|
||||
|
||||
function testCheckConnection_Okay() {
|
||||
connectionTest_setUp();
|
||||
previous.checkConnection_(next);
|
||||
next.checkConnection_(previous);
|
||||
input.checkConnection_(output);
|
||||
output.checkConnection_(input);
|
||||
|
||||
connectionTest_tearDown();
|
||||
}
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
<script src="test_utilities.js"></script>
|
||||
<script src="block_test.js"></script>
|
||||
<script src="connection_db_test.js"></script>
|
||||
<script src="connection_test.js"></script>
|
||||
<script src="event_test.js"></script>
|
||||
<script src="extensions_test.js"></script>
|
||||
<script src="generator_test.js"></script>
|
||||
|
||||
@@ -21,14 +21,8 @@
|
||||
suite('Blocks', function() {
|
||||
setup(function() {
|
||||
this.workspace = new Blockly.Workspace();
|
||||
});
|
||||
teardown(function() {
|
||||
this.workspace.dispose();
|
||||
});
|
||||
|
||||
suite('Connection Management', function() {
|
||||
setup(function() {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
"type": "stack_block",
|
||||
"message0": "",
|
||||
"previousStatement": null,
|
||||
@@ -44,13 +38,28 @@ suite('Blocks', function() {
|
||||
}
|
||||
],
|
||||
"output": null
|
||||
},
|
||||
{
|
||||
"type": "statement_block",
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_statement",
|
||||
"name": "STATEMENT"
|
||||
}
|
||||
],
|
||||
"previousStatement": null,
|
||||
"nextStatement": null
|
||||
}]);
|
||||
});
|
||||
teardown(function() {
|
||||
delete Blockly.Blocks['stack_block'];
|
||||
delete Blockly.Blocks['row_block'];
|
||||
});
|
||||
});
|
||||
teardown(function() {
|
||||
this.workspace.dispose();
|
||||
delete Blockly.Blocks['stack_block'];
|
||||
delete Blockly.Blocks['row_block'];
|
||||
delete Blockly.Blocks['statement_block'];
|
||||
});
|
||||
|
||||
suite('Connection Management', function() {
|
||||
suite('Unplug', function() {
|
||||
function assertUnpluggedNoheal(blocks) {
|
||||
// A has nothing connected to it.
|
||||
@@ -431,6 +440,535 @@ suite('Blocks', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('Connection Tracking', function() {
|
||||
setup(function() {
|
||||
this.workspace.dispose();
|
||||
// The new rendered workspace will get disposed by the parent teardown.
|
||||
this.workspace = Blockly.inject('blocklyDiv');
|
||||
|
||||
this.getInputs = function() {
|
||||
return this.workspace
|
||||
.connectionDBList[Blockly.INPUT_VALUE].connections_;
|
||||
};
|
||||
this.getOutputs = function() {
|
||||
return this.workspace
|
||||
.connectionDBList[Blockly.OUTPUT_VALUE].connections_;
|
||||
};
|
||||
this.getNext = function() {
|
||||
return this.workspace
|
||||
.connectionDBList[Blockly.NEXT_STATEMENT].connections_;
|
||||
};
|
||||
this.getPrevious = function() {
|
||||
return this.workspace
|
||||
.connectionDBList[Blockly.PREVIOUS_STATEMENT].connections_;
|
||||
};
|
||||
|
||||
this.assertConnectionsEmpty = function() {
|
||||
chai.assert.isEmpty(this.getInputs());
|
||||
chai.assert.isEmpty(this.getOutputs());
|
||||
chai.assert.isEmpty(this.getNext());
|
||||
chai.assert.isEmpty(this.getPrevious());
|
||||
};
|
||||
|
||||
this.clock = sinon.useFakeTimers();
|
||||
});
|
||||
teardown(function() {
|
||||
this.clock.restore();
|
||||
});
|
||||
suite('Deserialization', function() {
|
||||
test('Stack', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="stack_block"/>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
});
|
||||
test('Multi-Stack', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="stack_block">' +
|
||||
' <next>' +
|
||||
' <block type="stack_block">' +
|
||||
' <next>' +
|
||||
' <block type="stack_block"/>' +
|
||||
' </next>' +
|
||||
' </block>' +
|
||||
' </next>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
});
|
||||
test('Collapsed Stack', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="stack_block" collapsed="true"/>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
});
|
||||
test('Collapsed Multi-Stack', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="stack_block" collapsed="true">' +
|
||||
' <next>' +
|
||||
' <block type="stack_block" collapsed="true">' +
|
||||
' <next>' +
|
||||
' <block type="stack_block" collapsed="true"/>' +
|
||||
' </next>' +
|
||||
' </block>' +
|
||||
' </next>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
});
|
||||
test('Row', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="row_block"/>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
});
|
||||
test('Multi-Row', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block"/>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
});
|
||||
test('Collapsed Row', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="row_block" collapsed="true"/>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 0);
|
||||
});
|
||||
test('Collapsed Multi-Row', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="row_block" collapsed="true">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block"/>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 0);
|
||||
});
|
||||
test('Collapsed Multi-Row Middle', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block" collapsed="true">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block"/>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 2);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
});
|
||||
test('Statement', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="statement_block"/>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 2);
|
||||
});
|
||||
test('Multi-Statement', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
});
|
||||
test('Collapsed Statement', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="statement_block" collapsed="true"/>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
});
|
||||
test('Collapsed Multi-Statement', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="statement_block" collapsed="true">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
});
|
||||
test('Collapsed Multi-Statement Middle', function() {
|
||||
Blockly.Xml.appendDomToWorkspace(Blockly.Xml.textToDom(
|
||||
'<xml>' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block" collapsed="true">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
'</xml>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 2);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
});
|
||||
});
|
||||
suite('Programmatic Block Creation', function() {
|
||||
test('Stack', function() {
|
||||
var block = this.workspace.newBlock('stack_block');
|
||||
this.assertConnectionsEmpty();
|
||||
block.initSvg();
|
||||
block.render();
|
||||
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
});
|
||||
test('Row', function() {
|
||||
var block = this.workspace.newBlock('row_block');
|
||||
this.assertConnectionsEmpty();
|
||||
block.initSvg();
|
||||
block.render();
|
||||
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
});
|
||||
test('Statement', function() {
|
||||
var block = this.workspace.newBlock('statement_block');
|
||||
this.assertConnectionsEmpty();
|
||||
block.initSvg();
|
||||
block.render();
|
||||
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 2);
|
||||
});
|
||||
});
|
||||
suite('setCollapsed', function() {
|
||||
test('Stack', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="stack_block"/>'
|
||||
), this.workspace);
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
});
|
||||
test('Multi-Stack', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="stack_block">' +
|
||||
' <next>' +
|
||||
' <block type="stack_block">' +
|
||||
' <next>' +
|
||||
' <block type="stack_block"/>' +
|
||||
' </next>' +
|
||||
' </block>' +
|
||||
' </next>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
});
|
||||
test('Row', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="row_block"/>'
|
||||
), this.workspace);
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 0);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
});
|
||||
test('Multi-Row', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block"/>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
' </value>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 0);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
});
|
||||
test('Multi-Row Middle', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block"/>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
' </value>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
|
||||
block = block.getInputTargetBlock('INPUT');
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getOutputs().length, 2);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
});
|
||||
test('Multi-Row Double Collapse', function() {
|
||||
// Collapse middle -> Collapse top ->
|
||||
// Uncollapse top -> Uncollapse middle
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block">' +
|
||||
' <value name="INPUT">' +
|
||||
' <block type="row_block"/>' +
|
||||
' </value>' +
|
||||
' </block>' +
|
||||
' </value>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
|
||||
var middleBlock = block.getInputTargetBlock('INPUT');
|
||||
middleBlock.setCollapsed(true);
|
||||
chai.assert.equal(this.getOutputs().length, 2);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getOutputs().length, 1);
|
||||
chai.assert.equal(this.getInputs().length, 0);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getOutputs().length, 2);
|
||||
chai.assert.equal(this.getInputs().length, 1);
|
||||
|
||||
middleBlock.setCollapsed(false);
|
||||
chai.assert.equal(this.getOutputs().length, 3);
|
||||
chai.assert.equal(this.getInputs().length, 3);
|
||||
});
|
||||
test('Statement', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block"/>'
|
||||
), this.workspace);
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 2);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 2);
|
||||
});
|
||||
test('Multi-Statement', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
' </statement>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
});
|
||||
test('Multi-Statement Middle', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
' </statement>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
|
||||
block = block.getInputTargetBlock('STATEMENT');
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 2);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
});
|
||||
test('Multi-Statement Double Collapse', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
' </block>' +
|
||||
' </statement>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
this.assertConnectionsEmpty();
|
||||
this.clock.tick(1);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
|
||||
var middleBlock = block.getInputTargetBlock('STATEMENT');
|
||||
middleBlock.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 2);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
|
||||
block.setCollapsed(true);
|
||||
chai.assert.equal(this.getPrevious().length, 1);
|
||||
chai.assert.equal(this.getNext().length, 1);
|
||||
|
||||
block.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 2);
|
||||
chai.assert.equal(this.getNext().length, 3);
|
||||
|
||||
middleBlock.setCollapsed(false);
|
||||
chai.assert.equal(this.getPrevious().length, 3);
|
||||
chai.assert.equal(this.getNext().length, 6);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('Comments', function() {
|
||||
setup(function() {
|
||||
@@ -492,7 +1030,6 @@ suite('Blocks', function() {
|
||||
});
|
||||
suite('Rendered', function() {
|
||||
setup(function() {
|
||||
// Let the parent teardown take care of this.
|
||||
this.workspace = Blockly.inject('blocklyDiv', {
|
||||
comments: true,
|
||||
scrollbars: true
|
||||
@@ -501,6 +1038,9 @@ suite('Blocks', function() {
|
||||
'<block type="empty_block"/>'
|
||||
), this.workspace);
|
||||
});
|
||||
teardown(function() {
|
||||
this.workspace.dispose();
|
||||
});
|
||||
test('Text', function() {
|
||||
this.block.setCommentText('test text');
|
||||
chai.assert.equal(this.block.getCommentText(), 'test text');
|
||||
@@ -559,4 +1099,56 @@ suite('Blocks', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('Icon Management', function() {
|
||||
suite('Bubbles and Collapsing', function() {
|
||||
setup(function() {
|
||||
this.workspace.dispose();
|
||||
this.workspace = Blockly.inject('blocklyDiv');
|
||||
});
|
||||
teardown(function() {
|
||||
this.workspace.dispose();
|
||||
});
|
||||
|
||||
test('Has Icon', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block"/>'
|
||||
), this.workspace);
|
||||
block.setCommentText('test text');
|
||||
block.comment.setVisible(true);
|
||||
chai.assert.isTrue(block.comment.isVisible());
|
||||
block.setCollapsed(true);
|
||||
chai.assert.isFalse(block.comment.isVisible());
|
||||
});
|
||||
test('Child Has Icon', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block">' +
|
||||
' <statement name="STATEMENT">' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </statement>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
var childBlock = block.getInputTargetBlock('STATEMENT');
|
||||
childBlock.setCommentText('test text');
|
||||
childBlock.comment.setVisible(true);
|
||||
chai.assert.isTrue(childBlock.comment.isVisible());
|
||||
block.setCollapsed(true);
|
||||
chai.assert.isFalse(childBlock.comment.isVisible());
|
||||
});
|
||||
test('Next Block Has Icon', function() {
|
||||
var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
|
||||
'<block type="statement_block">' +
|
||||
' <next>' +
|
||||
' <block type="statement_block"/>' +
|
||||
' </next>' +
|
||||
'</block>'
|
||||
), this.workspace);
|
||||
var nextBlock = block.getNextBlock();
|
||||
nextBlock.setCommentText('test text');
|
||||
nextBlock.comment.setVisible(true);
|
||||
chai.assert.isTrue(nextBlock.comment.isVisible());
|
||||
block.setCollapsed(true);
|
||||
chai.assert.isTrue(nextBlock.comment.isVisible());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,299 +18,265 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Tests for connection DB.
|
||||
* @author samelh@google.com (Sam El-Husseini)
|
||||
*/
|
||||
'use strict';
|
||||
suite('Connection Database', function() {
|
||||
setup(function() {
|
||||
this.database = new Blockly.ConnectionDB();
|
||||
|
||||
suite('Connection DB', function() {
|
||||
|
||||
function verify_DB_(msg, expected, db) {
|
||||
var equal = (expected.length == db.connections_.length);
|
||||
if (equal) {
|
||||
for (var i = 0; i < expected.length; i++) {
|
||||
if (expected[i] != db.connections_[i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
this.assertOrder = function() {
|
||||
var length = this.database.connections_.length;
|
||||
for (var i = 1; i < length; i++) {
|
||||
chai.assert.isAtMost(this.database.connections_[i - 1].y_,
|
||||
this.database.connections_[i].y_);
|
||||
}
|
||||
};
|
||||
this.createConnection = function(x, y, type, opt_database) {
|
||||
var workspace = {
|
||||
connectionDBList: []
|
||||
};
|
||||
workspace.connectionDBList[type] = opt_database || this.database;
|
||||
var connection = new Blockly.RenderedConnection(
|
||||
{workspace: workspace}, type);
|
||||
connection.x_ = x;
|
||||
connection.y_ = y;
|
||||
return connection;
|
||||
};
|
||||
this.createSimpleTestConnections = function() {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var connection = this.createConnection(0, i, Blockly.PREVIOUS_STATEMENT);
|
||||
this.database.addConnection(connection, i);
|
||||
}
|
||||
}
|
||||
if (equal) {
|
||||
assertTrue(msg, true);
|
||||
} else {
|
||||
assertEquals(msg, expected, db.connections_);
|
||||
}
|
||||
}
|
||||
|
||||
function helper_createConnection(x, y, type, opt_shared_workspace,
|
||||
opt_rendered) {
|
||||
var workspace = opt_shared_workspace ? opt_shared_workspace : {};
|
||||
if (opt_rendered) {
|
||||
var conn = new Blockly.RenderedConnection({workspace: workspace}, type);
|
||||
} else {
|
||||
var conn = new Blockly.Connection({workspace: workspace}, type);
|
||||
}
|
||||
conn.x_ = x;
|
||||
conn.y_ = y;
|
||||
return conn;
|
||||
}
|
||||
|
||||
function helper_getNeighbours(db, x, y, radius) {
|
||||
return db.getNeighbours(helper_createConnection(x, y, Blockly.NEXT_STATEMENT,
|
||||
null, true), radius);
|
||||
}
|
||||
|
||||
function helper_makeSourceBlock(sharedWorkspace) {
|
||||
return {workspace: sharedWorkspace,
|
||||
parentBlock_: null,
|
||||
getParent: function() { return null; },
|
||||
movable_: true,
|
||||
isMovable: function() { return true; },
|
||||
isShadow: function() { return false; },
|
||||
isInsertionMarker: function() { return false; },
|
||||
getFirstStatementConnection: function() { return null; }
|
||||
};
|
||||
}
|
||||
|
||||
function helper_searchDB(db, x, y, radius, shared_workspace) {
|
||||
var tempConn = helper_createConnection(x, y,
|
||||
Blockly.NEXT_STATEMENT, shared_workspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(shared_workspace);
|
||||
tempConn.sourceBlock_.nextConnection = tempConn;
|
||||
var closest = db.searchForClosest(tempConn, radius, {x: 0, y: 0});
|
||||
return closest.connection;
|
||||
}
|
||||
|
||||
test('Add connection', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
var o2 = {y_: 2, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o2);
|
||||
verify_DB_('Adding connection #2', [o2], db);
|
||||
|
||||
var o4 = {y_: 4, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o4);
|
||||
verify_DB_('Adding connection #4', [o2, o4], db);
|
||||
|
||||
var o1 = {y_: 1, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o1);
|
||||
verify_DB_('Adding connection #1', [o1, o2, o4], db);
|
||||
|
||||
var o3a = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o3a);
|
||||
verify_DB_('Adding connection #3a', [o1, o2, o3a, o4], db);
|
||||
|
||||
var o3b = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o3b);
|
||||
verify_DB_('Adding connection #3b', [o1, o2, o3b, o3a, o4], db);
|
||||
});
|
||||
test('Remove connection', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
var o1 = {y_: 1, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o2 = {y_: 2, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o3a = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o3b = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o3c = {y_: 3, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
var o4 = {y_: 4, sourceBlock_: {},
|
||||
getSourceBlock: Blockly.Connection.prototype.getSourceBlock};
|
||||
db.addConnection(o1);
|
||||
db.addConnection(o2);
|
||||
db.addConnection(o3c);
|
||||
db.addConnection(o3b);
|
||||
db.addConnection(o3a);
|
||||
db.addConnection(o4);
|
||||
verify_DB_('Adding connections 1-4', [o1, o2, o3a, o3b, o3c, o4], db);
|
||||
// TODO: Re-enable once flyout checking is handled by the connection
|
||||
// (better yet - let it be handled by the flyout, but that's out of the
|
||||
// scope of this).
|
||||
test.skip('Add Connection', function() {
|
||||
var y2 = {y_: 2};
|
||||
var y4 = {y_: 4};
|
||||
var y1 = {y_: 1};
|
||||
var y3a = {y_: 3};
|
||||
var y3b = {y_: 3};
|
||||
|
||||
db.removeConnection_(o2);
|
||||
verify_DB_('Removing connection #2', [o1, o3a, o3b, o3c, o4], db);
|
||||
this.database.addConnection(y2, 2);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y2]);
|
||||
|
||||
db.removeConnection_(o4);
|
||||
verify_DB_('Removing connection #4', [o1, o3a, o3b, o3c], db);
|
||||
this.database.addConnection(y4, 4);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y2, y4]);
|
||||
|
||||
db.removeConnection_(o1);
|
||||
verify_DB_('Removing connection #1', [o3a, o3b, o3c], db);
|
||||
this.database.addConnection(y1, 1);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y1, y2, y4]);
|
||||
|
||||
db.removeConnection_(o3a);
|
||||
verify_DB_('Removing connection #3a', [o3b, o3c], db);
|
||||
this.database.addConnection(y3a, 3);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y1, y2, y3a, y4]);
|
||||
|
||||
db.removeConnection_(o3c);
|
||||
verify_DB_('Removing connection #3c', [o3b], db);
|
||||
this.database.addConnection(y3b, 3);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y1, y2, y3b, y3a, y4]);
|
||||
|
||||
db.removeConnection_(o3b);
|
||||
verify_DB_('Removing connection #3b', [], db);
|
||||
});
|
||||
test.skip('Remove Connection', function() {
|
||||
var y2 = {y_: 2};
|
||||
var y4 = {y_: 4};
|
||||
var y1 = {y_: 1};
|
||||
var y3a = {y_: 3};
|
||||
var y3b = {y_: 3};
|
||||
var y3c = {y_: 3};
|
||||
|
||||
test('get Neighbours', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
this.database.addConnection(y2, 2);
|
||||
this.database.addConnection(y4, 4);
|
||||
this.database.addConnection(y1, 1);
|
||||
this.database.addConnection(y3c, 3);
|
||||
this.database.addConnection(y3b, 3);
|
||||
this.database.addConnection(y3a, 3);
|
||||
|
||||
// Search an empty list.
|
||||
assertEquals(helper_getNeighbours(db,
|
||||
10 /* x */, 10 /* y */, 100 /* radius */).length, 0);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y1, y2, y3a, y3b, y3c, y4]);
|
||||
|
||||
// Set up some connections.
|
||||
for (var i = 0; i < 10; i++) {
|
||||
db.addConnection(helper_createConnection(0, i,
|
||||
Blockly.PREVIOUS_STATEMENT, null, true));
|
||||
}
|
||||
this.database.removeConnection(y2, 2);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y1, y3a, y3b, y3c, y4]);
|
||||
|
||||
// Test block belongs at beginning.
|
||||
var result = helper_getNeighbours(db, 0, 0, 4);
|
||||
assertEquals(5, result.length);
|
||||
for (i = 0; i < result.length; i++) {
|
||||
chai.assert.notEqual(result.indexOf(db.connections_[i]), -1); // contains
|
||||
}
|
||||
this.database.removeConnection(y4, 4);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y1, y3a, y3b, y3c]);
|
||||
|
||||
// Test block belongs at middle.
|
||||
result = helper_getNeighbours(db, 0, 4, 2);
|
||||
assertEquals(5, result.length);
|
||||
for (i = 0; i < result.length; i++) {
|
||||
chai.assert.notEqual(result.indexOf(db.connections_[i + 2]), -1); // contains
|
||||
}
|
||||
this.database.removeConnection(y1, 1);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y3a, y3b, y3c]);
|
||||
|
||||
// Test block belongs at end.
|
||||
result = helper_getNeighbours(db, 0, 9, 4);
|
||||
assertEquals(5, result.length);
|
||||
for (i = 0; i < result.length; i++) {
|
||||
chai.assert.notEqual(result.indexOf(db.connections_[i + 5]), -1); // contains
|
||||
}
|
||||
this.database.removeConnection(y3a, 3);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y3b, y3c]);
|
||||
|
||||
// Test block has no neighbours due to being out of range in the x direction.
|
||||
result = helper_getNeighbours(db, 10, 9, 4);
|
||||
assertEquals(result.length, 0);
|
||||
this.database.removeConnection(y3c, 3);
|
||||
chai.assert.sameOrderedMembers(
|
||||
this.database.connections_, [y3b]);
|
||||
|
||||
// Test block has no neighbours due to being out of range in the y direction.
|
||||
result = helper_getNeighbours(db, 0, 19, 4);
|
||||
assertEquals(result.length, 0);
|
||||
|
||||
// Test block has no neighbours due to being out of range diagonally.
|
||||
result = helper_getNeighbours(db, -2, -2, 2);
|
||||
assertEquals(result.length, 0);
|
||||
this.database.removeConnection(y3b, 3);
|
||||
chai.assert.isEmpty(this.database.connections_);
|
||||
});
|
||||
suite('Get Neighbors', function() {
|
||||
test('Empty Database', function() {
|
||||
var connection = this.createConnection(0, 0, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
chai.assert.isEmpty(this.database.getNeighbours(connection), 100);
|
||||
});
|
||||
test('Block At Top', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
test('Find position for connection', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
db.addConnection(helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 1, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 2, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 4, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
db.addConnection(helper_createConnection(0, 5, Blockly.PREVIOUS_STATEMENT,
|
||||
null, true));
|
||||
var checkConnection = this.createConnection(0, 0, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
var neighbors = this.database.getNeighbours(checkConnection, 4);
|
||||
chai.assert.sameMembers(neighbors, this.database.connections_.slice(0, 5));
|
||||
});
|
||||
test('Block In Middle', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
assertEquals(5, db.connections_.length);
|
||||
var conn = helper_createConnection(0, 3, Blockly.PREVIOUS_STATEMENT, null,
|
||||
true);
|
||||
assertEquals(3, db.findPositionForConnection_(conn));
|
||||
var checkConnection = this.createConnection(0, 4, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
var neighbors = this.database.getNeighbours(checkConnection, 2);
|
||||
chai.assert.sameMembers(neighbors, this.database.connections_.slice(2, 7));
|
||||
});
|
||||
test('Block At End', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
var checkConnection = this.createConnection(0, 9, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
var neighbors = this.database.getNeighbours(checkConnection, 4);
|
||||
chai.assert.sameMembers(neighbors, this.database.connections_.slice(5, 10));
|
||||
});
|
||||
test('Out of Range X', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
var checkConnection = this.createConnection(10, 9, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
var neighbors = this.database.getNeighbours(checkConnection, 4);
|
||||
chai.assert.isEmpty(neighbors);
|
||||
});
|
||||
test('Out of Range Y', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
var checkConnection = this.createConnection(0, 19, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
var neighbors = this.database.getNeighbours(checkConnection, 4);
|
||||
chai.assert.isEmpty(neighbors);
|
||||
});
|
||||
test('Out of Range Diagonal', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
var checkConnection = this.createConnection(-2, -2, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
var neighbors = this.database.getNeighbours(checkConnection, 2);
|
||||
chai.assert.isEmpty(neighbors);
|
||||
});
|
||||
});
|
||||
suite('Ordering', function() {
|
||||
test('Simple', function() {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var connection = this.createConnection(0, i, Blockly.NEXT_STATEMENT);
|
||||
this.database.addConnection(connection, i);
|
||||
}
|
||||
this.assertOrder();
|
||||
});
|
||||
test('Quasi-Random', function() {
|
||||
var xCoords = [-29, -47, -77, 2, 43, 34, -59, -52, -90, -36, -91, 38,
|
||||
87, -20, 60, 4, -57, 65, -37, -81, 57, 58, -96, 1, 67, -79, 34, 93,
|
||||
-90, -99, -62, 4, 11, -36, -51, -72, 3, -50, -24, -45, -92, -38, 37,
|
||||
24, -47, -73, 79, -20, 99, 43, -10, -87, 19, 35, -62, -36, 49, 86,
|
||||
-24, -47, -89, 33, -44, 25, -73, -91, 85, 6, 0, 89, -94, 36, -35, 84,
|
||||
-9, 96, -21, 52, 10, -95, 7, -67, -70, 62, 9, -40, -95, -9, -94, 55,
|
||||
57, -96, 55, 8, -48, -57, -87, 81, 23, 65];
|
||||
var yCoords = [-81, 82, 5, 47, 30, 57, -12, 28, 38, 92, -25, -20, 23,
|
||||
-51, 73, -90, 8, 28, -51, -15, 81, -60, -6, -16, 77, -62, -42, -24,
|
||||
35, 95, -46, -7, 61, -16, 14, 91, 57, -38, 27, -39, 92, 47, -98, 11,
|
||||
-33, -72, 64, 38, -64, -88, -35, -59, -76, -94, 45, -25, -100, -95,
|
||||
63, -97, 45, 98, 99, 34, 27, 52, -18, -45, 66, -32, -38, 70, -73,
|
||||
-23, 5, -2, -13, -9, 48, 74, -97, -11, 35, -79, -16, -77, 83, -57,
|
||||
-53, 35, -44, 100, -27, -15, 5, 39, 33, -19, -20, -95];
|
||||
|
||||
test('Find connection', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
db.addConnection(helper_createConnection(i, 0,
|
||||
Blockly.PREVIOUS_STATEMENT, null, true));
|
||||
db.addConnection(helper_createConnection(0, i,
|
||||
Blockly.PREVIOUS_STATEMENT, null, true));
|
||||
}
|
||||
|
||||
var conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null,
|
||||
true);
|
||||
db.addConnection(conn);
|
||||
assertEquals(conn, db.connections_[db.findConnection(conn)]);
|
||||
|
||||
conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT, null, true);
|
||||
assertEquals(-1, db.findConnection(conn));
|
||||
var length = xCoords.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var connection = this.createConnection(xCoords[i], yCoords[i],
|
||||
Blockly.NEXT_STATEMENT);
|
||||
this.database.addConnection(connection, yCoords[i]);
|
||||
}
|
||||
this.assertOrder();
|
||||
});
|
||||
});
|
||||
// Does not cover logic for isConnectionAllowed
|
||||
suite('Search For Closest', function() {
|
||||
setup(function() {
|
||||
this.allowedStub = null;
|
||||
|
||||
test('Ordering', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
db.addConnection(helper_createConnection(0, 9 - i,
|
||||
Blockly.PREVIOUS_STATEMENT), null, true);
|
||||
}
|
||||
this.createCheckConnection = function(x, y) {
|
||||
var checkConnection = this.createConnection(x, y, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
this.allowedStub = sinon.stub(checkConnection, 'isConnectionAllowed')
|
||||
.callsFake(function(candidate, maxRadius) {
|
||||
if (this.distanceFrom(candidate) > maxRadius) {
|
||||
return false;
|
||||
}
|
||||
// Ignore non-distance parameters.
|
||||
return true;
|
||||
});
|
||||
return checkConnection;
|
||||
};
|
||||
});
|
||||
teardown(function() {
|
||||
if (this.allowedStub) {
|
||||
this.allowedStub.restore();
|
||||
}
|
||||
});
|
||||
test('Empty Database', function() {
|
||||
var checkConnection = this.createConnection(0, 0, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
chai.assert.isNull(this.database.searchForClosest(
|
||||
checkConnection, 100, {x: 0, y: 0}).connection);
|
||||
});
|
||||
test('Too Far', function() {
|
||||
var connection = this.createConnection(0, 100, Blockly.PREVIOUS_STATEMENT);
|
||||
this.database.addConnection(connection, 100);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
assertEquals(i, db.connections_[i].y_);
|
||||
}
|
||||
var checkConnection = this.createConnection(0, 0, Blockly.NEXT_STATEMENT,
|
||||
new Blockly.ConnectionDB());
|
||||
chai.assert.isNull(this.database.searchForClosest(
|
||||
checkConnection, 50, {x: 0, y: 0}).connection);
|
||||
});
|
||||
test('Single in Range', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
// quasi-random
|
||||
var xCoords = [-29, -47, -77, 2, 43, 34, -59, -52, -90, -36, -91, 38, 87, -20,
|
||||
60, 4, -57, 65, -37, -81, 57, 58, -96, 1, 67, -79, 34, 93, -90, -99, -62,
|
||||
4, 11, -36, -51, -72, 3, -50, -24, -45, -92, -38, 37, 24, -47, -73, 79,
|
||||
-20, 99, 43, -10, -87, 19, 35, -62, -36, 49, 86, -24, -47, -89, 33, -44,
|
||||
25, -73, -91, 85, 6, 0, 89, -94, 36, -35, 84, -9, 96, -21, 52, 10, -95, 7,
|
||||
-67, -70, 62, 9, -40, -95, -9, -94, 55, 57, -96, 55, 8, -48, -57, -87, 81,
|
||||
23, 65];
|
||||
var yCoords = [-81, 82, 5, 47, 30, 57, -12, 28, 38, 92, -25, -20, 23, -51, 73,
|
||||
-90, 8, 28, -51, -15, 81, -60, -6, -16, 77, -62, -42, -24, 35, 95, -46,
|
||||
-7, 61, -16, 14, 91, 57, -38, 27, -39, 92, 47, -98, 11, -33, -72, 64, 38,
|
||||
-64, -88, -35, -59, -76, -94, 45, -25, -100, -95, 63, -97, 45, 98, 99, 34,
|
||||
27, 52, -18, -45, 66, -32, -38, 70, -73, -23, 5, -2, -13, -9, 48, 74, -97,
|
||||
-11, 35, -79, -16, -77, 83, -57, -53, 35, -44, 100, -27, -15, 5, 39, 33,
|
||||
-19, -20, -95];
|
||||
for (i = 0; i < xCoords.length; i++) {
|
||||
db.addConnection(helper_createConnection(xCoords[i], yCoords[i],
|
||||
Blockly.PREVIOUS_STATEMENT), null, true);
|
||||
}
|
||||
var checkConnection = this.createCheckConnection(0, 14);
|
||||
|
||||
for (i = 1; i < xCoords.length; i++) {
|
||||
assertTrue(db.connections_[i].y_ >= db.connections_[i - 1].y_);
|
||||
}
|
||||
var last = this.database.connections_[9];
|
||||
var closest = this.database.searchForClosest(
|
||||
checkConnection, 5, {x: 0, y: 0}).connection;
|
||||
chai.assert.equal(last, closest);
|
||||
});
|
||||
test('Many in Range', function() {
|
||||
this.createSimpleTestConnections();
|
||||
|
||||
var checkConnection = this.createCheckConnection(0, 10);
|
||||
|
||||
var last = this.database.connections_[9];
|
||||
var closest = this.database.searchForClosest(
|
||||
checkConnection, 5, {x: 0, y: 0}).connection;
|
||||
chai.assert.equal(last, closest);
|
||||
});
|
||||
test('No Y-Coord Priority', function() {
|
||||
var connection1 = this.createConnection(6, 6, Blockly.PREVIOUS_STATEMENT);
|
||||
this.database.addConnection(connection1, 6);
|
||||
var connection2 = this.createConnection(5, 5, Blockly.PREVIOUS_STATEMENT);
|
||||
this.database.addConnection(connection2, 5);
|
||||
|
||||
var checkConnection = this.createCheckConnection(4, 6);
|
||||
|
||||
var closest = this.database.searchForClosest(
|
||||
checkConnection, 3, {x: 0, y: 0}).connection;
|
||||
chai.assert.equal(connection2, closest);
|
||||
});
|
||||
});
|
||||
|
||||
test('Search for closest', function() {
|
||||
var db = new Blockly.ConnectionDB();
|
||||
var sharedWorkspace = {id: "Shared workspace"};
|
||||
|
||||
// Search an empty list.
|
||||
assertEquals(null, helper_searchDB(db, 10 /* x */, 10 /* y */,
|
||||
100 /* radius */));
|
||||
|
||||
db.addConnection(helper_createConnection(100, 0, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true));
|
||||
assertEquals(null, helper_searchDB(db, 0, 0, 5, sharedWorkspace));
|
||||
|
||||
db = new Blockly.ConnectionDB();
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var tempConn = helper_createConnection(0, i, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
db.addConnection(tempConn);
|
||||
}
|
||||
|
||||
// Should be at 0, 9.
|
||||
var last = db.connections_[db.connections_.length - 1];
|
||||
// Correct connection is last in db; many connections in radius.
|
||||
assertEquals(last, helper_searchDB(db, 0, 10, 15, sharedWorkspace));
|
||||
// Nothing nearby.
|
||||
assertEquals(null, helper_searchDB(db, 100, 100, 3, sharedWorkspace));
|
||||
// First in db, exact match.
|
||||
assertEquals(db.connections_[0], helper_searchDB(db, 0, 0, 0, sharedWorkspace));
|
||||
|
||||
tempConn = helper_createConnection(6, 6, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
db.addConnection(tempConn);
|
||||
tempConn = helper_createConnection(5, 5, Blockly.PREVIOUS_STATEMENT,
|
||||
sharedWorkspace, true);
|
||||
tempConn.sourceBlock_ = helper_makeSourceBlock(sharedWorkspace);
|
||||
db.addConnection(tempConn);
|
||||
|
||||
var result = helper_searchDB(db, 4, 6, 3, sharedWorkspace);
|
||||
assertEquals(5, result.x_);
|
||||
assertEquals(5, result.y_);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -18,323 +18,185 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
suite('Connections', function() {
|
||||
|
||||
suite.skip('Rendered', function() {
|
||||
function assertAllConnectionsHiddenState(block, hidden) {
|
||||
var connections = block.getConnections_(true);
|
||||
for (var i = 0; i < connections.length; i++) {
|
||||
var connection = connections[i];
|
||||
if (connection.type == Blockly.PREVIOUS_STATEMENT ||
|
||||
connection.type == Blockly.OUTPUT_VALUE) {
|
||||
// Only superior connections on inputs get hidden
|
||||
continue;
|
||||
}
|
||||
if (block.nextConnection && connection === block.nextConnection) {
|
||||
// The next connection is not hidden when collapsed
|
||||
continue;
|
||||
}
|
||||
assertEquals('Connection ' + i + ' failed', hidden, connections[i].hidden_);
|
||||
}
|
||||
}
|
||||
function assertAllConnectionsHidden(block) {
|
||||
assertAllConnectionsHiddenState(block, true);
|
||||
}
|
||||
function assertAllConnectionsVisible(block) {
|
||||
assertAllConnectionsHiddenState(block, false);
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "stack_block",
|
||||
"message0": "",
|
||||
"previousStatement": null,
|
||||
"nextStatement": null
|
||||
},
|
||||
{
|
||||
"type": "row_block",
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "INPUT"
|
||||
}
|
||||
],
|
||||
"output": null
|
||||
},
|
||||
{
|
||||
"type": "inputs_block",
|
||||
"message0": "%1 %2",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "INPUT"
|
||||
},
|
||||
{
|
||||
"type": "input_statement",
|
||||
"name": "STATEMENT"
|
||||
}
|
||||
],
|
||||
"previousStatement": null,
|
||||
"nextStatement": null
|
||||
},]);
|
||||
|
||||
var toolbox = document.getElementById('toolbox-connections');
|
||||
this.workspace = Blockly.inject('blocklyDiv', {toolbox: toolbox});
|
||||
// TODO: Re-enable once headless connections ignore databases.
|
||||
suite.skip('Connections', function() {
|
||||
suite('Can Connect With Reason', function() {
|
||||
test('Target Null', function() {
|
||||
var connection = new Blockly.Connection({}, Blockly.INPUT_VALUE);
|
||||
chai.assert.equal(connection.canConnectWithReason_(null),
|
||||
Blockly.Connection.REASON_TARGET_NULL);
|
||||
});
|
||||
test('Target Self', function() {
|
||||
var block = {workspace: 1};
|
||||
var connection1 = new Blockly.Connection(block, Blockly.INPUT_VALUE);
|
||||
var connection2 = new Blockly.Connection(block, Blockly.OUTPUT_VALUE);
|
||||
|
||||
teardown(function() {
|
||||
delete Blockly.Blocks['stack_block'];
|
||||
delete Blockly.Blocks['row_block'];
|
||||
delete Blockly.Blocks['inputs_block'];
|
||||
|
||||
this.workspace.dispose();
|
||||
chai.assert.equal(connection1.canConnectWithReason_(connection2),
|
||||
Blockly.Connection.REASON_SELF_CONNECTION);
|
||||
});
|
||||
test('Different Workspaces', function() {
|
||||
var connection1 = new Blockly.Connection(
|
||||
{workspace: 1}, Blockly.INPUT_VALUE);
|
||||
var connection2 = new Blockly.Connection(
|
||||
{workspace: 2}, Blockly.OUTPUT_VALUE);
|
||||
|
||||
suite('Row collapsing', function() {
|
||||
chai.assert.equal(connection1.canConnectWithReason_(connection2),
|
||||
Blockly.Connection.REASON_DIFFERENT_WORKSPACES);
|
||||
});
|
||||
suite('Types', function() {
|
||||
setup(function() {
|
||||
var blockA = this.workspace.newBlock('row_block');
|
||||
var blockB = this.workspace.newBlock('row_block');
|
||||
var blockC = this.workspace.newBlock('row_block');
|
||||
|
||||
blockA.inputList[0].connection.connect(blockB.outputConnection);
|
||||
blockA.setCollapsed(true);
|
||||
|
||||
assertEquals(blockA, blockB.getParent());
|
||||
assertNull(blockC.getParent());
|
||||
assertTrue(blockA.isCollapsed());
|
||||
assertAllConnectionsHidden(blockA);
|
||||
assertAllConnectionsHidden(blockB);
|
||||
assertAllConnectionsVisible(blockC);
|
||||
|
||||
this.blocks = {
|
||||
A: blockA,
|
||||
B: blockB,
|
||||
C: blockC
|
||||
};
|
||||
// We have to declare each separately so that the connections belong
|
||||
// on different blocks.
|
||||
var prevBlock = { isShadow: function() {}};
|
||||
var nextBlock = { isShadow: function() {}};
|
||||
var outBlock = { isShadow: function() {}};
|
||||
var inBlock = { isShadow: function() {}};
|
||||
this.previous = new Blockly.Connection(
|
||||
prevBlock, Blockly.PREVIOUS_STATEMENT);
|
||||
this.next = new Blockly.Connection(
|
||||
nextBlock, Blockly.NEXT_STATEMENT);
|
||||
this.output = new Blockly.Connection(
|
||||
outBlock, Blockly.OUTPUT_VALUE);
|
||||
this.input = new Blockly.Connection(
|
||||
inBlock, Blockly.INPUT_VALUE);
|
||||
});
|
||||
|
||||
test('Add to end', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.inputList[0].connection.connect(blocks.C.outputConnection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
test('Previous, Next', function() {
|
||||
chai.assert.equal(this.previous.canConnectWithReason_(this.next),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
|
||||
test('Add to end w/inferior', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.C.outputConnection.connect(blocks.B.inputList[0].connection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
test('Previous, Output', function() {
|
||||
chai.assert.equal(this.previous.canConnectWithReason_(this.output),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
|
||||
test('Add to middle', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.A.inputList[0].connection.connect(blocks.C.outputConnection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
test('Previous, Input', function() {
|
||||
chai.assert.equal(this.previous.canConnectWithReason_(this.input),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
|
||||
test('Add to middle w/inferior', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.C.outputConnection.connect(blocks.A.inputList[0].connection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
test('Next, Previous', function() {
|
||||
chai.assert.equal(this.next.canConnectWithReason_(this.previous),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
|
||||
test('Remove simple', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.unplug();
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
test('Next, Output', function() {
|
||||
chai.assert.equal(this.next.canConnectWithReason_(this.output),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
|
||||
test('Remove middle', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.inputList[0].connection.connect(blocks.C.outputConnection);
|
||||
blocks.B.unplug(false);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
test('Next, Input', function() {
|
||||
chai.assert.equal(this.next.canConnectWithReason_(this.input),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
|
||||
test('Remove middle healing', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.inputList[0].connection.connect(blocks.C.outputConnection);
|
||||
blocks.B.unplug(true);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
test('Output, Previous', function() {
|
||||
chai.assert.equal(this.output.canConnectWithReason_(this.previous),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
|
||||
test('Add before', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.C.inputList[0].connection.connect(blocks.A.outputConnection);
|
||||
// Connecting a collapsed block to another block doesn't change any hidden state
|
||||
assertAllConnectionsHidden(blocks.A);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
test('Output, Next', function() {
|
||||
chai.assert.equal(this.output.canConnectWithReason_(this.next),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
|
||||
test('Remove front', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.inputList[0].connection.connect(blocks.C.outputConnection);
|
||||
blocks.A.inputList[0].connection.disconnect();
|
||||
assertTrue(blocks.A.isCollapsed());
|
||||
assertAllConnectionsHidden(blocks.A);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
test('Output, Input', function() {
|
||||
chai.assert.equal(this.output.canConnectWithReason_(this.input),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
|
||||
test('Uncollapse', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.inputList[0].connection.connect(blocks.C.outputConnection);
|
||||
blocks.A.setCollapsed(false);
|
||||
assertFalse(blocks.A.isCollapsed());
|
||||
assertAllConnectionsVisible(blocks.A);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
test('Input, Previous', function() {
|
||||
chai.assert.equal(this.input.canConnectWithReason_(this.previous),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
test('Input, Next', function() {
|
||||
chai.assert.equal(this.input.canConnectWithReason_(this.next),
|
||||
Blockly.Connection.REASON_WRONG_TYPE);
|
||||
});
|
||||
test('Input, Output', function() {
|
||||
chai.assert.equal(this.input.canConnectWithReason_(this.output),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
});
|
||||
suite('Statement collapsing', function() {
|
||||
setup(function() {
|
||||
var blockA = this.workspace.newBlock('inputs_block');
|
||||
var blockB = this.workspace.newBlock('inputs_block');
|
||||
var blockC = this.workspace.newBlock('inputs_block');
|
||||
suite('Shadows', function() {
|
||||
test('Previous Shadow', function() {
|
||||
var prevBlock = { isShadow: function() { return true; }};
|
||||
var nextBlock = { isShadow: function() { return false; }};
|
||||
var prev = new Blockly.Connection(prevBlock, Blockly.PREVIOUS_STATEMENT);
|
||||
var next = new Blockly.Connection(nextBlock, Blockly.NEXT_STATEMENT);
|
||||
|
||||
blockA.getInput('STATEMENT').connection.connect(blockB.previousConnection);
|
||||
blockA.setCollapsed(true);
|
||||
|
||||
assertEquals(blockA, blockB.getParent());
|
||||
assertNull(blockC.getParent());
|
||||
assertTrue(blockA.isCollapsed());
|
||||
assertAllConnectionsHidden(blockA);
|
||||
assertAllConnectionsHidden(blockB);
|
||||
assertAllConnectionsVisible(blockC);
|
||||
|
||||
this.blocks = {
|
||||
A: blockA,
|
||||
B: blockB,
|
||||
C: blockC
|
||||
};
|
||||
chai.assert.equal(prev.canConnectWithReason_(next),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
test('Next Shadow', function() {
|
||||
var prevBlock = { isShadow: function() { return false; }};
|
||||
var nextBlock = { isShadow: function() { return true; }};
|
||||
var prev = new Blockly.Connection(prevBlock, Blockly.PREVIOUS_STATEMENT);
|
||||
var next = new Blockly.Connection(nextBlock, Blockly.NEXT_STATEMENT);
|
||||
|
||||
test('Add to statement', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.getInput('STATEMENT').connection.connect(blocks.C.previousConnection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
chai.assert.equal(prev.canConnectWithReason_(next),
|
||||
Blockly.Connection.REASON_SHADOW_PARENT);
|
||||
});
|
||||
test('Prev and Next Shadow', function() {
|
||||
var prevBlock = { isShadow: function() { return true; }};
|
||||
var nextBlock = { isShadow: function() { return true; }};
|
||||
var prev = new Blockly.Connection(prevBlock, Blockly.PREVIOUS_STATEMENT);
|
||||
var next = new Blockly.Connection(nextBlock, Blockly.NEXT_STATEMENT);
|
||||
|
||||
test('Insert in statement', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.A.getInput('STATEMENT').connection.connect(blocks.C.previousConnection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
chai.assert.equal(prev.canConnectWithReason_(next),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
test('Output Shadow', function() {
|
||||
var outBlock = { isShadow: function() { return true; }};
|
||||
var inBlock = { isShadow: function() { return false; }};
|
||||
var outCon = new Blockly.Connection(outBlock, Blockly.OUTPUT_VALUE);
|
||||
var inCon = new Blockly.Connection(inBlock, Blockly.INPUT_VALUE);
|
||||
|
||||
test('Add to hidden next', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.nextConnection.connect(blocks.C.previousConnection);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
chai.assert.equal(outCon.canConnectWithReason_(inCon),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
test('Input Shadow', function() {
|
||||
var outBlock = { isShadow: function() { return false; }};
|
||||
var inBlock = { isShadow: function() { return true; }};
|
||||
var outCon = new Blockly.Connection(outBlock, Blockly.OUTPUT_VALUE);
|
||||
var inCon = new Blockly.Connection(inBlock, Blockly.INPUT_VALUE);
|
||||
|
||||
test('Remove simple', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.unplug();
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
chai.assert.equal(outCon.canConnectWithReason_(inCon),
|
||||
Blockly.Connection.REASON_SHADOW_PARENT);
|
||||
});
|
||||
test('Output and Input Shadow', function() {
|
||||
var outBlock = { isShadow: function() { return true; }};
|
||||
var inBlock = { isShadow: function() { return true; }};
|
||||
var outCon = new Blockly.Connection(outBlock, Blockly.OUTPUT_VALUE);
|
||||
var inCon = new Blockly.Connection(inBlock, Blockly.INPUT_VALUE);
|
||||
|
||||
test('Remove middle', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.nextConnection.connect(blocks.C.previousConnection);
|
||||
blocks.B.unplug(false);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
});
|
||||
|
||||
test('Remove middle healing', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.nextConnection.connect(blocks.C.previousConnection);
|
||||
blocks.B.unplug(true);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsHidden(blocks.C);
|
||||
});
|
||||
|
||||
test('Add before', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.C.getInput('STATEMENT').connection.connect(blocks.A.previousConnection);
|
||||
assertAllConnectionsHidden(blocks.A);
|
||||
assertAllConnectionsHidden(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
});
|
||||
|
||||
test('Remove front', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.nextConnection.connect(blocks.C.previousConnection);
|
||||
blocks.A.getInput('STATEMENT').connection.disconnect();
|
||||
assertTrue(blocks.A.isCollapsed());
|
||||
assertAllConnectionsHidden(blocks.A);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
});
|
||||
|
||||
test('Uncollapse', function() {
|
||||
var blocks = this.blocks;
|
||||
blocks.B.nextConnection.connect(blocks.C.previousConnection);
|
||||
blocks.A.setCollapsed(false);
|
||||
assertFalse(blocks.A.isCollapsed());
|
||||
assertAllConnectionsVisible(blocks.A);
|
||||
assertAllConnectionsVisible(blocks.B);
|
||||
assertAllConnectionsVisible(blocks.C);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Collapsing with shadows', function() {
|
||||
setup(function() {
|
||||
var blockA = this.workspace.newBlock('inputs_block');
|
||||
var blockB = this.workspace.newBlock('inputs_block');
|
||||
var blockC = this.workspace.newBlock('inputs_block');
|
||||
var blockD = this.workspace.newBlock('row_block');
|
||||
|
||||
blockB.setShadow(true);
|
||||
var shadowStatement = Blockly.Xml.blockToDom(blockB, true /* noid */);
|
||||
blockB.setShadow(false);
|
||||
|
||||
blockD.setShadow(true);
|
||||
var shadowValue = Blockly.Xml.blockToDom(blockD, true /* noid */);
|
||||
blockD.setShadow(false);
|
||||
|
||||
var connection = blockA.getInput('STATEMENT').connection;
|
||||
connection.setShadowDom(shadowStatement);
|
||||
connection.connect(blockB.previousConnection);
|
||||
connection = blockA.getInput('INPUT').connection;
|
||||
connection.setShadowDom(shadowValue);
|
||||
connection.connect(blockD.outputConnection);
|
||||
blockA.setCollapsed(true);
|
||||
|
||||
assertEquals(blockA, blockB.getParent());
|
||||
assertNull(blockC.getParent());
|
||||
assertTrue(blockA.isCollapsed());
|
||||
assertAllConnectionsHidden(blockA);
|
||||
assertAllConnectionsHidden(blockB);
|
||||
assertAllConnectionsVisible(blockC);
|
||||
|
||||
this.blocks = {
|
||||
A: blockA,
|
||||
B: blockB,
|
||||
C: blockC,
|
||||
D: blockD
|
||||
};
|
||||
});
|
||||
|
||||
test('Reveal shadow statement', function() {
|
||||
var blocks = this.blocks;
|
||||
var connection = blocks.A.getInput('STATEMENT').connection;
|
||||
connection.disconnect();
|
||||
var shadowBlock = connection.targetBlock();
|
||||
assertTrue(shadowBlock.isShadow());
|
||||
assertAllConnectionsHidden(shadowBlock);
|
||||
});
|
||||
|
||||
test('Reveal shadow value', function() {
|
||||
var blocks = this.blocks;
|
||||
var connection = blocks.A.getInput('INPUT').connection;
|
||||
connection.disconnect();
|
||||
var shadowBlock = connection.targetBlock();
|
||||
assertTrue(shadowBlock.isShadow());
|
||||
assertAllConnectionsHidden(shadowBlock);
|
||||
chai.assert.equal(outCon.canConnectWithReason_(inCon),
|
||||
Blockly.Connection.CAN_CONNECT);
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('Check Types', function() {
|
||||
setup(function() {
|
||||
this.con1 = new Blockly.Connection({}, Blockly.PREVIOUS_STATEMENT);
|
||||
this.con2 = new Blockly.Connection({}, Blockly.NEXT_STATEMENT);
|
||||
});
|
||||
test('No Types', function() {
|
||||
chai.assert.isTrue(this.con1.checkType_(this.con2));
|
||||
});
|
||||
test('Same Type', function() {
|
||||
this.con1.setCheck('type1');
|
||||
this.con2.setCheck('type1');
|
||||
chai.assert.isTrue(this.con1.checkType_(this.con2));
|
||||
});
|
||||
test('Same Types', function() {
|
||||
this.con1.setCheck(['type1', 'type2']);
|
||||
this.con2.setCheck(['type1', 'type2']);
|
||||
chai.assert.isTrue(this.con1.checkType_(this.con2));
|
||||
});
|
||||
test('Single Same Type', function() {
|
||||
this.con1.setCheck(['type1', 'type2']);
|
||||
this.con2.setCheck(['type1', 'type3']);
|
||||
chai.assert.isTrue(this.con1.checkType_(this.con2));
|
||||
});
|
||||
test('One Typed, One Promiscuous', function() {
|
||||
this.con1.setCheck('type1');
|
||||
chai.assert.isTrue(this.con1.checkType_(this.con2));
|
||||
});
|
||||
test('No Compatible Types', function() {
|
||||
this.con1.setCheck('type1');
|
||||
this.con2.setCheck('type2');
|
||||
chai.assert.isFalse(this.con1.checkType_(this.con2));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<script src="comment_test.js"></script>
|
||||
<script src="connection_db_test.js"></script>
|
||||
<script src="connection_test.js"></script>
|
||||
<script src="connection_db_test.js"></script>
|
||||
<script src="cursor_test.js"></script>
|
||||
<script src="dropdowndiv_test.js"></script>
|
||||
<script src="event_test.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user