diff --git a/core/connection.js b/core/connection.js index afabedec5..13a3f6c6a 100644 --- a/core/connection.js +++ b/core/connection.js @@ -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} 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). */ diff --git a/core/input.js b/core/input.js index 4409237db..2ad195d94 100644 --- a/core/input.js +++ b/core/input.js @@ -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; diff --git a/tests/jsunit/connection_db_test.js b/tests/jsunit/connection_db_test.js deleted file mode 100644 index b7e087558..000000000 --- a/tests/jsunit/connection_db_test.js +++ /dev/null @@ -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; -} diff --git a/tests/jsunit/connection_test.js b/tests/jsunit/connection_test.js deleted file mode 100644 index 1f7e5cdab..000000000 --- a/tests/jsunit/connection_test.js +++ /dev/null @@ -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(); -} diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 7510fd7eb..ab42cf45a 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -18,8 +18,6 @@ - - diff --git a/tests/mocha/block_test.js b/tests/mocha/block_test.js index e76ce17c1..927d91445 100644 --- a/tests/mocha/block_test.js +++ b/tests/mocha/block_test.js @@ -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( + '' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '' + ), 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() { '' ), 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( + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + '' + ), 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( + '' + + ' ' + + ' ' + + ' ' + + '' + ), 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()); + }); + }); + }); }); diff --git a/tests/mocha/connection_db_test.js b/tests/mocha/connection_db_test.js index 459e1bcea..1e2639a8e 100644 --- a/tests/mocha/connection_db_test.js +++ b/tests/mocha/connection_db_test.js @@ -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_); - }); - }); diff --git a/tests/mocha/connection_test.js b/tests/mocha/connection_test.js index fb239ee33..4f84e8ff4 100644 --- a/tests/mocha/connection_test.js +++ b/tests/mocha/connection_test.js @@ -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)); + }); + }); }); diff --git a/tests/mocha/index.html b/tests/mocha/index.html index e6a9ca37f..f535ba2e1 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -29,6 +29,7 @@ +