More testing with mocha

This commit is contained in:
Rachel Fenichel
2018-12-14 10:33:35 -08:00
parent e27f58ada7
commit 1c413f0442
5 changed files with 587 additions and 1 deletions

View File

@@ -52,6 +52,7 @@
"unused": true
},
"dependencies": {
"jsdom": "^13.0.0"
"jsdom": "^13.0.0",
"sinon": "^7.2.0"
}
}

385
tests/mocha/event_test.js Normal file
View File

@@ -0,0 +1,385 @@
// Declare some globals to make eslint happier.
// TODO: make an eslint config that applies to this directory and put this
// configuration in that file, instead of inline.
/* global suite, test, chai, setup, teardown */
/* global sinon */
/* global assertNotNull, assertNotUndefined, assertNull, assertEquals, isEqualArrays, assertUndefined */
suite('Events', function() {
setup(function() {
this.workspace = new Blockly.Workspace();
Blockly.defineBlocksWithJsonArray([{
'type': 'field_variable_test_block',
'message0': '%1',
'args0': [
{
'type': 'field_variable',
'name': 'VAR',
'variable': 'item'
}
],
},
{
'type': 'simple_test_block',
'message0': 'simple test block'
}]);
});
teardown(function() {
delete Blockly.Blocks['field_variable_test_block'];
delete Blockly.Blocks['simple_test_block'];
this.workspace.dispose();
// Clear Blockly.Event state.
Blockly.Events.setGroup(false);
Blockly.Events.disabled_ = 0;
});
function checkExactEventValues(event, values) {
var keys = Object.keys(values);
for (var i = 0, field; field = keys[i]; i++) {
assertEquals(values[field], event[field]);
}
}
function checkCreateEventValues(event, block, ids, type) {
var expected_xml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block));
var result_xml = Blockly.Xml.domToText(event.xml);
assertEquals(expected_xml, result_xml);
isEqualArrays(ids, event.ids);
assertEquals(type, event.type);
}
function checkDeleteEventValues(event, block, ids, type) {
var expected_xml = Blockly.Xml.domToText(Blockly.Xml.blockToDom(block));
var result_xml = Blockly.Xml.domToText(event.oldXml);
assertEquals(expected_xml, result_xml);
isEqualArrays(ids, event.ids);
assertEquals(type, event.type);
}
suite('Constructors', function() {
test('Abstract', function() {
var event = new Blockly.Events.Abstract();
assertUndefined(event.blockId);
assertUndefined(event.workspaceId);
assertUndefined(event.varId);
checkExactEventValues(event, {'group': '', 'recordUndo': true});
});
test('UI event without block', function() {
Blockly.Events.setGroup('testGroup');
var event = new Blockly.Events.Ui(null, 'foo', 'bar', 'baz');
checkExactEventValues(event,
{
'blockId': null,
'workspaceId': null,
'type': 'ui',
'oldValue': 'bar',
'newValue': 'baz',
'element': 'foo',
'recordUndo': false,
'group': 'testGroup'
});
});
suite('With simple blocks', function() {
setup(function() {
this.FAKE_ID = 'hedgehog';
sinon.stub(Blockly.utils, "genUid").returns(this.FAKE_ID);
// Disable events while constructing the block: this is a test of the
// Blockly.Event constructors, not the block constructor.
Blockly.Events.disable();
this.block = new Blockly.Block(this.workspace, 'simple_test_block');
Blockly.Events.enable();
sinon.restore();
});
teardown(function() {
});
test('Block base', function() {
var event = new Blockly.Events.BlockBase(this.block);
assertUndefined(event.varId);
checkExactEventValues(event,
{
'blockId': this.FAKE_ID,
'workspaceId': this.workspace.id,
'group': '',
'recordUndo': true
});
});
test('Create', function() {
var event = new Blockly.Events.Create(this.block);
checkCreateEventValues(event, this.block, [this.FAKE_ID], 'create');
});
test('Block create', function() {
var event = new Blockly.Events.BlockCreate(this.block);
checkCreateEventValues(event, this.block, [this.FAKE_ID], 'create');
});
test('Delete', function() {
var event = new Blockly.Events.Delete(this.block);
checkDeleteEventValues(event, this.block, [this.FAKE_ID], 'delete');
});
test('Block delete', function() {
var event = new Blockly.Events.BlockDelete(this.block);
checkDeleteEventValues(event, this.block, [this.FAKE_ID], 'delete');
});
test('UI event with block', function() {
Blockly.Events.setGroup('testGroup');
var event = new Blockly.Events.Ui(this.block, 'foo', 'bar', 'baz');
checkExactEventValues(event,
{
'blockId': this.FAKE_ID,
'workspaceId': this.workspace.id,
'type': 'ui',
'oldValue': 'bar',
'newValue': 'baz',
'element': 'foo',
'recordUndo': false,
'group': 'testGroup'
});
});
suite('Move', function() {
test('Move by coordinate', function() {
var coordinate = new goog.math.Coordinate(3, 4);
this.block.xy_ = coordinate;
var event = new Blockly.Events.Move(this.block);
checkExactEventValues(event,
{'oldCoordinate': coordinate, 'type': 'move'});
});
test('Block move by coordinate', function() {
var coordinate = new goog.math.Coordinate(3, 4);
this.block.xy_ = coordinate;
var event = new Blockly.Events.BlockMove(this.block);
checkExactEventValues(event,
{'oldCoordinate': coordinate, 'type': 'move'});
});
suite('Move by parent', function() {
setup(function() {
sinon.stub(Blockly.utils, "genUid").returns("parent");
Blockly.Events.disable();
this.parentBlock = new Blockly.Block(this.workspace, 'simple_test_block');
Blockly.Events.enable();
sinon.restore();
this.block.parentBlock_ = this.parentBlock;
this.block.xy_ = new goog.math.Coordinate(3, 4);
});
teardown(function() {
this.block.parentBlock_ = null;
});
test('Move by parent', function() {
// Expect the oldParentId to be set but not the oldCoordinate to be set.
var event = new Blockly.Events.Move(this.block);
checkExactEventValues(event, {'oldCoordinate': undefined,
'oldParentId': 'parent', 'type': 'move'});
});
test('Block move by parent', function() {
// Expect the oldParentId to be set but not the oldCoordinate to be set.
var event = new Blockly.Events.BlockMove(this.block);
checkExactEventValues(event, {'oldCoordinate': undefined,
'oldParentId': 'parent', 'type': 'move'});
});
});
});
});
suite('With variable getter blocks', function() {
setup(function() {
// Disable events while constructing the block: this is a test of the
// Blockly.Event constructors, not the block constructor.
Blockly.Events.disable();
this.block = new Blockly.Block(this.workspace, 'field_variable_test_block');
Blockly.Events.enable();
});
teardown(function() {
});
test('Change', function() {
var event =
new Blockly.Events.Change(this.block, 'field', 'VAR', 'id1', 'id2');
checkExactEventValues(event, {'element': 'field', 'name': 'VAR',
'oldValue': 'id1', 'newValue': 'id2', 'type': 'change'});
});
test('Block change', function() {
var event = new Blockly.Events.BlockChange(
this.block, 'field', 'VAR', 'id1', 'id2');
checkExactEventValues(event, {'element': 'field', 'name': 'VAR',
'oldValue': 'id1', 'newValue': 'id2', 'type': 'change'});
});
});
});
suite('Variable events', function() {
setup(function() {
this.variable = this.workspace.createVariable('name1', 'type1', 'id1');
});
/**
* Check if a variable with the given values exists.
* @param {Blockly.Workspace|Blockly.VariableMap} container The workspace or
* variableMap the checked variable belongs to.
* @param {!string} name The expected name of the variable.
* @param {!string} type The expected type of the variable.
* @param {!string} id The expected id of the variable.
*/
function checkVariableValues(container, name, type, id) {
var variable = container.getVariableById(id);
assertNotUndefined(variable);
assertEquals(name, variable.name);
assertEquals(type, variable.type);
assertEquals(id, variable.getId());
}
suite('Constructors', function() {
test('Var base', function() {
var event = new Blockly.Events.VarBase(this.variable);
assertUndefined(event.blockId);
checkExactEventValues(event, {'varId': 'id1',
'workspaceId': this.workspace.id, 'group': '', 'recordUndo': true});
});
test('Var create', function() {
var event = new Blockly.Events.VarCreate(this.variable);
checkExactEventValues(event, {'varName': 'name1', 'varType': 'type1',
'type': 'var_create'});
});
test('Var delete', function() {
var event = new Blockly.Events.VarDelete(this.variable);
checkExactEventValues(event, {'varName': 'name1', 'varType': 'type1',
'varId':'id1', 'type': 'var_delete'});
});
test('Var rename', function() {
var event = new Blockly.Events.VarRename(this.variable, 'name2');
checkExactEventValues(event, {'varId': 'id1', 'oldName': 'name1',
'newName': 'name2', 'type': 'var_rename'});
});
});
suite('fromJson', function() {
test('Var create', function() {
var event = new Blockly.Events.VarCreate(this.variable);
var event2 = new Blockly.Events.VarCreate(null);
var json = event.toJson();
event2.fromJson(json);
assertEquals(JSON.stringify(json), JSON.stringify(event2.toJson()));
});
test('Var delete', function() {
var event = new Blockly.Events.VarDelete(this.variable);
var event2 = new Blockly.Events.VarDelete(null);
var json = event.toJson();
event2.fromJson(json);
assertEquals(JSON.stringify(json), JSON.stringify(event2.toJson()));
});
test('Var rename', function() {
var event = new Blockly.Events.VarRename(this.variable, '');
var event2 = new Blockly.Events.VarRename(null);
var json = event.toJson();
event2.fromJson(json);
assertEquals(JSON.stringify(json), JSON.stringify(event2.toJson()));
});
});
suite('toJson', function() {
test('Var create', function() {
var variable = this.workspace.createVariable('name1', 'type1', 'id1');
var event = new Blockly.Events.VarCreate(variable);
var json = event.toJson();
var expectedJson = ({type: "var_create", varId: "id1", varType: "type1",
varName: "name1"});
assertEquals(JSON.stringify(expectedJson), JSON.stringify(json));
});
test('Var delete', function() {
var event = new Blockly.Events.VarDelete(this.variable);
var json = event.toJson();
var expectedJson = ({type: "var_delete", varId: "id1", varType: "type1",
varName: "name1"});
assertEquals(JSON.stringify(expectedJson), JSON.stringify(json));
});
test('Var rename', function() {
var event = new Blockly.Events.VarRename(this.variable, 'name2');
var json = event.toJson();
var expectedJson = ({type: "var_rename", varId: "id1", oldName: "name1",
newName: "name2"});
assertEquals(JSON.stringify(expectedJson), JSON.stringify(json));
});
});
suite('Run Forward', function() {
test('Var create', function() {
var json = {type: "var_create", varId: "id1", varType: "type1",
varName: "name1"};
var event = Blockly.Events.fromJson(json, this.workspace);
assertNull(this.workspace.getVariableById('id1'));
event.run(true);
checkVariableValues(this.workspace, 'name1', 'type1', 'id1');
});
test('Var delete', function() {
var event = new Blockly.Events.VarDelete(this.variable);
assertNotNull(this.workspace.getVariableById('id1'));
event.run(true);
assertNull(this.workspace.getVariableById('id1'));
});
test('Var rename', function() {
var event = new Blockly.Events.VarRename(this.variable, 'name2');
event.run(true);
assertNull(this.workspace.getVariable('name1'));
checkVariableValues(this.workspace, 'name2', 'type1', 'id1');
});
});
suite('Run Backward', function() {
test('Var create', function() {
var variable = this.workspace.createVariable('name1', 'type1', 'id1');
var event = new Blockly.Events.VarCreate(variable);
assertNotNull(this.workspace.getVariableById('id1'));
event.run(false);
});
test('Var delete', function() {
var json = {type: "var_delete", varId: "id1", varType: "type1",
varName: "name1"};
var event = Blockly.Events.fromJson(json, this.workspace);
assertNull(this.workspace.getVariableById('id1'));
event.run(false);
checkVariableValues(this.workspace, 'name1', 'type1', 'id1');
});
test('Var rename', function() {
var event = new Blockly.Events.VarRename(this.variable, 'name2');
event.run(false);
assertNull(this.workspace.getVariable('name2'));
checkVariableValues(this.workspace, 'name1', 'type1', 'id1');
});
});
});
});

View File

@@ -0,0 +1,162 @@
// Declare some globals to make eslint happier.
// TODO: make an eslint config that applies to this directory and put this
// configuration in that file, instead of inline.
/* global suite, test, chai, setup, teardown */
/* global sinon */
/* global assertFalse, assertTrue, assertNull, assertEquals, isEqualArrays */
suite('Variable Fields', function() {
function getMockBlock(workspace) {
return {
'workspace': workspace,
'isShadow': function() {
return false;
}
};
}
function fieldVariable_createAndInitField(workspace) {
var fieldVariable = new Blockly.FieldVariable('name1');
var mockBlock = getMockBlock(workspace);
fieldVariable.setSourceBlock(mockBlock);
// No view to initialize, but still need to init the model.
fieldVariable.initModel();
return fieldVariable;
}
setup(function() {
this.workspace = new Blockly.Workspace();
});
teardown(function() {
this.workspace.dispose();
});
test('Constructor', function() {
var fieldVariable = new Blockly.FieldVariable('name1');
// The field does not have a variable until after init() is called.
assertEquals('', fieldVariable.getText());
assertNull(fieldVariable.getValue());
});
test('Set value by ID', function() {
this.workspace.createVariable('name2', null, 'id2');
var fieldVariable = fieldVariable_createAndInitField(this.workspace);
var oldId = fieldVariable.getValue();
fieldVariable.setValue('id2');
// Setting value by ID gives us the right text as well.
assertEquals('name2', fieldVariable.getText());
assertEquals('id2', fieldVariable.getValue());
chai.assert.notEqual(oldId, fieldVariable.getValue());
});
test('Set value: variable does not exist', function() {
var fieldVariable = fieldVariable_createAndInitField(this.workspace);
chai.assert.throws(function() {
fieldVariable.setValue('id1');
});
});
test('Dropdown contains variables', function() {
// Expect that the dropdown options will contain the variables that exist
this.workspace.createVariable('name1', '', 'id1');
this.workspace.createVariable('name2', '', 'id2');
var fieldVariable = fieldVariable_createAndInitField(this.workspace);
// Expect that variables created after field creation will show up too.
this.workspace.createVariable('name3', '', 'id3');
var result_options = Blockly.FieldVariable.dropdownCreate.call(
fieldVariable);
// Expect three variable options and a rename option.
assertEquals(result_options.length, 4);
isEqualArrays(result_options[0], ['name1', 'id1']);
isEqualArrays(result_options[1], ['name2', 'id2']);
isEqualArrays(result_options[2], ['name3', 'id3']);
});
suite('Get variable types', function() {
setup(function() {
this.workspace.createVariable('name1', 'type1');
this.workspace.createVariable('name2', 'type2');
});
test('variableTypes is undefined', function() {
// Expect that since variableTypes is undefined, only type empty string
// will be returned (regardless of what types are available on the workspace).
var fieldVariable = new Blockly.FieldVariable('name1');
var resultTypes = fieldVariable.getVariableTypes_();
isEqualArrays(resultTypes, ['']);
});
test('variableTypes is explicit', function() {
// Expect that since variableTypes is defined, it will be the return
// value, regardless of what types are available on the workspace.
var fieldVariable = new Blockly.FieldVariable(
'name1', null, ['type1', 'type2'], 'type1');
var resultTypes = fieldVariable.getVariableTypes_();
isEqualArrays(resultTypes, ['type1', 'type2']);
assertEquals('Default type was wrong', 'type1',
fieldVariable.defaultType_);
});
test('variableTypes is null', function() {
// Expect all variable types to be returned.
// The field does not need to be initialized to do this--it just needs
// a pointer to the workspace.
var fieldVariable = new Blockly.FieldVariable('name1');
var mockBlock = getMockBlock(this.workspace);
fieldVariable.setSourceBlock(mockBlock);
fieldVariable.variableTypes = null;
var resultTypes = fieldVariable.getVariableTypes_();
// The empty string is always one of the options.
isEqualArrays(resultTypes, ['type1', 'type2', '']);
});
test('variableTypes is the empty list', function() {
var fieldVariable = new Blockly.FieldVariable('name1');
var mockBlock = getMockBlock(this.workspace);
fieldVariable.setSourceBlock(mockBlock);
fieldVariable.variableTypes = [];
chai.assert.throws(function() {
fieldVariable.getVariableTypes_();
});
});
});
suite('Default types', function() {
test('Default type exists', function() {
var fieldVariable = new Blockly.FieldVariable(null, null, ['b'], 'b');
assertEquals('The variable field\'s default type should be "b"',
'b', fieldVariable.defaultType_);
});
test('No default type', function() {
var fieldVariable = new Blockly.FieldVariable(null);
assertEquals('The variable field\'s default type should be the empty string',
'', fieldVariable.defaultType_);
assertNull('The variable field\'s allowed types should be null',
fieldVariable.variableTypes);
});
test('Default type mismatch', function() {
// Invalid default type when creating a variable field.
chai.assert.throws(function() {
var _fieldVariable = new Blockly.FieldVariable(null, null, ['a'], 'b');
});
});
test('Default type mismatch with empty array', function() {
// Invalid default type when creating a variable field.
chai.assert.throws(function() {
var _fieldVariable = new Blockly.FieldVariable(null, null, ['a']);
});
});
});
});

View File

@@ -12,6 +12,7 @@
<div id="mocha"></div>
<script src="https://unpkg.com/chai/chai.js"></script>
<script src="https://unpkg.com/mocha@5.2.0/mocha.js"></script>
<script src="../../node_modules/sinon/pkg/sinon.js"></script>
<script>
mocha.setup({
ui: 'tdd'
@@ -19,6 +20,8 @@
</script>
<script src="test_helpers.js"></script>
<script src="block_test.js"></script>
<script src="event_test.js"></script>
<script src="field_variable_test.js"></script>
<script src="utils_test.js"></script>
<script>

View File

@@ -1,3 +1,5 @@
/* global chai */
function _argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) {
return args.length == expectedNumberOfNonCommentArgs + 1;
}
@@ -71,3 +73,36 @@ function assertNull() {
var val = _nonCommentArg(1, 1, arguments);
chai.assert.isNull(val, commentArg);
}
function assertNotNull() {
_validateArguments(1, arguments);
var commentArg = _commentArg(1, arguments);
var val = _nonCommentArg(1, 1, arguments);
chai.assert.isNotNull(val, commentArg);
}
/**
* Check that two arrays have the same content.
* @param {!Array.<string>} array1 The first array.
* @param {!Array.<string>} array2 The second array.
*/
function isEqualArrays(array1, array2) {
assertEquals(array1.length, array2.length);
for (var i = 0; i < array1.length; i++) {
assertEquals(array1[i], array2[i]);
}
}
function assertUndefined() {
_validateArguments(1, arguments);
var commentArg = _commentArg(1, arguments);
var val = _nonCommentArg(1, 1, arguments);
chai.assert.isUndefined(val, commentArg);
}
function assertNotUndefined() {
_validateArguments(1, arguments);
var commentArg = _commentArg(1, arguments);
var val = _nonCommentArg(1, 1, arguments);
chai.assert.isNotUndefined(val, commentArg);
}