mirror of
https://github.com/google/blockly.git
synced 2026-01-09 01:50:11 +01:00
Converting extensions_test to mocha. (#3820)
* Converting extensions_test to mocha. * Add spacing between test cases. * Fix cleanup for block type. * Add cleanup for event state.
This commit is contained in:
@@ -1,643 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Tests for Blockly.Extensions
|
||||
* @author Anm@anm.me (Andrew n marshall)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
function test_extension() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test']);
|
||||
|
||||
var numCallsToBefore = 0;
|
||||
var numCallsToAfter = 0;
|
||||
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.register('extensions_test_before', function () {
|
||||
numCallsToBefore++;
|
||||
this.extendedWithBefore = true;
|
||||
});
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "extension_test_block",
|
||||
"message0": "extension_test_block",
|
||||
"extensions": ["extensions_test_before", "extensions_test_after"]
|
||||
}]);
|
||||
|
||||
// Extension defined after the block type (but before instantiation).
|
||||
Blockly.Extensions.register('extensions_test_after', function () {
|
||||
numCallsToAfter++;
|
||||
this.extendedWithAfter = true;
|
||||
});
|
||||
|
||||
assert(typeof Blockly.Extensions.ALL_['extensions_test_before'] == 'function');
|
||||
assert(typeof Blockly.Extensions.ALL_['extensions_test_after'] == 'function');
|
||||
assertEquals(0, numCallsToBefore);
|
||||
assertEquals(0, numCallsToAfter);
|
||||
|
||||
block = new Blockly.Block(workspace, 'extension_test_block');
|
||||
|
||||
assertEquals(1, numCallsToBefore);
|
||||
assertEquals(1, numCallsToAfter);
|
||||
assert(block.extendedWithBefore);
|
||||
assert(block.extendedWithAfter);
|
||||
} 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'];
|
||||
}
|
||||
}
|
||||
|
||||
function test_extension_missing() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['missing_extension']);
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "missing_extension_block",
|
||||
"message0": "missing_extension_block",
|
||||
"extensions": ["missing_extension"]
|
||||
}]);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
function test_extension_not_a_function() {
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['extension_just_a_string']);
|
||||
Blockly.Extensions.register('extension_just_a_string', 'extension_just_a_string');
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['extension_just_a_string'];
|
||||
}
|
||||
assert(exceptionWasThrown);
|
||||
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['extension_is_null']);
|
||||
Blockly.Extensions.register('extension_is_null', null);
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['extension_is_null'];
|
||||
}
|
||||
assert(exceptionWasThrown);
|
||||
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['extension_is_undefined']);
|
||||
Blockly.Extensions.register('extension_is_undefined');
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['extension_is_undefined'];
|
||||
}
|
||||
assert(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_parent_tooltip_when_inline() {
|
||||
var defaultTooltip = "defaultTooltip";
|
||||
var parentTooltip = "parentTooltip";
|
||||
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
"type": "test_parent_tooltip_when_inline",
|
||||
"message0": "test_parent_tooltip_when_inline",
|
||||
"output": true,
|
||||
"tooltip": defaultTooltip,
|
||||
"extensions": ["parent_tooltip_when_inline"]
|
||||
},
|
||||
{
|
||||
"type": "test_parent",
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "INPUT"
|
||||
}
|
||||
],
|
||||
"tooltip": parentTooltip
|
||||
}
|
||||
]);
|
||||
|
||||
block = new Blockly.Block(workspace, 'test_parent_tooltip_when_inline');
|
||||
|
||||
// Tooltip is dynamic after extension initialization.
|
||||
assert(typeof block.tooltip == 'function');
|
||||
assertEquals(block.tooltip(), defaultTooltip);
|
||||
|
||||
// Tooltip is normal before connected to parent.
|
||||
var parent = new Blockly.Block(workspace, 'test_parent');
|
||||
assertEquals(parent.tooltip, parentTooltip);
|
||||
assertFalse(!!parent.inputsInline);
|
||||
|
||||
// Tooltip is normal when parent is not inline.
|
||||
parent.getInput('INPUT').connection.connect(block.outputConnection);
|
||||
assertEquals(block.getParent(), parent);
|
||||
assertEquals(block.tooltip(), defaultTooltip);
|
||||
|
||||
// Tooltip is parent's when parent is inline.
|
||||
parent.setInputsInline(true);
|
||||
assertEquals(block.tooltip(), parentTooltip);
|
||||
|
||||
// Tooltip revert when disconnected.
|
||||
parent.getInput('INPUT').connection.disconnect();
|
||||
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'];
|
||||
}
|
||||
}
|
||||
|
||||
function test_mixin_extension() {
|
||||
var TEST_MIXIN = {
|
||||
field: 'FIELD',
|
||||
method: function() {
|
||||
console.log('TEXT_MIXIN method()');
|
||||
}
|
||||
};
|
||||
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['mixin_test']);
|
||||
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.registerMixin('mixin_test', TEST_MIXIN);
|
||||
assert(typeof Blockly.Extensions.ALL_['mixin_test'] == 'function');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "test_block_mixin",
|
||||
"message0": "test_block_mixin",
|
||||
"extensions": ["mixin_test"]
|
||||
}]);
|
||||
|
||||
block = new Blockly.Block(workspace, 'test_block_mixin');
|
||||
|
||||
assertEquals(TEST_MIXIN.field, block.field);
|
||||
assertEquals(TEST_MIXIN.method, block.method);
|
||||
} finally {
|
||||
block && block.dispose();
|
||||
workspace.dispose();
|
||||
|
||||
delete Blockly.Extensions.ALL_['mixin_test'];
|
||||
delete Blockly.Blocks['test_block_mixin'];
|
||||
}
|
||||
}
|
||||
|
||||
function test_bad_mixin_overwrites_local_value() {
|
||||
var TEST_MIXIN_BAD_INPUTLIST = {
|
||||
inputList: 'bad inputList' // Defined in constructor
|
||||
};
|
||||
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['mixin_bad_inputList']);
|
||||
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.registerMixin('mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST);
|
||||
assert(typeof Blockly.Extensions.ALL_['mixin_bad_inputList'] == 'function');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "test_block_bad_inputList",
|
||||
"message0": "test_block_bad_inputList",
|
||||
"extensions": ["mixin_bad_inputList"]
|
||||
}]);
|
||||
|
||||
try {
|
||||
block = new Blockly.Block(workspace, 'test_block_bad_inputList');
|
||||
} catch (e) {
|
||||
// Expected Error
|
||||
assert(e.message.indexOf('inputList') >= 0); // Reference the conflict
|
||||
return;
|
||||
}
|
||||
fail('Expected error when constructing block');
|
||||
} finally {
|
||||
block && block.dispose();
|
||||
workspace.dispose();
|
||||
|
||||
delete Blockly.Extensions.ALL_['mixin_bad_inputList'];
|
||||
delete Blockly.Blocks['test_block_bad_inputList'];
|
||||
}
|
||||
}
|
||||
|
||||
function test_bad_mixin_overwrites_prototype() {
|
||||
var TEST_MIXIN_BAD_COLOUR = {
|
||||
colour_: 'bad colour_' // Defined on prototype
|
||||
};
|
||||
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
try {
|
||||
assertUndefined(Blockly.Extensions.ALL_['mixin_bad_colour_']);
|
||||
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.registerMixin('mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR);
|
||||
assert(typeof Blockly.Extensions.ALL_['mixin_bad_colour_'] == 'function');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "test_block_bad_colour",
|
||||
"message0": "test_block_bad_colour",
|
||||
"extensions": ["mixin_bad_colour_"]
|
||||
}]);
|
||||
|
||||
try {
|
||||
block = new Blockly.Block(workspace, 'test_block_bad_colour');
|
||||
} catch (e) {
|
||||
// Expected Error
|
||||
assert(e.message.indexOf('colour_') >= 0); // Reference the conflict
|
||||
return;
|
||||
}
|
||||
fail('Expected error when constructing block');
|
||||
} finally {
|
||||
block && block.dispose();
|
||||
workspace.dispose();
|
||||
|
||||
delete Blockly.Extensions.ALL_['mixin_bad_colour_'];
|
||||
delete Blockly.Blocks['test_block_bad_colour'];
|
||||
}
|
||||
}
|
||||
|
||||
function test_mutator_mixin() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": "mutator_test"
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
Blockly.Events.disable();
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
|
||||
block = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
|
||||
// Make sure all of the functions were installed correctly.
|
||||
assertEquals(block.domToMutation(), 'domToMutationFn');
|
||||
assertEquals(block.mutationToDom(), 'mutationToDomFn');
|
||||
assertEquals(block.compose(), 'composeFn');
|
||||
assertEquals(block.decompose(), 'decomposeFn');
|
||||
} finally {
|
||||
if (block) {
|
||||
block.dispose();
|
||||
}
|
||||
workspace.dispose();
|
||||
Blockly.Events.enable();
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
}
|
||||
|
||||
function test_mutator_mixin_no_dialog() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": "mutator_test"
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['mutator_test']);
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
});
|
||||
|
||||
block = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
|
||||
// Make sure all of the functions were installed correctly.
|
||||
assertEquals(block.domToMutation(), 'domToMutationFn');
|
||||
assertEquals(block.mutationToDom(), 'mutationToDomFn');
|
||||
assertFalse(block.hasOwnProperty('compose'));
|
||||
assertFalse(block.hasOwnProperty('decompose'));
|
||||
} finally {
|
||||
if (block) {
|
||||
block.dispose();
|
||||
}
|
||||
workspace.dispose();
|
||||
Blockly.Events.enable();
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly check all four things that could be missing.
|
||||
function test_mutator_mixin_no_decompose_fails() {
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_mutator_mixin_no_compose_fails() {
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_mutator_mixin_no_domToMutation_fails() {
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_mutator_mixin_no_mutationToDom_fails() {
|
||||
var exceptionWasThrown = false;
|
||||
try {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// Expected.
|
||||
exceptionWasThrown = true;
|
||||
} finally {
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_use_mutator_as_extension_fails() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
var exceptionWasThrown = false;
|
||||
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"extensions": ["mutator_test"]
|
||||
}]);
|
||||
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['mutator_test']);
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
});
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
block = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
} catch (e) {
|
||||
// Expected
|
||||
exceptionWasThrown = true;
|
||||
// Should have failed on apply, not on register.
|
||||
assertNotNull(Blockly.Extensions.ALL_['mutator_test']);
|
||||
} finally {
|
||||
if (block) {
|
||||
block.dispose();
|
||||
}
|
||||
workspace.dispose();
|
||||
Blockly.Events.enable();
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_use_mutator_mixin_as_extension_fails() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
var exceptionWasThrown = false;
|
||||
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"extensions": ["mutator_test"]
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['mutator_test']);
|
||||
Blockly.Extensions.registerMixin('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
});
|
||||
|
||||
block = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
} catch (e) {
|
||||
// Expected
|
||||
exceptionWasThrown = true;
|
||||
// Should have failed on apply, not on register.
|
||||
assertNotNull(Blockly.Extensions.ALL_['mutator_test']);
|
||||
} finally {
|
||||
if (block) {
|
||||
block.dispose();
|
||||
}
|
||||
workspace.dispose();
|
||||
Blockly.Events.enable();
|
||||
delete Blockly.Extensions.ALL_['mutator_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_use_extension_as_mutator_fails() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
var exceptionWasThrown = false;
|
||||
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": ["extensions_test"]
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test']);
|
||||
Blockly.Extensions.register('extensions_test', function() {
|
||||
return 'extensions_test_fn';
|
||||
});
|
||||
|
||||
block = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
} catch (e) {
|
||||
// Expected
|
||||
exceptionWasThrown = true;
|
||||
// Should have failed on apply, not on register.
|
||||
assertNotNull(Blockly.Extensions.ALL_['extensions_test']);
|
||||
} finally {
|
||||
if (block) {
|
||||
block.dispose();
|
||||
}
|
||||
workspace.dispose();
|
||||
Blockly.Events.enable();
|
||||
delete Blockly.Extensions.ALL_['extensions_test'];
|
||||
}
|
||||
assertTrue(exceptionWasThrown);
|
||||
}
|
||||
|
||||
function test_mutator_mixin_plus_function() {
|
||||
var workspace = new Blockly.Workspace();
|
||||
var block;
|
||||
var fnWasCalled = false;
|
||||
|
||||
try {
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": ["extensions_test"]
|
||||
}]);
|
||||
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test']);
|
||||
Blockly.Extensions.registerMutator('extensions_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
},
|
||||
function() {
|
||||
fnWasCalled = true;
|
||||
}
|
||||
);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
block = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
} finally {
|
||||
if (block) {
|
||||
block.dispose();
|
||||
}
|
||||
workspace.dispose();
|
||||
Blockly.Events.enable();
|
||||
delete Blockly.Extensions.ALL_['extensions_test'];
|
||||
}
|
||||
assertTrue(fnWasCalled);
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<script src="../mocha/test_helpers.js"></script>
|
||||
|
||||
<script src="test_utilities.js"></script>
|
||||
<script src="extensions_test.js"></script>
|
||||
|
||||
<script src="generator_test.js"></script>
|
||||
<script src="variables_test.js"></script>
|
||||
<script src="variable_map_test.js"></script>
|
||||
|
||||
511
tests/mocha/extensions_test.js
Normal file
511
tests/mocha/extensions_test.js
Normal file
@@ -0,0 +1,511 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2020 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
suite('Extensions', function() {
|
||||
setup(function() {
|
||||
this.workspace = new Blockly.Workspace();
|
||||
this.blockTypesCleanup_ = [];
|
||||
this.extensionsCleanup_ = [];
|
||||
});
|
||||
teardown(function() {
|
||||
var i;
|
||||
for (i = 0; i < this.blockTypesCleanup_.length; i++) {
|
||||
var blockType = this.blockTypesCleanup_[i];
|
||||
delete Blockly.Blocks[blockType];
|
||||
}
|
||||
for (i = 0; i < this.extensionsCleanup_.length; i++) {
|
||||
var extension = this.extensionsCleanup_[i];
|
||||
delete Blockly.Extensions.ALL_[extension];
|
||||
}
|
||||
this.workspace.dispose();
|
||||
// Clear Blockly.Event state.
|
||||
Blockly.Events.setGroup(false);
|
||||
Blockly.Events.disabled_ = 0;
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
test('Definition before and after block type', function() {
|
||||
this.extensionsCleanup_.push('extensions_test_before');
|
||||
this.extensionsCleanup_.push('extensions_test_after');
|
||||
this.blockTypesCleanup_.push('extension_test_block');
|
||||
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test_before']);
|
||||
var beforeCallback = sinon.spy();
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.register('extensions_test_before', beforeCallback);
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "extension_test_block",
|
||||
"message0": "extension_test_block",
|
||||
"extensions": ["extensions_test_before", "extensions_test_after"]
|
||||
}]);
|
||||
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test_after']);
|
||||
var afterCallback = sinon.spy();
|
||||
// Extension defined after the block type (but before instantiation).
|
||||
Blockly.Extensions.register('extensions_test_after', afterCallback);
|
||||
|
||||
assert(typeof Blockly.Extensions.ALL_['extensions_test_before'] == 'function');
|
||||
assert(typeof Blockly.Extensions.ALL_['extensions_test_after'] == 'function');
|
||||
sinon.assert.notCalled(beforeCallback);
|
||||
sinon.assert.notCalled(afterCallback);
|
||||
|
||||
var block = new Blockly.Block(this.workspace, 'extension_test_block');
|
||||
|
||||
sinon.assert.calledOnce(beforeCallback);
|
||||
sinon.assert.calledOnce(afterCallback);
|
||||
sinon.assert.calledOn(beforeCallback, block);
|
||||
sinon.assert.calledOn(afterCallback, block);
|
||||
});
|
||||
|
||||
test('Parent tooltip when inline', function() {
|
||||
this.blockTypesCleanup_.push('test_parent_tooltip_when_inline');
|
||||
this.blockTypesCleanup_.push('test_parent');
|
||||
|
||||
var defaultTooltip = "defaultTooltip";
|
||||
var parentTooltip = "parentTooltip";
|
||||
Blockly.defineBlocksWithJsonArray([
|
||||
{
|
||||
"type": "test_parent_tooltip_when_inline",
|
||||
"message0": "test_parent_tooltip_when_inline",
|
||||
"output": true,
|
||||
"tooltip": defaultTooltip,
|
||||
"extensions": ["parent_tooltip_when_inline"]
|
||||
},
|
||||
{
|
||||
"type": "test_parent",
|
||||
"message0": "%1",
|
||||
"args0": [
|
||||
{
|
||||
"type": "input_value",
|
||||
"name": "INPUT"
|
||||
}
|
||||
],
|
||||
"tooltip": parentTooltip
|
||||
}
|
||||
]);
|
||||
|
||||
var block =
|
||||
new Blockly.Block(this.workspace, 'test_parent_tooltip_when_inline');
|
||||
|
||||
// Tooltip is dynamic after extension initialization.
|
||||
assert(typeof block.tooltip == 'function');
|
||||
assertEquals(block.tooltip(), defaultTooltip);
|
||||
|
||||
// Tooltip is normal before connected to parent.
|
||||
var parent = new Blockly.Block(this.workspace, 'test_parent');
|
||||
assertEquals(parent.tooltip, parentTooltip);
|
||||
assertFalse(!!parent.inputsInline);
|
||||
|
||||
// Tooltip is normal when parent is not inline.
|
||||
parent.getInput('INPUT').connection.connect(block.outputConnection);
|
||||
assertEquals(block.getParent(), parent);
|
||||
assertEquals(block.tooltip(), defaultTooltip);
|
||||
|
||||
// Tooltip is parent's when parent is inline.
|
||||
parent.setInputsInline(true);
|
||||
assertEquals(block.tooltip(), parentTooltip);
|
||||
|
||||
// Tooltip revert when disconnected.
|
||||
parent.getInput('INPUT').connection.disconnect();
|
||||
assert(!block.getParent());
|
||||
assertEquals(block.tooltip(), defaultTooltip);
|
||||
});
|
||||
|
||||
suite('Mixin', function() {
|
||||
test('Basic', function() {
|
||||
this.extensionsCleanup_.push('mixin_test');
|
||||
this.blockTypesCleanup_.push('test_block_mixin');
|
||||
|
||||
var testMixin = {
|
||||
field: 'FIELD',
|
||||
method: function() {
|
||||
console.log('TEXT_MIXIN method()');
|
||||
}
|
||||
};
|
||||
|
||||
assertUndefined(Blockly.Extensions.ALL_['mixin_test']);
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.registerMixin('mixin_test', testMixin);
|
||||
|
||||
assert(typeof Blockly.Extensions.ALL_['mixin_test'] == 'function');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "test_block_mixin",
|
||||
"message0": "test_block_mixin",
|
||||
"extensions": ["mixin_test"]
|
||||
}]);
|
||||
|
||||
var block = new Blockly.Block(this.workspace, 'test_block_mixin');
|
||||
|
||||
assertEquals(testMixin.field, block.field);
|
||||
assertEquals(testMixin.method, block.method);
|
||||
});
|
||||
|
||||
suite('Mutator', function() {
|
||||
test('Basic', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
this.blockTypesCleanup_.push('mutator_test_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": "mutator_test"
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a meaningful
|
||||
// value.
|
||||
Blockly.Events.disable();
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
|
||||
var block = new Blockly.Block(this.workspace, 'mutator_test_block');
|
||||
|
||||
// Make sure all of the functions were installed correctly.
|
||||
assertEquals(block.domToMutation(), 'domToMutationFn');
|
||||
assertEquals(block.mutationToDom(), 'mutationToDomFn');
|
||||
assertEquals(block.compose(), 'composeFn');
|
||||
assertEquals(block.decompose(), 'decomposeFn');
|
||||
});
|
||||
|
||||
test('With helper function', function() {
|
||||
this.extensionsCleanup_.push('extensions_test');
|
||||
this.blockTypesCleanup_.push('mutator_test_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": ["extensions_test"]
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a
|
||||
// meaningful value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test']);
|
||||
var helperFunctionSpy = sinon.spy();
|
||||
Blockly.Extensions.registerMutator('extensions_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
},
|
||||
helperFunctionSpy
|
||||
);
|
||||
|
||||
var _ = new Blockly.Block(this.workspace, 'mutator_test_block');
|
||||
|
||||
sinon.assert.calledOnce(helperFunctionSpy);
|
||||
});
|
||||
|
||||
test('No dialog', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
this.blockTypesCleanup_.push('mutator_test_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": "mutator_test"
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a
|
||||
// meaningful value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['mutator_test']);
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
});
|
||||
|
||||
var block = new Blockly.Block(this.workspace, 'mutator_test_block');
|
||||
|
||||
// Make sure all of the functions were installed correctly.
|
||||
assertEquals(block.domToMutation(), 'domToMutationFn');
|
||||
assertEquals(block.mutationToDom(), 'mutationToDomFn');
|
||||
assertFalse(block.hasOwnProperty('compose'));
|
||||
assertFalse(block.hasOwnProperty('decompose'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Error cases', function() {
|
||||
test('Missing extension', function() {
|
||||
this.blockTypesCleanup_.push('missing_extension_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "missing_extension_block",
|
||||
"message0": "missing_extension_block",
|
||||
"extensions": ["missing_extension"]
|
||||
}]);
|
||||
|
||||
assertUndefined(Blockly.Extensions.ALL_['missing_extension']);
|
||||
var workspace = this.workspace;
|
||||
chai.assert.throws(function() {
|
||||
var _ = new Blockly.Block(workspace, 'missing_extension_block');
|
||||
});
|
||||
});
|
||||
|
||||
test('Mixin overwrites local value', function() {
|
||||
this.extensionsCleanup_.push('mixin_bad_inputList');
|
||||
this.blockTypesCleanup_.push('test_block_bad_inputList');
|
||||
|
||||
var TEST_MIXIN_BAD_INPUTLIST = {
|
||||
inputList: 'bad inputList' // Defined in constructor
|
||||
};
|
||||
|
||||
assertUndefined(Blockly.Extensions.ALL_['mixin_bad_inputList']);
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.registerMixin('mixin_bad_inputList', TEST_MIXIN_BAD_INPUTLIST);
|
||||
assert(typeof Blockly.Extensions.ALL_['mixin_bad_inputList'] == 'function');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "test_block_bad_inputList",
|
||||
"message0": "test_block_bad_inputList",
|
||||
"extensions": ["mixin_bad_inputList"]
|
||||
}]);
|
||||
|
||||
var workspace = this.workspace;
|
||||
chai.assert.throws(function() {
|
||||
var _ = new Blockly.Block(workspace, 'test_block_bad_inputList');
|
||||
}, /inputList/);
|
||||
});
|
||||
|
||||
test('Mixin overwrites prototype', function() {
|
||||
this.extensionsCleanup_.push('mixin_bad_colour_');
|
||||
this.blockTypesCleanup_.push('test_block_bad_colour');
|
||||
|
||||
var TEST_MIXIN_BAD_COLOUR = {
|
||||
colour_: 'bad colour_' // Defined on prototype
|
||||
};
|
||||
|
||||
assertUndefined(Blockly.Extensions.ALL_['mixin_bad_colour_']);
|
||||
// Extension defined before the block type is defined.
|
||||
Blockly.Extensions.registerMixin('mixin_bad_colour_', TEST_MIXIN_BAD_COLOUR);
|
||||
assert(typeof Blockly.Extensions.ALL_['mixin_bad_colour_'] == 'function');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "test_block_bad_colour",
|
||||
"message0": "test_block_bad_colour",
|
||||
"extensions": ["mixin_bad_colour_"]
|
||||
}]);
|
||||
|
||||
var workspace = this.workspace;
|
||||
chai.assert.throws(function() {
|
||||
var _ = new Blockly.Block(workspace, 'test_block_bad_colour');
|
||||
}, /colour_/);
|
||||
});
|
||||
|
||||
test('Use mutator as extension', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
this.blockTypesCleanup_.push('mutator_test_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"extensions": ["mutator_test"]
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a
|
||||
// meaningful value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['mutator_test']);
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
});
|
||||
|
||||
var workspace = this.workspace;
|
||||
chai.assert.throws(function() {
|
||||
var _ = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
});
|
||||
// Should have failed on apply, not on register.
|
||||
assertNotNull(Blockly.Extensions.ALL_['mutator_test']);
|
||||
});
|
||||
|
||||
test('Use mutator mixin as extension', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
this.blockTypesCleanup_.push('mutator_test_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"extensions": ["mutator_test"]
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a
|
||||
// meaningful value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['mutator_test']);
|
||||
Blockly.Extensions.registerMixin('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
}
|
||||
});
|
||||
|
||||
var workspace = this.workspace;
|
||||
chai.assert.throws(function() {
|
||||
var _ = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
});
|
||||
// Should have failed on apply, not on register.
|
||||
assertNotNull(Blockly.Extensions.ALL_['mutator_test']);
|
||||
});
|
||||
|
||||
test('Use extension as mutator', function() {
|
||||
this.extensionsCleanup_.push('extensions_test');
|
||||
this.blockTypesCleanup_.push('mutator_test_block');
|
||||
|
||||
Blockly.defineBlocksWithJsonArray([{
|
||||
"type": "mutator_test_block",
|
||||
"message0": "mutator_test_block",
|
||||
"mutator": ["extensions_test"]
|
||||
}]);
|
||||
|
||||
// Events code calls mutationToDom and expects it to give back a
|
||||
// meaningful value.
|
||||
Blockly.Events.disable();
|
||||
assertUndefined(Blockly.Extensions.ALL_['extensions_test']);
|
||||
Blockly.Extensions.register('extensions_test', function() {
|
||||
return 'extensions_test_fn';
|
||||
});
|
||||
|
||||
var workspace = this.workspace;
|
||||
chai.assert.throws(function() {
|
||||
var _ = new Blockly.Block(workspace, 'mutator_test_block');
|
||||
});
|
||||
// Should have failed on apply, not on register.
|
||||
assertNotNull(Blockly.Extensions.ALL_['extensions_test']);
|
||||
});
|
||||
|
||||
suite('register', function() {
|
||||
test('Just a string', function() {
|
||||
this.extensionsCleanup_.push('extension_just_a_string');
|
||||
assertUndefined(Blockly.Extensions.ALL_['extension_just_a_string']);
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.register('extension_just_a_string', null);
|
||||
});
|
||||
});
|
||||
|
||||
test('Null', function() {
|
||||
this.extensionsCleanup_.push('extension_is_null');
|
||||
assertUndefined(Blockly.Extensions.ALL_['extension_is_null']);
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.register('extension_is_null', null);
|
||||
});
|
||||
});
|
||||
|
||||
test('Undefined', function() {
|
||||
this.extensionsCleanup_.push('extension_is_undefined');
|
||||
assertUndefined(Blockly.Extensions.ALL_['extension_is_undefined']);
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.register('extension_is_undefined', null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('registerMutator', function() {
|
||||
test('No domToMutation', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
}, /domToMutation/);
|
||||
});
|
||||
|
||||
test('No mutationToDom', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
}, /mutationToDom/);
|
||||
});
|
||||
|
||||
test('Has decompose but no compose', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
decompose: function() {
|
||||
return 'decomposeFn';
|
||||
}
|
||||
});
|
||||
}, /compose/);
|
||||
});
|
||||
|
||||
test('Has compose but no decompose', function() {
|
||||
this.extensionsCleanup_.push('mutator_test');
|
||||
chai.assert.throws(function() {
|
||||
Blockly.Extensions.registerMutator('mutator_test',
|
||||
{
|
||||
domToMutation: function() {
|
||||
return 'domToMutationFn';
|
||||
},
|
||||
mutationToDom: function() {
|
||||
return 'mutationToDomFn';
|
||||
},
|
||||
compose: function() {
|
||||
return 'composeFn';
|
||||
}
|
||||
});
|
||||
}, /decompose/);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -33,6 +33,7 @@
|
||||
<script src="cursor_test.js"></script>
|
||||
<script src="dropdowndiv_test.js"></script>
|
||||
<script src="event_test.js"></script>
|
||||
<script src="extensions_test.js"></script>
|
||||
<script src="field_test.js"></script>
|
||||
<script src="field_angle_test.js"></script>
|
||||
<script src="field_checkbox_test.js"></script>
|
||||
|
||||
@@ -76,6 +76,9 @@ suite('XML', function() {
|
||||
delete Blockly.Blocks[this.blockTypes_[i]];
|
||||
}
|
||||
this.blockTypes_.length = 0;
|
||||
// Clear Blockly.Event state.
|
||||
Blockly.Events.setGroup(false);
|
||||
Blockly.Events.disabled_ = 0;
|
||||
sinon.restore();
|
||||
});
|
||||
suite('textToDom', function() {
|
||||
|
||||
Reference in New Issue
Block a user