From fb0f1b05dd6fb0ac76655682a4de8450e5ca3364 Mon Sep 17 00:00:00 2001 From: Andrew n marshall Date: Fri, 20 Jan 2017 14:18:33 -0800 Subject: [PATCH] Unit tests for JSON block definitions (just the start) (#850) * Beginnings of a JSON block definition unit test set. * Dispose of unit test workspaces and blocks in finally blocks. * Clarify JSON error message by echoing arg notation. --- core/block.js | 6 +- tests/jsunit/extensions_test.js | 26 +++-- tests/jsunit/index.html | 1 + tests/jsunit/json_test.js | 172 ++++++++++++++++++++++++++++++++ tests/jsunit/workspace_test.js | 136 +++++++++++++++---------- tests/jsunit/xml_test.js | 4 +- 6 files changed, 280 insertions(+), 65 deletions(-) create mode 100644 tests/jsunit/json_test.js diff --git a/core/block.js b/core/block.js index d4ebc1ec5..bad026075 100644 --- a/core/block.js +++ b/core/block.js @@ -1026,7 +1026,7 @@ Blockly.Block.prototype.jsonInit = function(json) { } if (Array.isArray(json['extensions'])) { var extensionNames = json['extensions']; - for (var i = 0; i < extensionNames.length; ++i) { + for (var i = 0; i < extensionNames.length; ++i) { var extensionName = extensionNames[i]; Blockly.Extensions.apply(extensionName, this); } @@ -1052,9 +1052,9 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) { var token = tokens[i]; if (typeof token == 'number') { goog.asserts.assert(token > 0 && token <= args.length, - 'Message index "%s" out of range.', token); + 'Message index %%s out of range.', token); goog.asserts.assert(!indexDup[token], - 'Message index "%s" duplicated.', token); + 'Message index %%s duplicated.', token); indexDup[token] = true; indexCount++; elements.push(args[token - 1]); diff --git a/tests/jsunit/extensions_test.js b/tests/jsunit/extensions_test.js index 032c7c53b..caef7c992 100644 --- a/tests/jsunit/extensions_test.js +++ b/tests/jsunit/extensions_test.js @@ -25,6 +25,8 @@ 'use strict'; function test_extension() { + var workspace = new Blockly.Workspace(); + var block; try { assertUndefined(Blockly.Extensions.ALL_['extensions_test']); @@ -54,14 +56,16 @@ function test_extension() { assertEquals(0, numCallsToBefore); assertEquals(0, numCallsToAfter); - var workspace = new Blockly.Workspace(); - var block = new Blockly.Block(workspace, 'extension_test_block'); + block = new Blockly.Block(workspace, 'extension_test_block'); assertEquals(1, numCallsToBefore); assertEquals(1, numCallsToAfter); assert(block.extendedWithBefore); assert(block.extendedWithAfter); - } finally { + } finally { + block && block.dispose(); + workspace.dispose(); + delete Blockly.Extensions.ALL_['extensions_test_before']; delete Blockly.Extensions.ALL_['extensions_test_after']; delete Blockly.Blocks['extension_test_block']; @@ -69,6 +73,8 @@ function test_extension() { } function test_extension_missing() { + var workspace = new Blockly.Workspace(); + var block; var exceptionWasThrown = false; try { assertUndefined(Blockly.Extensions.ALL_['missing_extension']); @@ -78,12 +84,13 @@ function test_extension_missing() { "extensions": ["missing_extension"] }]); - var workspace = new Blockly.Workspace(); - var block = new Blockly.Block(workspace, 'missing_extension_block'); + block = new Blockly.Block(workspace, 'missing_extension_block'); } catch (e) { // Expected. exceptionWasThrown = true; } finally { + block && block.dispose(); + workspace.dispose(); delete Blockly.Blocks['missing_extension_block']; } assert(exceptionWasThrown); @@ -130,6 +137,9 @@ function test_extension_not_a_function() { function test_parent_tooltip_when_inline() { var defaultTooltip = "defaultTooltip"; var parentTooltip = "parentTooltip"; + + var workspace = new Blockly.Workspace(); + var block; try { Blockly.defineBlocksWithJsonArray([ { @@ -152,8 +162,7 @@ function test_parent_tooltip_when_inline() { } ]); - var workspace = new Blockly.Workspace(); - var block = new Blockly.Block(workspace, 'test_parent_tooltip_when_inline'); + block = new Blockly.Block(workspace, 'test_parent_tooltip_when_inline'); // Tooltip is dynamic after extension initialization. assert(goog.isFunction(block.tooltip)); @@ -178,6 +187,9 @@ function test_parent_tooltip_when_inline() { assert(!block.getParent()); assertEquals(block.tooltip(), defaultTooltip); } finally { + block && block.dispose(); + workspace.dispose(); + delete Blockly.Blocks['test_parent_tooltip_when_inline']; delete Blockly.Blocks['test_parent']; } diff --git a/tests/jsunit/index.html b/tests/jsunit/index.html index 887fb323e..71623d384 100644 --- a/tests/jsunit/index.html +++ b/tests/jsunit/index.html @@ -17,5 +17,6 @@ + diff --git a/tests/jsunit/json_test.js b/tests/jsunit/json_test.js new file mode 100644 index 000000000..fe0b47896 --- /dev/null +++ b/tests/jsunit/json_test.js @@ -0,0 +1,172 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2017 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'; + +/** Ensure a block can be instantiated from a JSON definition. */ +function test_json_minimal() { + var BLOCK_TYPE = 'test_json_minimal'; + + var workspace = new Blockly.Workspace(); + var block; + try { + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE + }]); + + block = new Blockly.Block(workspace, BLOCK_TYPE); + assertEquals(BLOCK_TYPE, block.type); + // TODO: asserts + } finally { + block.dispose(); + workspace.dispose(); + delete Blockly.Blocks[BLOCK_TYPE]; + } +} + +/** Ensure message0 creates an input. */ +function test_json_message0() { + var BLOCK_TYPE = 'test_json_message0'; + var MESSAGE0 = 'message0'; + + var workspace = new Blockly.Workspace(); + var block; + try { + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": MESSAGE0 + }]); + + block = new Blockly.Block(workspace, BLOCK_TYPE); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var textField = block.inputList[0].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE0, textField.getText()); + } finally { + block && block.dispose(); + workspace.dispose(); + delete Blockly.Blocks[BLOCK_TYPE]; + } +} + +/** Ensure message1 creates a new input. */ +function test_json_message1() { + var BLOCK_TYPE = 'test_json_message1'; + var MESSAGE0 = 'message0'; + var MESSAGE1 = 'message1'; + + var workspace = new Blockly.Workspace(); + var block; + try { + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": MESSAGE0, + "message1": MESSAGE1 + }]); + + block = new Blockly.Block(workspace, BLOCK_TYPE); + assertEquals(2, block.inputList.length); + + assertEquals(1, block.inputList[0].fieldRow.length); + var textField = block.inputList[0].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE0, textField.getText()); + + assertEquals(1, block.inputList[1].fieldRow.length); + var textField = block.inputList[1].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE1, textField.getText()); + } finally { + block && block.dispose(); + workspace.dispose(); + delete Blockly.Blocks[BLOCK_TYPE]; + } +} + +/** Ensure message string is dereferenced. */ +function test_json_message0_i18n() { + var BLOCK_TYPE = 'test_json_message0_i18n'; + var MESSAGE0 = '%{BKY_MESSAGE}'; + var MESSAGE = 'message'; + + Blockly.Msg['MESSAGE'] = MESSAGE; + + var workspace = new Blockly.Workspace(); + var block; + try { + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": MESSAGE0 + }]); + + block = new Blockly.Block(workspace, BLOCK_TYPE); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var textField = block.inputList[0].fieldRow[0]; + assertEquals(Blockly.FieldLabel, textField.constructor); + assertEquals(MESSAGE, textField.getText()); + } finally { + block && block.dispose(); // Disposes of textField, too. + workspace.dispose(); + delete Blockly.Blocks[BLOCK_TYPE]; + delete Blockly.Msg['MESSAGE']; + } +} + +function test_json_dropdown() { + var BLOCK_TYPE = 'test_json_dropdown'; + var FIELD_NAME = 'FIELD_NAME'; + var LABEL0 = 'LABEL0'; + var VALUE0 = 'VALUE0'; + var LABEL1 = 'LABEL1'; + var VALUE1 = 'VALUE1'; + + var workspace = new Blockly.Workspace(); + var block; + try { + Blockly.defineBlocksWithJsonArray([{ + "type": BLOCK_TYPE, + "message0": "%1", + "args0": [ + { + "type": "field_dropdown", + "name": FIELD_NAME, + "options": [ + [LABEL0, VALUE0], + [LABEL1, VALUE1] + ] + } + ] + }]); + + block = new Blockly.Block(workspace, BLOCK_TYPE); + assertEquals(1, block.inputList.length); + assertEquals(1, block.inputList[0].fieldRow.length); + var dropdown = block.inputList[0].fieldRow[0]; + assertEquals(dropdown, block.getField(FIELD_NAME)); + assertEquals(Blockly.FieldDropdown, dropdown.constructor); + assertEquals(VALUE0, dropdown.getValue()); + } finally { + block && block.dispose(); // Disposes of dropdown, too. + workspace.dispose(); + delete Blockly.Blocks[BLOCK_TYPE]; + } +} + diff --git a/tests/jsunit/workspace_test.js b/tests/jsunit/workspace_test.js index 87ff3bb98..5c4bed429 100644 --- a/tests/jsunit/workspace_test.js +++ b/tests/jsunit/workspace_test.js @@ -21,79 +21,107 @@ function test_emptyWorkspace() { var workspace = new Blockly.Workspace(); - assertEquals('Empty workspace (1).', 0, workspace.getTopBlocks(true).length); - assertEquals('Empty workspace (2).', 0, workspace.getTopBlocks(false).length); - assertEquals('Empty workspace (3).', 0, workspace.getAllBlocks().length); - workspace.clear(); - assertEquals('Empty workspace (4).', 0, workspace.getTopBlocks(true).length); - assertEquals('Empty workspace (5).', 0, workspace.getTopBlocks(false).length); - assertEquals('Empty workspace (6).', 0, workspace.getAllBlocks().length); + try { + assertEquals('Empty workspace (1).', 0, workspace.getTopBlocks(true).length); + assertEquals('Empty workspace (2).', 0, workspace.getTopBlocks(false).length); + assertEquals('Empty workspace (3).', 0, workspace.getAllBlocks().length); + workspace.clear(); + assertEquals('Empty workspace (4).', 0, workspace.getTopBlocks(true).length); + assertEquals('Empty workspace (5).', 0, workspace.getTopBlocks(false).length); + assertEquals('Empty workspace (6).', 0, workspace.getAllBlocks().length); + } finally { + workspace.dispose(); + } } function test_flatWorkspace() { var workspace = new Blockly.Workspace(); - var blockA = workspace.newBlock(''); - assertEquals('One block workspace (1).', 1, workspace.getTopBlocks(true).length); - assertEquals('One block workspace (2).', 1, workspace.getTopBlocks(false).length); - assertEquals('One block workspace (3).', 1, workspace.getAllBlocks().length); - var blockB = workspace.newBlock(''); - assertEquals('Two block workspace (1).', 2, workspace.getTopBlocks(true).length); - assertEquals('Two block workspace (2).', 2, workspace.getTopBlocks(false).length); - assertEquals('Two block workspace (3).', 2, workspace.getAllBlocks().length); - blockA.dispose(); - assertEquals('One block workspace (4).', 1, workspace.getTopBlocks(true).length); - assertEquals('One block workspace (5).', 1, workspace.getTopBlocks(false).length); - assertEquals('One block workspace (6).', 1, workspace.getAllBlocks().length); - workspace.clear(); - assertEquals('Cleared workspace (1).', 0, workspace.getTopBlocks(true).length); - assertEquals('Cleared workspace (2).', 0, workspace.getTopBlocks(false).length); - assertEquals('Cleared workspace (3).', 0, workspace.getAllBlocks().length); + var blockA, blockB; + try { + blockA = workspace.newBlock(''); + assertEquals('One block workspace (1).', 1, workspace.getTopBlocks(true).length); + assertEquals('One block workspace (2).', 1, workspace.getTopBlocks(false).length); + assertEquals('One block workspace (3).', 1, workspace.getAllBlocks().length); + blockB = workspace.newBlock(''); + assertEquals('Two block workspace (1).', 2, workspace.getTopBlocks(true).length); + assertEquals('Two block workspace (2).', 2, workspace.getTopBlocks(false).length); + assertEquals('Two block workspace (3).', 2, workspace.getAllBlocks().length); + blockA.dispose(); + assertEquals('One block workspace (4).', 1, workspace.getTopBlocks(true).length); + assertEquals('One block workspace (5).', 1, workspace.getTopBlocks(false).length); + assertEquals('One block workspace (6).', 1, workspace.getAllBlocks().length); + workspace.clear(); + assertEquals('Cleared workspace (1).', 0, workspace.getTopBlocks(true).length); + assertEquals('Cleared workspace (2).', 0, workspace.getTopBlocks(false).length); + assertEquals('Cleared workspace (3).', 0, workspace.getAllBlocks().length); + } finally { + blockB && blockB.dispose(); + blockA && blockA.dispose(); + workspace.dispose(); + } } function test_maxBlocksWorkspace() { var workspace = new Blockly.Workspace(); var blockA = workspace.newBlock(''); var blockB = workspace.newBlock(''); - assertEquals('Infinite capacity.', Infinity, workspace.remainingCapacity()); - workspace.options.maxBlocks = 3; - assertEquals('Three capacity.', 1, workspace.remainingCapacity()); - workspace.options.maxBlocks = 2; - assertEquals('Two capacity.', 0, workspace.remainingCapacity()); - workspace.options.maxBlocks = 1; - assertEquals('One capacity.', -1, workspace.remainingCapacity()); - workspace.options.maxBlocks = 0; - assertEquals('Zero capacity.', -2, workspace.remainingCapacity()); - workspace.clear(); - assertEquals('Cleared capacity.', 0, workspace.remainingCapacity()); + try { + assertEquals('Infinite capacity.', Infinity, workspace.remainingCapacity()); + workspace.options.maxBlocks = 3; + assertEquals('Three capacity.', 1, workspace.remainingCapacity()); + workspace.options.maxBlocks = 2; + assertEquals('Two capacity.', 0, workspace.remainingCapacity()); + workspace.options.maxBlocks = 1; + assertEquals('One capacity.', -1, workspace.remainingCapacity()); + workspace.options.maxBlocks = 0; + assertEquals('Zero capacity.', -2, workspace.remainingCapacity()); + workspace.clear(); + assertEquals('Cleared capacity.', 0, workspace.remainingCapacity()); + } finally { + blockB.dispose(); + blockA.dispose(); + workspace.dispose(); + } } function test_getWorkspaceById() { var workspaceA = new Blockly.Workspace(); var workspaceB = new Blockly.Workspace(); - assertEquals('Find workspaceA.', workspaceA, - Blockly.Workspace.getById(workspaceA.id)); - assertEquals('Find workspaceB.', workspaceB, - Blockly.Workspace.getById(workspaceB.id)); - assertEquals('No workspace found.', null, - Blockly.Workspace.getById('I do not exist.')); - workspaceA.dispose(); - assertEquals('Can\'t find workspaceA.', null, - Blockly.Workspace.getById(workspaceA.id)); - assertEquals('WorkspaceB exists.', workspaceB, - Blockly.Workspace.getById(workspaceB.id)); + try { + assertEquals('Find workspaceA.', workspaceA, + Blockly.Workspace.getById(workspaceA.id)); + assertEquals('Find workspaceB.', workspaceB, + Blockly.Workspace.getById(workspaceB.id)); + assertEquals('No workspace found.', null, + Blockly.Workspace.getById('I do not exist.')); + workspaceA.dispose(); + assertEquals('Can\'t find workspaceA.', null, + Blockly.Workspace.getById(workspaceA.id)); + assertEquals('WorkspaceB exists.', workspaceB, + Blockly.Workspace.getById(workspaceB.id)); + } finally { + workspaceB.dispose(); + workspaceA.dispose(); + } } function test_getBlockById() { var workspace = new Blockly.Workspace(); var blockA = workspace.newBlock(''); var blockB = workspace.newBlock(''); - assertEquals('Find blockA.', blockA, workspace.getBlockById(blockA.id)); - assertEquals('Find blockB.', blockB, workspace.getBlockById(blockB.id)); - assertEquals('No block found.', null, - workspace.getBlockById('I do not exist.')); - blockA.dispose(); - assertEquals('Can\'t find blockA.', null, workspace.getBlockById(blockA.id)); - assertEquals('BlockB exists.', blockB, workspace.getBlockById(blockB.id)); - workspace.clear(); - assertEquals('Can\'t find blockB.', null, workspace.getBlockById(blockB.id)); + try { + assertEquals('Find blockA.', blockA, workspace.getBlockById(blockA.id)); + assertEquals('Find blockB.', blockB, workspace.getBlockById(blockB.id)); + assertEquals('No block found.', null, + workspace.getBlockById('I do not exist.')); + blockA.dispose(); + assertEquals('Can\'t find blockA.', null, workspace.getBlockById(blockA.id)); + assertEquals('BlockB exists.', blockB, workspace.getBlockById(blockB.id)); + workspace.clear(); + assertEquals('Can\'t find blockB.', null, workspace.getBlockById(blockB.id)); + } finally { + blockB.dispose(); + blockA.dispose(); + workspace.dispose(); + } } diff --git a/tests/jsunit/xml_test.js b/tests/jsunit/xml_test.js index 25e2655ea..7365a850a 100644 --- a/tests/jsunit/xml_test.js +++ b/tests/jsunit/xml_test.js @@ -68,17 +68,19 @@ function test_domToWorkspace() { } }; + var workspace = new Blockly.Workspace(); try { var dom = Blockly.Xml.textToDom( '' + ' ' + ' ' + ''); - var workspace = new Blockly.Workspace(); Blockly.Xml.domToWorkspace(dom, workspace); assertEquals('Block count', 1, workspace.getAllBlocks().length); } finally { delete Blockly.Blocks.test_block; + + workspace.dispose(); } }