diff --git a/tests/blocks/index.html b/tests/blocks/index.html
deleted file mode 100644
index 3187af9d2..000000000
--- a/tests/blocks/index.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
- Unit Tests for Blockly Blocks
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/blocks/logic_ternary_test.js b/tests/blocks/logic_ternary_test.js
deleted file mode 100644
index 81142c349..000000000
--- a/tests/blocks/logic_ternary_test.js
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- * @license
- * Copyright 2017 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-'use strict';
-
-function test_logic_ternary_structure() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- assertEquals(3, block.inputList && block.inputList.length);
- assertEquals(1, block.getInput('IF').connection.check_.length);
- assertEquals('Boolean', block.getInput('IF').connection.check_[0]);
- assertTrue(!!block.onchangeWrapper_); // Has onchange handler
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachSameTypeCheckInThenAndElseWithoutParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
-
- var string1 = workspace.newBlock('text');
- var string2 = workspace.newBlock('text_charAt');
-
- block.getInput('THEN').connection.connect(string1.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string1.getRootBlock());
- block.getInput('ELSE').connection.connect(string2.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string1.getRootBlock()); // Still connected.
- assertEquals(block, string2.getRootBlock());
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachDifferectTypeChecksInThenAndElseWithoutParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
-
- var string = workspace.newBlock('text');
- var number = workspace.newBlock('math_number');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock());
- block.getInput('ELSE').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock()); // Input THEN still connected.
- assertEquals(block, number.getRootBlock());
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachSameTypeCheckInThenAndElseWithMatchingParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var parent = workspace.newBlock('text_trim');
-
- parent.getInput('TEXT').connection.connect(block.outputConnection);
- assertEquals(parent, block.getRootBlock());
-
- var string1 = workspace.newBlock('text');
- var string2 = workspace.newBlock('text_charAt');
-
- block.getInput('THEN').connection.connect(string1.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string1.getRootBlock());
- block.getInput('ELSE').connection.connect(string2.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string1.getRootBlock()); // Input THEN still connected.
- assertEquals(parent, string2.getRootBlock());
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachDifferectTypeChecksInThenAndElseWithUncheckedParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var parent = workspace.newBlock('text_print');
-
- parent.getInput('TEXT').connection.connect(block.outputConnection);
- assertEquals(parent, block.parentBlock_);
-
- var string = workspace.newBlock('text');
- var number = workspace.newBlock('math_number');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string.getRootBlock());
- block.getInput('ELSE').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string.getRootBlock()); // Input THEN still connected.
- assertEquals(parent, number.getRootBlock());
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachDifferectTypeChecksInThenAndElseWithPermissiveParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var parent = workspace.newBlock('text_length'); // Allows String or Array
-
- parent.getInput('VALUE').connection.connect(block.outputConnection);
- assertEquals(parent, block.parentBlock_);
-
- var string = workspace.newBlock('text');
- var array = workspace.newBlock('lists_create_empty');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string.getRootBlock());
- block.getInput('ELSE').connection.connect(array.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string.getRootBlock()); // Input THEN still connected.
- assertEquals(parent, array.getRootBlock());
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachMismatchTypeToThen_breakWithParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var parent = workspace.newBlock('text_length'); // Allows String or Array
-
- parent.getInput('VALUE').connection.connect(block.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.parentBlock_);
-
- var string = workspace.newBlock('text');
- var number = workspace.newBlock('math_number');
-
- block.getInput('ELSE').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string.getRootBlock());
-
- // Adding mismatching number.
- block.getInput('THEN').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, block.getRootBlock()); // Disconnected from parent.
- assertEquals(block, number.getRootBlock());
- assertEquals(block, string.getRootBlock()); // ELSE string still connected.
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachMismatchTypeToElse_breakWithParent() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var parent = workspace.newBlock('text_length'); // Allows String or Array
-
- parent.getInput('VALUE').connection.connect(block.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.parentBlock_);
-
- var string = workspace.newBlock('text');
- var number = workspace.newBlock('math_number');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Still connected to parent.
- assertEquals(parent, string.getRootBlock());
-
- // Adding mismatching number.
- block.getInput('ELSE').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, block.getRootBlock()); // Disconnected from parent.
- assertEquals(block, number.getRootBlock());
- assertEquals(block, string.getRootBlock()); // THEN string still connected.
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachToUncheckedParentWithDifferentTypes() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var string = workspace.newBlock('text');
- var number = workspace.newBlock('math_number');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock());
- block.getInput('ELSE').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock()); // Input THEN still connected.
- assertEquals(block, number.getRootBlock());
-
- // Attaching to parent.
- var parent = workspace.newBlock('text_print');
- parent.getInput('TEXT').connection.connect(block.outputConnection);
- assertEquals(parent, block.getRootBlock());
- assertEquals(parent, string.getRootBlock()); // Input THEN still connected.
- assertEquals(parent, number.getRootBlock()); // Input ELSE still connected.
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachToPermissiveParentWithDifferentTypes() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var string = workspace.newBlock('text');
- var array = workspace.newBlock('lists_create_empty');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock());
- block.getInput('ELSE').connection.connect(array.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock()); // Input THEN still connected.
- assertEquals(block, array.getRootBlock());
-
- // Attaching to parent.
- var parent = workspace.newBlock('text_print');
- parent.getInput('TEXT').connection.connect(block.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock());
- assertEquals(parent, string.getRootBlock()); // Input THEN still connected.
- assertEquals(parent, array.getRootBlock()); // Input ELSE still connected.
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachToParentWithMismatchingThen_disconnectThen() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var number = workspace.newBlock('math_number');
- var string = workspace.newBlock('text');
-
- block.getInput('THEN').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, number.getRootBlock());
- block.getInput('ELSE').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, number.getRootBlock()); // Input THEN still connected.
- assertEquals(block, string.getRootBlock());
-
- // Attaching to parent.
- var parent = workspace.newBlock('text_trim');
- parent.getInput('TEXT').connection.connect(block.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Successful connection to parent.
- assertEquals(parent, string.getRootBlock()); // Input ELSE still connected.
- assertEquals(number, number.getRootBlock()); // Input THEN disconnected.
- } finally {
- workspace.dispose();
- }
-}
-
-function test_logic_ternary_attachToParentWithMismatchingElse_disconnectElse() {
- var workspace = new Blockly.Workspace();
- try {
- var block = workspace.newBlock('logic_ternary');
- var string = workspace.newBlock('text');
- var number = workspace.newBlock('math_number');
-
- block.getInput('THEN').connection.connect(string.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock());
- block.getInput('ELSE').connection.connect(number.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(block, string.getRootBlock()); // Input THEN still connected.
- assertEquals(block, number.getRootBlock());
-
- // Attaching to parent.
- var parent = workspace.newBlock('text_trim');
- parent.getInput('TEXT').connection.connect(block.outputConnection);
- Blockly.Events.fireNow_(); // Force synchronous onchange() call.
- assertEquals(parent, block.getRootBlock()); // Successful connection to parent.
- assertEquals(parent, string.getRootBlock()); // Input THEN still connected.
- assertEquals(number, number.getRootBlock()); // Input ELSE disconnected.
- } finally {
- workspace.dispose();
- }
-}
diff --git a/tests/mocha/index.html b/tests/mocha/index.html
index ff94913bb..75869ca30 100644
--- a/tests/mocha/index.html
+++ b/tests/mocha/index.html
@@ -12,8 +12,11 @@
-
+
+
+
+
@@ -58,6 +61,7 @@
+
diff --git a/tests/mocha/logic_ternary_test.js b/tests/mocha/logic_ternary_test.js
new file mode 100644
index 000000000..e94598e69
--- /dev/null
+++ b/tests/mocha/logic_ternary_test.js
@@ -0,0 +1,194 @@
+/**
+ * @license
+ * Copyright 2020 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+suite('Logic ternary', function() {
+ setup(function() {
+ this.workspace = new Blockly.Workspace();
+ this.block = this.workspace.newBlock('logic_ternary');
+ });
+
+ teardown(function() {
+ this.workspace.dispose();
+ });
+
+ test('Structure', function() {
+ chai.assert.exists(this.block.inputList, 'Has inputList');
+ chai.assert.equal(this.block.inputList.length, 3);
+ chai.assert.equal(this.block.getInput('IF').connection.check_.length, 1);
+ chai.assert.equal(this.block.getInput('IF').connection.check_[0], 'Boolean');
+ chai.assert.exists(this.block.onchangeWrapper_, 'Has onchange handler');
+ });
+
+ function connectParentAndCheckConnections(
+ block, parent, parentInputName, opt_thenInput, opt_elseInput) {
+ parent.getInput(parentInputName).connection.connect(block.outputConnection);
+ Blockly.Events.fireNow_(); // Force synchronous onchange() call.
+ chai.assert.equal(block.getParent(), parent,
+ 'Successful connection to parent');
+ if (opt_thenInput) {
+ chai.assert.equal(opt_thenInput.getParent(), block,
+ 'Input THEN still connected after connecting parent');
+ }
+ if (opt_elseInput) {
+ chai.assert.equal(opt_elseInput.getParent(), block,
+ 'Input ELSE still connected after connecting parent');
+ }
+ }
+ function connectThenInputAndCheckConnections(
+ block, thenInput, opt_elseInput, opt_parent) {
+ block.getInput('THEN').connection.connect(thenInput.outputConnection);
+ Blockly.Events.fireNow_(); // Force synchronous onchange() call.
+ chai.assert.equal(thenInput.getParent(), block, 'THEN is connected');
+ if (opt_parent) {
+ chai.assert.equal(block.getParent(), opt_parent,
+ 'Still connected to parent after connecting THEN');
+ }
+ if (opt_elseInput) {
+ chai.assert.equal(opt_elseInput.getParent(), block,
+ 'Input ELSE still connected after connecting THEN');
+ }
+ }
+ function connectElseInputAndCheckConnections(
+ block, elseInput, opt_thenInput, opt_parent) {
+ block.getInput('ELSE').connection.connect(elseInput.outputConnection);
+ Blockly.Events.fireNow_(); // Force synchronous onchange() call.
+ chai.assert.equal(elseInput.getParent(), block, 'ELSE is connected');
+ if (opt_parent) {
+ chai.assert.equal(block.getParent(), opt_parent,
+ 'Still connected to parent after connecting ELSE');
+ }
+ if (opt_thenInput) {
+ chai.assert.equal(opt_thenInput.getParent(), block,
+ 'Input THEN still connected after connecting ELSE');
+ }
+ }
+ function connectInputsAndCheckConnections(
+ block, thenInput, elseInput, opt_parent) {
+ connectThenInputAndCheckConnections(block, thenInput, null, opt_parent);
+ connectElseInputAndCheckConnections(block, elseInput, thenInput, opt_parent);
+ }
+ suite('No parent', function() {
+ test('Attach inputs same type', function() {
+ var string1 = this.workspace.newBlock('text');
+ var string2 = this.workspace.newBlock('text_charAt');
+
+ connectInputsAndCheckConnections(this.block, string1, string2);
+ });
+ test('Attach inputs different types', function() {
+ var string = this.workspace.newBlock('text');
+ var number = this.workspace.newBlock('math_number');
+
+ connectInputsAndCheckConnections(this.block, string, number);
+ });
+ });
+ suite('With parent already attached', function() {
+ test('Attach inputs same type with matching parent', function() {
+ var parent = this.workspace.newBlock('text_trim');
+
+ connectParentAndCheckConnections(this.block, parent, 'TEXT');
+
+ var string1 = this.workspace.newBlock('text');
+ var string2 = this.workspace.newBlock('text_charAt');
+
+ connectInputsAndCheckConnections(this.block, string1, string2, parent);
+ });
+ test('Attach inputs different types with unchecked parent', function() {
+ var parent = this.workspace.newBlock('text_print');
+
+ connectParentAndCheckConnections(this.block, parent, 'TEXT');
+
+ var string = this.workspace.newBlock('text');
+ var number = this.workspace.newBlock('math_number');
+
+ connectInputsAndCheckConnections(this.block, string, number, parent);
+ });
+ test('Attach inputs different types with permissive parent', function() {
+ var parent = this.workspace.newBlock('text_length'); // Allows String or Array
+
+ connectParentAndCheckConnections(this.block, parent, 'VALUE');
+
+ var string = this.workspace.newBlock('text');
+ var array = this.workspace.newBlock('lists_create_empty');
+
+ connectInputsAndCheckConnections(this.block, string, array, parent);
+ });
+ test('Attach mismatch type to then causes break with parent', function() {
+ var parent = this.workspace.newBlock('text_length'); // Allows String or Array
+
+ connectParentAndCheckConnections(this.block, parent, 'VALUE');
+
+ var string = this.workspace.newBlock('text');
+ var number = this.workspace.newBlock('math_number');
+
+ connectElseInputAndCheckConnections(this.block, string, null, parent);
+
+ // Adding mismatching number.
+ connectThenInputAndCheckConnections(this.block, number, string);
+ chai.assert.equal(this.block.getRootBlock(), this.block,
+ 'Disconnected from parent');
+ });
+ test('Attach mismatch type to else causes break with parent', function() {
+ var parent = this.workspace.newBlock('text_length'); // Allows String or Array
+
+ connectParentAndCheckConnections(this.block, parent, 'VALUE');
+
+ var string = this.workspace.newBlock('text');
+ var number = this.workspace.newBlock('math_number');
+
+ connectThenInputAndCheckConnections(this.block, string, null, parent);
+
+ // Adding mismatching number.
+ connectElseInputAndCheckConnections(this.block, number, string);
+ chai.assert.equal(this.block.getRootBlock(), this.block,
+ 'Disconnected from parent');
+ });
+ });
+ suite('Attaching parent after inputs', function() {
+ test('Unchecked parent with inputs different types', function() {
+ var string = this.workspace.newBlock('text');
+ var number = this.workspace.newBlock('math_number');
+
+ connectInputsAndCheckConnections(this.block, string, number);
+
+ var parent = this.workspace.newBlock('text_print');
+ connectParentAndCheckConnections(
+ this.block, parent, 'TEXT', string, number);
+ });
+ test('Permissive parent with inputs different types', function() {
+ var string = this.workspace.newBlock('text');
+ var array = this.workspace.newBlock('lists_create_empty');
+
+ connectInputsAndCheckConnections(this.block, string, array);
+
+ var parent = this.workspace.newBlock('text_print');
+ connectParentAndCheckConnections(
+ this.block, parent, 'TEXT', string, array);
+ });
+ test('Mismatch with then causes break with then', function() {
+ var number = this.workspace.newBlock('math_number');
+ var string = this.workspace.newBlock('text');
+
+ connectInputsAndCheckConnections(this.block, number, string);
+
+ var parent = this.workspace.newBlock('text_trim');
+ connectParentAndCheckConnections(
+ this.block, parent, 'TEXT', null, string);
+ chai.assert.equal(number.getRootBlock(), number,
+ 'Input THEN disconnected');
+ });
+ test('Mismatch with else causes break with else', function() {
+ var string = this.workspace.newBlock('text');
+ var number = this.workspace.newBlock('math_number');
+
+ connectInputsAndCheckConnections(this.block, string, number);
+
+ var parent = this.workspace.newBlock('text_trim');
+ connectParentAndCheckConnections(this.block, parent, 'TEXT', string);
+ chai.assert.equal(number.getRootBlock(), number,
+ 'Input ELSE disconnected');
+ });
+ });
+});