From 4ac4332f5e78d9894a831ecd1288517798cc659d Mon Sep 17 00:00:00 2001 From: Monica Kozbial Date: Fri, 12 Jun 2020 15:18:28 -0700 Subject: [PATCH] Update logic for field default values. (#3953) * Update logic for field default values. * Fix bugs * Use contant for default value. * Fix FieldColour * Update field number tests. * Update field angle test. * Minor update. * Update field checkbox test. * Undo enabling logging * Remove only. * Update field colour test. * Update invalid test cases for field colour * Update field label tests * Update field textinput test. * Minor cleanup * Make lint happy. --- core/field.js | 9 +- core/field_angle.js | 10 +- core/field_checkbox.js | 10 +- core/field_colour.js | 10 +- core/field_image.js | 11 +- core/field_label.js | 10 +- core/field_multilineinput.js | 4 - core/field_number.js | 9 +- core/field_textinput.js | 10 +- tests/mocha/.eslintrc.json | 1 + tests/mocha/field_angle_test.js | 342 ++++-------- tests/mocha/field_checkbox_test.js | 215 ++++---- tests/mocha/field_colour_test.js | 305 +++++------ tests/mocha/field_label_serializable_test.js | 247 ++++----- tests/mocha/field_label_test.js | 239 ++++----- tests/mocha/field_number_test.js | 527 +++++++------------ tests/mocha/field_textinput_test.js | 297 ++++------- tests/mocha/index.html | 1 + 18 files changed, 880 insertions(+), 1377 deletions(-) diff --git a/core/field.js b/core/field.js index 03cbf6d2e..d1e501cc3 100644 --- a/core/field.js +++ b/core/field.js @@ -53,7 +53,7 @@ Blockly.Field = function(value, opt_validator, opt_config) { * @type {*} * @protected */ - this.value_ = null; + this.value_ = this.DEFAULT_VALUE; /** * Validation function called when user edits an editable field. @@ -140,6 +140,13 @@ Blockly.Field = function(value, opt_validator, opt_config) { opt_validator && this.setValidator(opt_validator); }; +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.Field.prototype.DEFAULT_VALUE = null; + /** * Name of field. Unique within each block. * Static labels are usually unnamed. diff --git a/core/field_angle.js b/core/field_angle.js index 70153495a..04133dbf4 100644 --- a/core/field_angle.js +++ b/core/field_angle.js @@ -71,7 +71,7 @@ Blockly.FieldAngle = function(opt_value, opt_validator, opt_config) { this.round_ = Blockly.FieldAngle.ROUND; Blockly.FieldAngle.superClass_.constructor.call( - this, opt_value || 0, opt_validator, opt_config); + this, opt_value, opt_validator, opt_config); /** * The angle picker's gauge path depending on the value. @@ -108,6 +108,14 @@ Blockly.FieldAngle = function(opt_value, opt_validator, opt_config) { }; Blockly.utils.object.inherits(Blockly.FieldAngle, Blockly.FieldTextInput); + +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldAngle.prototype.DEFAULT_VALUE = 0; + /** * Construct a FieldAngle from a JSON arg object. * @param {!Object} options A JSON object with options (angle). diff --git a/core/field_checkbox.js b/core/field_checkbox.js index e4818ebe8..acca4f203 100644 --- a/core/field_checkbox.js +++ b/core/field_checkbox.js @@ -44,14 +44,18 @@ Blockly.FieldCheckbox = function(opt_value, opt_validator, opt_config) { */ this.checkChar_ = null; - if (opt_value == null) { - opt_value = 'FALSE'; - } Blockly.FieldCheckbox.superClass_.constructor.call( this, opt_value, opt_validator, opt_config); }; Blockly.utils.object.inherits(Blockly.FieldCheckbox, Blockly.Field); +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldCheckbox.prototype.DEFAULT_VALUE = false; + /** * Construct a FieldCheckbox from a JSON arg object. * @param {!Object} options A JSON object with options (checked). diff --git a/core/field_colour.js b/core/field_colour.js index 50068d15a..fbef49384 100644 --- a/core/field_colour.js +++ b/core/field_colour.js @@ -43,8 +43,7 @@ goog.require('Blockly.utils.Size'); */ Blockly.FieldColour = function(opt_value, opt_validator, opt_config) { Blockly.FieldColour.superClass_.constructor.call( - this, opt_value || Blockly.FieldColour.COLOURS[0], - opt_validator, opt_config); + this, opt_value, opt_validator, opt_config); /** * The field's colour picker element. @@ -268,6 +267,13 @@ Blockly.FieldColour.COLOURS = [ '#ffccff', '#ff99ff', '#cc66cc', '#cc33cc', '#993399', '#663366', '#330033' ]; +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldColour.prototype.DEFAULT_VALUE = Blockly.FieldColour.COLOURS[0]; + /** * An array of tooltip strings for the palette. If not the same length as * COLOURS, the colour's hex code will be used for any missing titles. diff --git a/core/field_image.js b/core/field_image.js index 32af8adca..d6474ea3b 100644 --- a/core/field_image.js +++ b/core/field_image.js @@ -22,7 +22,7 @@ goog.require('Blockly.utils.Size'); /** * Class for an image on a block. - * @param {string} src The URL of the image. Defaults to an empty string. + * @param {string} src The URL of the image. * @param {!(string|number)} width Width of the image. * @param {!(string|number)} height Height of the image. * @param {string=} opt_alt Optional alt text for when block is collapsed. @@ -70,7 +70,7 @@ Blockly.FieldImage = function(src, width, height, this.altText_ = ''; Blockly.FieldImage.superClass_.constructor.call( - this, src || '', null, opt_config); + this, src, null, opt_config); if (!opt_config) { // If the config wasn't passed, do old configuration. this.flipRtl_ = !!opt_flipRtl; @@ -114,6 +114,13 @@ Blockly.FieldImage = function(src, width, height, }; Blockly.utils.object.inherits(Blockly.FieldImage, Blockly.Field); +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldImage.prototype.DEFAULT_VALUE = ''; + /** * Construct a FieldImage from a JSON arg object, * dereferencing any string table references. diff --git a/core/field_label.js b/core/field_label.js index 666e2ec78..87942a34b 100644 --- a/core/field_label.js +++ b/core/field_label.js @@ -40,9 +40,6 @@ Blockly.FieldLabel = function(opt_value, opt_class, opt_config) { */ this.class_ = null; - if (opt_value == null) { - opt_value = ''; - } Blockly.FieldLabel.superClass_.constructor.call( this, opt_value, null, opt_config); @@ -52,6 +49,13 @@ Blockly.FieldLabel = function(opt_value, opt_class, opt_config) { }; Blockly.utils.object.inherits(Blockly.FieldLabel, Blockly.Field); +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldLabel.prototype.DEFAULT_VALUE = ''; + /** * Construct a FieldLabel from a JSON arg object, * dereferencing any string table references. diff --git a/core/field_multilineinput.js b/core/field_multilineinput.js index 734f4135a..0660aa571 100644 --- a/core/field_multilineinput.js +++ b/core/field_multilineinput.js @@ -43,9 +43,6 @@ goog.require('Blockly.utils.userAgent'); Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) { // TODO: Once this field is documented the opt_config link should point to its // creation documentation, rather than the text input field's. - if (opt_value == null) { - opt_value = ''; - } Blockly.FieldMultilineInput.superClass_.constructor.call(this, opt_value, opt_validator, opt_config); @@ -59,7 +56,6 @@ Blockly.FieldMultilineInput = function(opt_value, opt_validator, opt_config) { Blockly.utils.object.inherits(Blockly.FieldMultilineInput, Blockly.FieldTextInput); - /** * Construct a FieldMultilineInput from a JSON arg object, * dereferencing any string table references. diff --git a/core/field_number.js b/core/field_number.js index 8e49a2abe..061995348 100644 --- a/core/field_number.js +++ b/core/field_number.js @@ -67,7 +67,7 @@ Blockly.FieldNumber = function(opt_value, opt_min, opt_max, opt_precision, this.decimalPlaces_ = null; Blockly.FieldNumber.superClass_.constructor.call( - this, opt_value || 0, opt_validator, opt_config); + this, opt_value, opt_validator, opt_config); if (!opt_config) { // Only do one kind of configuration or the other. this.setConstraints(opt_min, opt_max, opt_precision); @@ -75,6 +75,13 @@ Blockly.FieldNumber = function(opt_value, opt_min, opt_max, opt_precision, }; Blockly.utils.object.inherits(Blockly.FieldNumber, Blockly.FieldTextInput); +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldNumber.prototype.DEFAULT_VALUE = 0; + /** * Construct a FieldNumber from a JSON arg object. * @param {!Object} options A JSON object with options (value, min, max, and diff --git a/core/field_textinput.js b/core/field_textinput.js index 7b1c388c8..4bd367f37 100644 --- a/core/field_textinput.js +++ b/core/field_textinput.js @@ -48,9 +48,6 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) { */ this.spellcheck_ = true; - if (opt_value == null) { - opt_value = ''; - } Blockly.FieldTextInput.superClass_.constructor.call(this, opt_value, opt_validator, opt_config); @@ -90,6 +87,13 @@ Blockly.FieldTextInput = function(opt_value, opt_validator, opt_config) { }; Blockly.utils.object.inherits(Blockly.FieldTextInput, Blockly.Field); +/** + * The default value for this field. + * @type {*} + * @protected + */ +Blockly.FieldTextInput.prototype.DEFAULT_VALUE = ''; + /** * Construct a FieldTextInput from a JSON arg object, * dereferencing any string table references. diff --git a/tests/mocha/.eslintrc.json b/tests/mocha/.eslintrc.json index aa7377a34..705a79397 100644 --- a/tests/mocha/.eslintrc.json +++ b/tests/mocha/.eslintrc.json @@ -15,6 +15,7 @@ "defineStatementBlock": true, "createEventsFireStub": true, "testAWorkspace": true, + "testHelpers" : true, "getSimpleJSON": true, "getXmlArray": true, "getCategoryJSON": true diff --git a/tests/mocha/field_angle_test.js b/tests/mocha/field_angle_test.js index 8fde28c4b..74206c888 100644 --- a/tests/mocha/field_angle_test.js +++ b/tests/mocha/field_angle_test.js @@ -5,255 +5,139 @@ */ suite('Angle Fields', function() { - function assertValue(angleField, expectedValue, opt_expectedText) { - var actualValue = angleField.getValue(); - var actualText = angleField.getText(); - opt_expectedText = opt_expectedText || String(expectedValue); - chai.assert.equal(String(actualValue), String(expectedValue)); - chai.assert.equal(Number(actualValue), expectedValue); - chai.assert.equal(actualText, opt_expectedText); - } - function assertValueDefault(angleField) { - assertValue(angleField, 0); - } - suite('Constructor', function() { - test('Empty', function() { - var angleField = new Blockly.FieldAngle(); - assertValueDefault(angleField); - }); - test('Undefined', function() { - var angleField = new Blockly.FieldAngle(undefined); - assertValueDefault(angleField); - }); - test('NaN', function() { - var angleField = new Blockly.FieldAngle(NaN); - assertValueDefault(angleField); - }); - test('Integer', function() { - var angleField = new Blockly.FieldAngle(1); - assertValue(angleField, 1); - }); - test('Float', function() { - var angleField = new Blockly.FieldAngle(1.5); - assertValue(angleField, 1.5); - }); - test('Integer String', function() { - var angleField = new Blockly.FieldAngle('1'); - assertValue(angleField, 1); - }); - test('Float String', function() { - var angleField = new Blockly.FieldAngle('1.5'); - assertValue(angleField, 1.5); - }); - test('> 360°', function() { - var angleField = new Blockly.FieldAngle(362); - assertValue(angleField, 2); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var angleField = Blockly.FieldAngle.fromJson({}); - assertValueDefault(angleField); - }); - test('Undefined', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:undefined }); - assertValueDefault(angleField); - }); - test('NaN', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:NaN }); - assertValueDefault(angleField); - }); - test('Integer', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:1 }); - assertValue(angleField, 1); - }); - test('Float', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:1.5 }); - assertValue(angleField, 1.5); - }); - test('Integer String', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:'1' }); - assertValue(angleField, 1); - }); - test('Float String', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:'1.5' }); - assertValue(angleField, 1.5); - }); - test('> 360°', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:362 }); - assertValue(angleField, 2); - }); - }); + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + {title: 'NaN', value: NaN}, + {title: 'Non-Parsable String', value: 'bad'}, + {title: 'Infinity', value: Infinity, expectedValue: Infinity}, + {title: 'Negative Infinity', value: -Infinity, expectedValue: -Infinity}, + {title: 'Infinity String', value: 'Infinity', expectedValue: Infinity}, + {title: 'Negative Infinity String', value: '-Infinity', + expectedValue: -Infinity}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ + + var validValueTestCases = [ + {title: 'Integer', value: 1, expectedValue: 1}, + {title: 'Float', value: 1.5, expectedValue: 1.5}, + {title: 'Integer String', value: '1', expectedValue: 1}, + {title: 'Float String', value: '1.5', expectedValue: 1.5}, + {title: '> 360°', value: 362, expectedValue: 2}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = [testCase.value]; + testCase.json = {'angle': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = 0; + /** + * Asserts that the field property values are set to default. + * @param {FieldTemplate} field The field to check. + */ + var assertFieldDefault = function(field) { + testHelpers.assertFieldValue(field, defaultFieldValue); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldAngle} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + testHelpers.assertFieldValue(field, testCase.expectedValue); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldAngle, validValueTestCases, invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldAngle, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { suite('Empty -> New Value', function() { setup(function() { - this.angleField = new Blockly.FieldAngle(); - }); - test('Null', function() { - this.angleField.setValue(null); - assertValueDefault(this.angleField); - }); - test('Undefined', function() { - this.angleField.setValue(undefined); - assertValueDefault(this.angleField); - }); - test('Non-Parsable String', function() { - this.angleField.setValue('bad'); - assertValueDefault(this.angleField); - }); - test('NaN', function() { - this.angleField.setValue(NaN); - assertValueDefault(this.angleField); - }); - test('Integer', function() { - this.angleField.setValue(2); - assertValue(this.angleField, 2); - }); - test('Float', function() { - this.angleField.setValue(2.5); - assertValue(this.angleField, 2.5); - }); - test('Integer String', function() { - this.angleField.setValue('2'); - assertValue(this.angleField, 2); - }); - test('Float', function() { - this.angleField.setValue('2.5'); - assertValue(this.angleField, 2.5); - }); - test('>360°', function() { - this.angleField.setValue(362); - assertValue(this.angleField, 2); - }); - test('Infinity', function() { - this.angleField.setValue(Infinity); - assertValueDefault(this.angleField); - }); - test('Negative Infinity String', function() { - this.angleField.setValue('-Infinity'); - assertValueDefault(this.angleField); + this.field = new Blockly.FieldAngle(); }); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, defaultFieldValue); test('With source block', function() { - this.angleField.setSourceBlock(createTestBlock()); - this.angleField.setValue(2.5); - assertValue(this.angleField, 2.5); + this.field.setSourceBlock(createTestBlock()); + this.field.setValue(2.5); + testHelpers.assertFieldValue(this.field, 2.5); }); }); suite('Value -> New Value', function() { + var initialValue = 1; setup(function() { - this.angleField = new Blockly.FieldAngle(1); + this.field = new Blockly.FieldAngle(initialValue); }); - test('Null', function() { - this.angleField.setValue(null); - assertValue(this.angleField, 1); - }); - test('Undefined', function() { - this.angleField.setValue(undefined); - assertValue(this.angleField, 1); - }); - test('Non-Parsable String', function() { - this.angleField.setValue('bad'); - assertValue(this.angleField, 1); - }); - test('NaN', function() { - this.angleField.setValue(NaN); - assertValue(this.angleField, 1); - }); - test('Integer', function() { - this.angleField.setValue(2); - assertValue(this.angleField, 2); - }); - test('Float', function() { - this.angleField.setValue(2.5); - assertValue(this.angleField, 2.5); - }); - test('Integer String', function() { - this.angleField.setValue('2'); - assertValue(this.angleField, 2); - }); - test('Float', function() { - this.angleField.setValue('2.5'); - assertValue(this.angleField, 2.5); - }); - test('>360°', function() { - this.angleField.setValue(362); - assertValue(this.angleField, 2); - }); - test('Infinity', function() { - this.angleField.setValue(Infinity); - assertValue(this.angleField, 1); - }); - test('Negative Infinity String', function() { - this.angleField.setValue('-Infinity'); - assertValue(this.angleField, 1); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, initialValue); + test('With source block', function() { + this.field.setSourceBlock(createTestBlock()); + this.field.setValue(2.5); + testHelpers.assertFieldValue(this.field, 2.5); }); }); }); suite('Validators', function() { setup(function() { - this.angleField = new Blockly.FieldAngle(1); - this.angleField.htmlInput_ = Object.create(null); - this.angleField.htmlInput_.oldValue_ = '1'; - this.angleField.htmlInput_.untypedDefaultValue_ = 1; - this.stub = sinon.stub(this.angleField, 'resizeEditor_'); + this.field = new Blockly.FieldAngle(1); + this.field.htmlInput_ = Object.create(null); + this.field.htmlInput_.oldValue_ = '1'; + this.field.htmlInput_.untypedDefaultValue_ = 1; + this.stub = sinon.stub(this.field, 'resizeEditor_'); }); teardown(function() { - this.angleField.setValidator(null); - this.angleField.htmlInput_ = null; - if (this.stub) { - this.stub.restore(); - } + sinon.restore(); }); - suite('Null Validator', function() { - setup(function() { - this.angleField.setValidator(function() { - return null; + var testSuites = [ + {title: 'Null Validator', + validator: + function() { + return null; + }, + value: 2, expectedValue: 1}, + {title: 'Force Mult of 30 Validator', + validator: + function(newValue) { + return Math.round(newValue / 30) * 30; + }, + value: 25, expectedValue: 30}, + {title: 'Returns Undefined Validator', validator: function() {}, value: 2, + expectedValue: 2}, + ]; + testSuites.forEach(function(suiteInfo) { + suite(suiteInfo.title, function() { + setup(function() { + this.field.setValidator(suiteInfo.validator); }); - }); - test('When Editing', function() { - this.angleField.isBeingEdited_ = true; - this.angleField.htmlInput_.value = '2'; - this.angleField.onHtmlInputChange_(null); - assertValue(this.angleField, 1, '2'); - this.angleField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.angleField.setValue(2); - assertValue(this.angleField, 1); - }); - }); - suite('Force Mult of 30 Validator', function() { - setup(function() { - this.angleField.setValidator(function(newValue) { - return Math.round(newValue / 30) * 30; + test('When Editing', function() { + this.field.isBeingEdited_ = true; + this.field.htmlInput_.value = String(suiteInfo.value); + this.field.onHtmlInputChange_(null); + testHelpers.assertFieldValue( + this.field, suiteInfo.expectedValue, String(suiteInfo.value)); + }); + test('When Not Editing', function() { + this.field.setValue(suiteInfo.value); + testHelpers.assertFieldValue(this.field, suiteInfo.expectedValue); }); - }); - test('When Editing', function() { - this.angleField.isBeingEdited_ = true; - this.angleField.htmlInput_.value = '25'; - this.angleField.onHtmlInputChange_(null); - assertValue(this.angleField, 30, '25'); - this.angleField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.angleField.setValue(25); - assertValue(this.angleField, 30); - }); - }); - suite('Returns Undefined Validator', function() { - setup(function() { - this.angleField.setValidator(function() {}); - }); - test('When Editing', function() { - this.angleField.isBeingEdited_ = true; - this.angleField.htmlInput_.value = '2'; - this.angleField.onHtmlInputChange_(null); - assertValue(this.angleField, 2); - this.angleField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.angleField.setValue(2); - assertValue(this.angleField, 2); }); }); }); diff --git a/tests/mocha/field_checkbox_test.js b/tests/mocha/field_checkbox_test.js index dfc95f372..7eaac4d5a 100644 --- a/tests/mocha/field_checkbox_test.js +++ b/tests/mocha/field_checkbox_test.js @@ -5,67 +5,68 @@ */ suite('Checkbox Fields', function() { - function assertValue(checkboxField, expectedValue, expectedText) { - var actualValue = checkboxField.getValue(); - var actualText = checkboxField.getText(); - chai.assert.equal(actualValue, expectedValue); - chai.assert.equal(actualText, expectedText); - } - function assertValueDefault(checkboxField) { - assertValue(checkboxField, 'FALSE', 'false'); - } - suite('Constructor', function() { - test('Empty', function() { - var checkboxField = new Blockly.FieldCheckbox(); - assertValueDefault(checkboxField); - }); - test('Undefined', function() { - var checkboxField = new Blockly.FieldCheckbox(undefined); - assertValueDefault(checkboxField); - }); - test('True', function() { - var checkboxField = new Blockly.FieldCheckbox(true); - assertValue(checkboxField, 'TRUE', 'true'); - }); - test('False', function() { - var checkboxField = new Blockly.FieldCheckbox(false); - assertValue(checkboxField, 'FALSE', 'false'); - }); - test('String TRUE', function() { - var checkboxField = new Blockly.FieldCheckbox('TRUE'); - assertValue(checkboxField, 'TRUE', 'true'); - }); - test('String FALSE', function() { - var checkboxField = new Blockly.FieldCheckbox('FALSE'); - assertValue(checkboxField, 'FALSE', 'false'); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({}); - assertValueDefault(checkboxField); - }); - test('Undefined', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: undefined}); - assertValueDefault(checkboxField); - }); - test('True', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: true}); - assertValue(checkboxField, 'TRUE', 'true'); - }); - test('False', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: false}); - assertValue(checkboxField, 'FALSE', 'false'); - }); - test('String TRUE', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: 'TRUE'}); - assertValue(checkboxField, 'TRUE', 'true'); - }); - test('String FALSE', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: 'FALSE'}); - assertValue(checkboxField, 'FALSE', 'false'); - }); - }); + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + {title: 'NaN', value: NaN}, + {title: 'Non-Parsable String', value: 'bad'}, + {title: 'Integer', value: 1}, + {title: 'Float', value: 1.5}, + {title: 'String true', value: 'true'}, + {title: 'String false', value: 'false'}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ + var validValueTestCases = [ + {title: 'Boolean true', value: true, expectedValue: 'TRUE'}, + {title: 'Boolean false', value: false, expectedValue: 'FALSE'}, + {title: 'String TRUE', value: 'TRUE', expectedValue: 'TRUE'}, + {title: 'String FALSE', value: 'FALSE', expectedValue: 'FALSE'}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = [testCase.value]; + testCase.json = {'checked': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = 'FALSE'; + /** + * Asserts that the field property values are set to default. + * @param {!Blockly.FieldNumber} field The field to check. + */ + var assertFieldDefault = function(field) { + testHelpers.assertFieldValue( + field, defaultFieldValue, defaultFieldValue.toLowerCase()); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldNumber} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + testHelpers.assertFieldValue( + field, testCase.expectedValue, testCase.expectedValue.toLowerCase()); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldCheckbox, validValueTestCases, invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldCheckbox, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { suite('True -> New Value', function() { setup(function() { @@ -73,24 +74,24 @@ suite('Checkbox Fields', function() { }); test('Null', function() { this.checkboxField.setValue(null); - assertValue(this.checkboxField, 'TRUE', 'true'); + testHelpers.assertFieldValue(this.checkboxField, 'TRUE', 'true'); }); test('Undefined', function() { this.checkboxField.setValue(undefined); - assertValue(this.checkboxField, 'TRUE', 'true'); + testHelpers.assertFieldValue(this.checkboxField, 'TRUE', 'true'); }); test('Non-Parsable String', function() { this.checkboxField.setValue('bad'); - assertValue(this.checkboxField, 'TRUE', 'true'); + testHelpers.assertFieldValue(this.checkboxField, 'TRUE', 'true'); }); test('False', function() { this.checkboxField.setValue('FALSE'); - assertValue(this.checkboxField, 'FALSE', 'false'); + testHelpers.assertFieldValue(this.checkboxField, 'FALSE', 'false'); }); test('With source block', function() { this.checkboxField.setSourceBlock(createTestBlock()); this.checkboxField.setValue('FALSE'); - assertValue(this.checkboxField, 'FALSE', 'false'); + testHelpers.assertFieldValue(this.checkboxField, 'FALSE', 'false'); }); }); suite('False -> New Value', function() { @@ -99,70 +100,60 @@ suite('Checkbox Fields', function() { }); test('Null', function() { this.checkboxField.setValue(null); - assertValue(this.checkboxField, 'FALSE', 'false'); + testHelpers.assertFieldValue(this.checkboxField, 'FALSE', 'false'); }); test('Undefined', function() { this.checkboxField.setValue(undefined); - assertValue(this.checkboxField, 'FALSE', 'false'); + testHelpers.assertFieldValue(this.checkboxField, 'FALSE', 'false'); }); test('Non-Parsable String', function() { this.checkboxField.setValue('bad'); - assertValue(this.checkboxField, 'FALSE', 'false'); + testHelpers.assertFieldValue(this.checkboxField, 'FALSE', 'false'); }); test('True', function() { this.checkboxField.setValue('TRUE'); - assertValue(this.checkboxField, 'TRUE', 'true'); + testHelpers.assertFieldValue(this.checkboxField, 'TRUE', 'true'); }); }); }); suite('Validators', function() { setup(function() { - this.checkboxField = new Blockly.FieldCheckbox(true); + this.field = new Blockly.FieldCheckbox(true); }); - teardown(function() { - this.checkboxField.setValidator(null); - }); - suite('Null Validator', function() { - setup(function() { - this.checkboxField.setValidator(function() { - return null; + var testSuites = [ + {title: 'Null Validator', + validator: + function() { + return null; + }, + value: 'FALSE', expectedValue: 'TRUE'}, + {title: 'Always True Validator', + validator: + function() { + return 'TRUE'; + }, + value: 'FALSE', expectedValue: 'TRUE'}, + {title: 'Always False Validator', + validator: + function() { + return 'TRUE'; + }, + value: 'FALSE', expectedValue: 'TRUE'}, + {title: 'Returns Undefined Validator', validator: function() {}, + value: 'FALSE', expectedValue: 'FALSE'}, + ]; + testSuites.forEach(function(suiteInfo) { + suite(suiteInfo.title, function() { + setup(function() { + this.field.setValidator(suiteInfo.validator); }); - }); - test('New Value', function() { - this.checkboxField.setValue('FALSE'); - assertValue(this.checkboxField, 'TRUE', 'true'); - }); - }); - suite('Always True Validator', function() { - setup(function() { - this.checkboxField.setValidator(function() { - return 'TRUE'; + test('New Value', function() { + this.field.setValue(suiteInfo.value); + testHelpers.assertFieldValue( + this.field, suiteInfo.expectedValue, + String(suiteInfo.expectedValue).toLowerCase()); }); }); - test('New Value', function() { - this.checkboxField.setValue('FALSE'); - assertValue(this.checkboxField, 'TRUE', 'true'); - }); - }); - suite('Always False Validator', function() { - setup(function() { - this.checkboxField.setValidator(function() { - return 'FALSE'; - }); - }); - test('New Value', function() { - this.checkboxField.setValue('TRUE'); - assertValue(this.checkboxField, 'FALSE', 'false'); - }); - }); - suite('Returns Undefined Validator', function() { - setup(function() { - this.checkboxField.setValidator(function() {}); - }); - test('New Value', function() { - this.checkboxField.setValue('FALSE'); - assertValue(this.checkboxField, 'FALSE', 'false'); - }); }); }); suite('Customizations', function() { diff --git a/tests/mocha/field_colour_test.js b/tests/mocha/field_colour_test.js index dbadc14c8..71d1d352a 100644 --- a/tests/mocha/field_colour_test.js +++ b/tests/mocha/field_colour_test.js @@ -5,132 +5,97 @@ */ suite('Colour Fields', function() { - function assertValue(colourField, expectedValue, expectedText) { - var actualValue = colourField.getValue(); - var actualText = colourField.getText(); - chai.assert.equal(actualValue, expectedValue); - chai.assert.equal(actualText, expectedText); - } - function assertValueDefault(colourField) { - var expectedValue = Blockly.FieldColour.COLOURS[0]; - var expectedText = expectedValue; - var m = expectedValue.match(/^#(.)\1(.)\2(.)\3$/); - if (m) { - expectedText = '#' + m[1] + m[2] + m[3]; - } - assertValue(colourField, expectedValue, expectedText); - } + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + {title: 'NaN', value: NaN}, + {title: 'Non-Parsable String', value: 'bad-string'}, + {title: 'Integer', value: 1}, + {title: 'Float', value: 1.5}, + {title: 'Infinity', value: Infinity, expectedValue: Infinity}, + {title: 'Negative Infinity', value: -Infinity, expectedValue: -Infinity}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ - setup(function() { - this.previousColours = Blockly.FieldColour.COLOURS; - Blockly.FieldColour.Colours = [ - '#ffffff', '#ff0000', '#00ff00', '#0000ff', '#ffffff' - ]; - }); - teardown(function() { - Blockly.FieldColour.Colours = this.previousColours; - }); - suite('Constructor', function() { - test('Empty', function() { - var colourField = new Blockly.FieldColour(); - assertValueDefault(colourField); - }); - test('Undefined', function() { - var colourField = new Blockly.FieldColour(undefined); - assertValueDefault(colourField); - }); - test('#AAAAAA', function() { - var colourField = new Blockly.FieldColour('#AAAAAA'); - assertValue(colourField, '#aaaaaa', '#aaa'); - }); - test('#aaaaaa', function() { - var colourField = new Blockly.FieldColour('#aaaaaa'); - assertValue(colourField, '#aaaaaa', '#aaa'); - }); - test('#AAAA00', function() { - var colourField = new Blockly.FieldColour('#AAAA00'); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('#aaaa00', function() { - var colourField = new Blockly.FieldColour('#aaaa00'); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('#BCBCBC', function() { - var colourField = new Blockly.FieldColour('#BCBCBC'); - assertValue(colourField, '#bcbcbc', '#bcbcbc'); - }); - test('#bcbcbc', function() { - var colourField = new Blockly.FieldColour('#bcbcbc'); - assertValue(colourField, '#bcbcbc', '#bcbcbc'); - }); - test('#AA0', function() { - var colourField = new Blockly.FieldColour('#AA0'); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('#aa0', function() { - var colourField = new Blockly.FieldColour('#aa0'); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('rgb(170, 170, 0)', function() { - var colourField = new Blockly.FieldColour('rgb(170, 170, 0)'); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('red', function() { - var colourField = new Blockly.FieldColour('red'); - assertValue(colourField, '#ff0000', '#f00'); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var colourField = new Blockly.FieldColour.fromJson({}); - assertValueDefault(colourField); - }); - test('Undefined', function() { - var colourField = new Blockly.FieldColour.fromJson({ colour:undefined }); - assertValueDefault(colourField); - }); - test('#AAAAAA', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#AAAAAA' }); - assertValue(colourField, '#aaaaaa', '#aaa'); - }); - test('#aaaaaa', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#aaaaaa' }); - assertValue(colourField, '#aaaaaa', '#aaa'); - }); - test('#AAAA00', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#AAAA00' }); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('#aaaa00', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#aaaa00' }); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('#BCBCBC', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#BCBCBC' }); - assertValue(colourField, '#bcbcbc', '#bcbcbc'); - }); - test('#bcbcbc', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#bcbcbc' }); - assertValue(colourField, '#bcbcbc', '#bcbcbc'); - }); - test('#AA0', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#AA0' }); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('#aa0', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: '#aa0' }); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('rgb(170, 170, 0)', function() { - var colourField = Blockly.FieldColour.fromJson( - { colour: 'rgb(170, 170, 0)' }); - assertValue(colourField, '#aaaa00', '#aa0'); - }); - test('red', function() { - var colourField = Blockly.FieldColour.fromJson({ colour: 'red' }); - assertValue(colourField, '#ff0000', '#f00'); - }); - }); + var validValueTestCases = [ + {title: '#AAAAAA', value: '#AAAAAA', expectedValue: '#aaaaaa', + expectedText: '#aaa'}, + {title: '#aaaaaa', value: '#aaaaaa', expectedValue: '#aaaaaa', + expectedText: '#aaa'}, + {title: '#AAAA00', value: '#AAAA00', expectedValue: '#aaaa00', + expectedText: '#aa0'}, + {title: '#aaaA00', value: '#aaaA00', expectedValue: '#aaaa00', + expectedText: '#aa0'}, + {title: '#BCBCBC', value: '#BCBCBC', expectedValue: '#bcbcbc', + expectedText: '#bcbcbc'}, + {title: '#bcbcbc', value: '#bcbcbc', expectedValue: '#bcbcbc', + expectedText: '#bcbcbc'}, + {title: '#AA0', value: '#AA0', expectedValue: '#aaaa00', + expectedText: '#aa0'}, + {title: '#aa0', value: '#aa0', expectedValue: '#aaaa00', + expectedText: '#aa0'}, + {title: 'rgb(170, 170, 0)', value: 'rgb(170, 170, 0)', + expectedValue: '#aaaa00', expectedText: '#aa0'}, + {title: 'red', value: 'red', expectedValue: '#ff0000', + expectedText: '#f00'}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = [testCase.value]; + testCase.json = {'colour': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = Blockly.FieldColour.COLOURS[0]; + /** + * The expected default text for the field being tested. + * @type {*} + */ + var defaultTextValue = ( + function() { + var expectedText = defaultFieldValue; + var m = defaultFieldValue.match(/^#(.)\1(.)\2(.)\3$/); + if (m) { + expectedText = '#' + m[1] + m[2] + m[3]; + } + return expectedText; + })(); + /** + * Asserts that the field property values are set to default. + * @param {FieldTemplate} field The field to check. + */ + var assertFieldDefault = function(field) { + testHelpers.assertFieldValue(field, defaultFieldValue, defaultTextValue); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldAngle} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + testHelpers.assertFieldValue( + field, testCase.expectedValue, testCase.expectedText); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldColour, validValueTestCases, invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldColour, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { suite('Empty -> New Value', function() { setup(function() { @@ -138,40 +103,40 @@ suite('Colour Fields', function() { }); test('Null', function() { this.colourField.setValue(null); - assertValueDefault(this.colourField); + assertFieldDefault(this.colourField); }); test('Undefined', function() { this.colourField.setValue(undefined); - assertValueDefault(this.colourField); + assertFieldDefault(this.colourField); }); test('Non-Parsable String', function() { this.colourField.setValue('not_a_colour'); - assertValueDefault(this.colourField); + assertFieldDefault(this.colourField); }); test('#000000', function() { this.colourField.setValue('#000000'); - assertValue(this.colourField, '#000000', '#000'); + testHelpers.assertFieldValue(this.colourField, '#000000', '#000'); }); test('#bcbcbc', function() { this.colourField.setValue('#bcbcbc'); - assertValue(this.colourField, '#bcbcbc', '#bcbcbc'); + testHelpers.assertFieldValue(this.colourField, '#bcbcbc', '#bcbcbc'); }); test('#aa0', function() { this.colourField.setValue('#aa0'); - assertValue(this.colourField, '#aaaa00', '#aa0'); + testHelpers.assertFieldValue(this.colourField, '#aaaa00', '#aa0'); }); test('rgb(170, 170, 0)', function() { this.colourField.setValue('rgb(170, 170, 0)'); - assertValue(this.colourField, '#aaaa00', '#aa0'); + testHelpers.assertFieldValue(this.colourField, '#aaaa00', '#aa0'); }); test('red', function() { this.colourField.setValue('red'); - assertValue(this.colourField, '#ff0000', '#f00'); + testHelpers.assertFieldValue(this.colourField, '#ff0000', '#f00'); }); test('With source block', function() { this.colourField.setSourceBlock(createTestBlock()); this.colourField.setValue('#bcbcbc'); - assertValue(this.colourField, '#bcbcbc', '#bcbcbc'); + testHelpers.assertFieldValue(this.colourField, '#bcbcbc', '#bcbcbc'); }); }); suite('Value -> New Value', function() { @@ -180,75 +145,69 @@ suite('Colour Fields', function() { }); test('Null', function() { this.colourField.setValue(null); - assertValue(this.colourField, '#aaaaaa', '#aaa'); + testHelpers.assertFieldValue(this.colourField, '#aaaaaa', '#aaa'); }); test('Undefined', function() { this.colourField.setValue(undefined); - assertValue(this.colourField, '#aaaaaa', '#aaa'); + testHelpers.assertFieldValue(this.colourField, '#aaaaaa', '#aaa'); }); test('Non-Parsable String', function() { this.colourField.setValue('not_a_colour'); - assertValue(this.colourField, '#aaaaaa', '#aaa'); + testHelpers.assertFieldValue(this.colourField, '#aaaaaa', '#aaa'); }); test('#000000', function() { this.colourField.setValue('#000000'); - assertValue(this.colourField, '#000000', '#000'); + testHelpers.assertFieldValue(this.colourField, '#000000', '#000'); }); test('#bcbcbc', function() { this.colourField.setValue('#bcbcbc'); - assertValue(this.colourField, '#bcbcbc', '#bcbcbc'); + testHelpers.assertFieldValue(this.colourField, '#bcbcbc', '#bcbcbc'); }); test('#aa0', function() { this.colourField.setValue('#aa0'); - assertValue(this.colourField, '#aaaa00', '#aa0'); + testHelpers.assertFieldValue(this.colourField, '#aaaa00', '#aa0'); }); test('rgb(170, 170, 0)', function() { this.colourField.setValue('rgb(170, 170, 0)'); - assertValue(this.colourField, '#aaaa00', '#aa0'); + testHelpers.assertFieldValue(this.colourField, '#aaaa00', '#aa0'); }); test('red', function() { this.colourField.setValue('red'); - assertValue(this.colourField, '#ff0000', '#f00'); + testHelpers.assertFieldValue(this.colourField, '#ff0000', '#f00'); }); }); }); suite('Validators', function() { setup(function() { - this.colourField = new Blockly.FieldColour('#aaaaaa'); + this.field = new Blockly.FieldColour('#aaaaaa'); }); - teardown(function() { - this.colourField.setValidator(null); - }); - suite('Null Validator', function() { - setup(function() { - this.colourField.setValidator(function() { - return null; + var testSuites = [ + {title: 'Null Validator', + validator: + function() { + return null; + }, + value: '#000000', expectedValue: '#aaaaaa', expectedText: '#aaa'}, + {title: 'Force Full Red Validator', + validator: + function(newValue) { + return '#ff' + newValue.substr(3, 4); + }, + value: '#000000', expectedValue: '#ff0000', expectedText: '#f00'}, + {title: 'Returns Undefined Validator', validator: function() {}, + value: '#000000', expectedValue: '#000000', expectedText: '#000'}, + ]; + testSuites.forEach(function(suiteInfo) { + suite(suiteInfo.title, function() { + setup(function() { + this.field.setValidator(suiteInfo.validator); }); - }); - test('New Value', function() { - this.colourField.setValue('#000000'); - assertValue(this.colourField, '#aaaaaa', '#aaa'); - }); - }); - suite('Force Full Red Validator', function() { - setup(function() { - this.colourField.setValidator(function(newValue) { - return '#ff' + newValue.substr(3, 4); + test('New Value', function() { + this.field.setValue(suiteInfo.value); + testHelpers.assertFieldValue( + this.field, suiteInfo.expectedValue, suiteInfo.expectedText); }); }); - test('New Value', function() { - this.colourField.setValue('#000000'); - assertValue(this.colourField, '#ff0000', '#f00'); - }); - }); - suite('Returns Undefined Validator', function() { - setup(function() { - this.colourField.setValidator(function() {}); - }); - test('New Value', function() { - this.colourField.setValue('#000000'); - assertValue(this.colourField, '#000000', '#000'); - }); }); }); suite('Customizations', function() { diff --git a/tests/mocha/field_label_serializable_test.js b/tests/mocha/field_label_serializable_test.js index 9aa2baebf..8b7954a68 100644 --- a/tests/mocha/field_label_serializable_test.js +++ b/tests/mocha/field_label_serializable_test.js @@ -5,178 +5,109 @@ */ suite('Label Serializable Fields', function() { - function assertValue(labelField, expectedValue) { - var actualValue = labelField.getValue(); - var actualText = labelField.getText(); - chai.assert.equal(actualValue, expectedValue); - chai.assert.equal(actualText, expectedValue); - } - function assertValueDefault(labelField) { - assertValue(labelField, ''); - } - function assertHasClass(labelField, cssClass) { - labelField.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); - labelField.constants_ = { - FIELD_TEXT_BASELINE_Y: 13 - }; - labelField.initView(); - chai.assert.isTrue(Blockly.utils.dom.hasClass( - labelField.textElement_, cssClass)); - } - function assertDoesNotHaveClass(labelField, cssClass) { - labelField.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); - labelField.constants_ = { - FIELD_TEXT_BASELINE_Y: 13 - }; - labelField.initView(); - chai.assert.isFalse(Blockly.utils.dom.hasClass( - labelField.textElement_, cssClass)); - } - suite('Constructor', function() { - test('Empty', function() { - var labelField = new Blockly.FieldLabelSerializable(); - assertValueDefault(labelField); - }); - test('Null', function() { - var labelField = new Blockly.FieldLabelSerializable(null); - assertValueDefault(labelField); - }); - test('Undefined', function() { - var labelField = new Blockly.FieldLabelSerializable(undefined); - assertValueDefault(labelField); - }); - test('String', function() { - var labelField = new Blockly.FieldLabelSerializable('value'); - assertValue(labelField, 'value'); - }); - test('Number (Truthy)', function() { - var labelField = new Blockly.FieldLabelSerializable(1); - assertValue(labelField, '1'); - }); - test('Number (Falsy)', function() { - var labelField = new Blockly.FieldLabelSerializable(0); - assertValue(labelField, '0'); - }); - test('Boolean True', function() { - var labelField = new Blockly.FieldLabelSerializable(true); - assertValue(labelField, 'true'); - }); - test('Boolean False', function() { - var labelField = new Blockly.FieldLabelSerializable(false); - assertValue(labelField, 'false'); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var labelField = new Blockly.FieldLabelSerializable.fromJson({}); - assertValueDefault(labelField); - }); - test('Null', function() { - var labelField = new Blockly.FieldLabelSerializable - .fromJson({ text:null }); - assertValueDefault(labelField); - }); - test('Undefined', function() { - var labelField = new Blockly.FieldLabelSerializable - .fromJson({ text:undefined }); - assertValueDefault(labelField); - }); - test('String', function() { - var labelField = Blockly.FieldLabelSerializable - .fromJson({ text:'value' }); - assertValue(labelField, 'value'); - }); - test('Number (Truthy)', function() { - var labelField = Blockly.FieldLabelSerializable.fromJson({ text:1 }); - assertValue(labelField, '1'); - }); - test('Number (Falsy)', function() { - var labelField = Blockly.FieldLabelSerializable.fromJson({ text:0 }); - assertValue(labelField, '0'); - }); - test('Boolean True', function() { - var labelField = Blockly.FieldLabelSerializable.fromJson({ text:true }); - assertValue(labelField, 'true'); - }); - test('Boolean False', function() { - var labelField = Blockly.FieldLabelSerializable.fromJson({ text:false }); - assertValue(labelField, 'false'); - }); - }); + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ + var validValueTestCases = [ + {title: 'String', value: 'value', expectedValue: 'value'}, + {title: 'Boolean true', value: true, expectedValue: 'true'}, + {title: 'Boolean false', value: false, expectedValue: 'false'}, + {title: 'Number (Truthy)', value: 1, expectedValue: '1'}, + {title: 'Number (Falsy)', value: 0, expectedValue: '0'}, + {title: 'NaN', value: NaN, expectedValue: 'NaN'}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = [testCase.value]; + testCase.json = {'text': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = ''; + /** + * Asserts that the field property values are set to default. + * @param {!Blockly.FieldNumber} field The field to check. + */ + var assertFieldDefault = function(field) { + testHelpers.assertFieldValue(field, defaultFieldValue); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldNumber} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + testHelpers.assertFieldValue(field, testCase.expectedValue); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldLabelSerializable, validValueTestCases, + invalidValueTestCases, validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldLabelSerializable, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { suite('Empty -> New Value', function() { setup(function() { - this.labelField = new Blockly.FieldLabelSerializable(); - }); - test('Null', function() { - this.labelField.setValue(null); - assertValueDefault(this.labelField); - }); - test('Undefined', function() { - this.labelField.setValue(undefined); - assertValueDefault(this.labelField); - }); - test('New String', function() { - this.labelField.setValue('newValue'); - assertValue(this.labelField, 'newValue'); - }); - test('Number (Truthy)', function() { - this.labelField.setValue(1); - assertValue(this.labelField, '1'); - }); - test('Number (Falsy)', function() { - this.labelField.setValue(0); - assertValue(this.labelField, '0'); - }); - test('Boolean True', function() { - this.labelField.setValue(true); - assertValue(this.labelField, 'true'); - }); - test('Boolean False', function() { - this.labelField.setValue(false); - assertValue(this.labelField, 'false'); + this.field = new Blockly.FieldLabelSerializable(); }); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, defaultFieldValue); test('With source block', function() { - this.labelField.setSourceBlock(createTestBlock()); - this.labelField.setValue('newValue'); - assertValue(this.labelField, 'newValue'); + this.field.setSourceBlock(createTestBlock()); + this.field.setValue('value'); + testHelpers.assertFieldValue(this.field, 'value'); }); }); suite('Value -> New Value', function() { + var initialValue = 'oldValue'; setup(function() { - this.labelField = new Blockly.FieldLabelSerializable('value'); + this.field = new Blockly.FieldLabelSerializable(initialValue); }); - test('Null', function() { - this.labelField.setValue(null); - assertValue(this.labelField, 'value'); - }); - test('Undefined', function() { - this.labelField.setValue(undefined); - assertValue(this.labelField, 'value'); - }); - test('New String', function() { - this.labelField.setValue('newValue'); - assertValue(this.labelField, 'newValue'); - }); - test('Number (Truthy)', function() { - this.labelField.setValue(1); - assertValue(this.labelField, '1'); - }); - test('Number (Falsy)', function() { - this.labelField.setValue(0); - assertValue(this.labelField, '0'); - }); - test('Boolean True', function() { - this.labelField.setValue(true); - assertValue(this.labelField, 'true'); - }); - test('Boolean False', function() { - this.labelField.setValue(false); - assertValue(this.labelField, 'false'); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, initialValue); + test('With source block', function() { + this.field.setSourceBlock(createTestBlock()); + this.field.setValue('value'); + testHelpers.assertFieldValue(this.field, 'value'); }); }); }); + suite('Customizations', function() { + function assertHasClass(labelField, cssClass) { + labelField.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); + labelField.constants_ = { + FIELD_TEXT_BASELINE_Y: 13 + }; + labelField.initView(); + chai.assert.isTrue(Blockly.utils.dom.hasClass( + labelField.textElement_, cssClass)); + } + function assertDoesNotHaveClass(labelField, cssClass) { + labelField.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); + labelField.constants_ = { + FIELD_TEXT_BASELINE_Y: 13 + }; + labelField.initView(); + chai.assert.isFalse(Blockly.utils.dom.hasClass( + labelField.textElement_, cssClass)); + } test('JS Constructor', function() { var field = new Blockly.FieldLabelSerializable('text', 'testClass'); assertHasClass(field, 'testClass'); diff --git a/tests/mocha/field_label_test.js b/tests/mocha/field_label_test.js index 2e7910bbf..62a888aae 100644 --- a/tests/mocha/field_label_test.js +++ b/tests/mocha/field_label_test.js @@ -5,167 +5,112 @@ */ suite('Label Fields', function() { - function assertValue(labelField, expectedValue) { - var actualValue = labelField.getValue(); - var actualText = labelField.getText(); - chai.assert.equal(actualValue, expectedValue); - chai.assert.equal(actualText, expectedValue); - } - function assertValueDefault(labelField) { - assertValue(labelField, ''); - } - function assertHasClass(labelField, cssClass) { - labelField.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); - labelField.constants_ = { - FIELD_TEXT_BASELINE_Y: 13 - }; - labelField.initView(); - chai.assert.isTrue(Blockly.utils.dom.hasClass( - labelField.textElement_, cssClass)); - } - function assertDoesNotHaveClass(labelField, cssClass) { - labelField.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); - labelField.constants_ = { - FIELD_TEXT_BASELINE_Y: 13 - }; - labelField.initView(); - chai.assert.isFalse(Blockly.utils.dom.hasClass( - labelField.textElement_, cssClass)); - } - suite('Constructor', function() { - test('Empty', function() { - var labelField = new Blockly.FieldLabel(); - assertValueDefault(labelField); - }); - test('Undefined', function() { - var labelField = new Blockly.FieldLabel(undefined); - assertValueDefault(labelField); - }); - test('String', function() { - var labelField = new Blockly.FieldLabel('value'); - assertValue(labelField, 'value'); - }); - test('Number (Truthy)', function() { - var labelField = new Blockly.FieldLabel(1); - assertValue(labelField, '1'); - }); - test('Number (Falsy)', function() { - var labelField = new Blockly.FieldLabel(0); - assertValue(labelField, '0'); - }); - test('Boolean True', function() { - var labelField = new Blockly.FieldLabel(true); - assertValue(labelField, 'true'); - }); - test('Boolean False', function() { - var labelField = new Blockly.FieldLabel(false); - assertValue(labelField, 'false'); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var labelField = new Blockly.FieldLabel.fromJson({}); - assertValueDefault(labelField); - }); - test('Undefined', function() { - var labelField = new Blockly.FieldLabel.fromJson({ text:undefined }); - assertValueDefault(labelField); - }); - test('String', function() { - var labelField = Blockly.FieldLabel.fromJson({ text:'value' }); - assertValue(labelField, 'value'); - }); - test('Number (Truthy)', function() { - var labelField = Blockly.FieldLabel.fromJson({ text:1 }); - assertValue(labelField, '1'); - }); - test('Number (Falsy)', function() { - var labelField = Blockly.FieldLabel.fromJson({ text:0 }); - assertValue(labelField, '0'); - }); - test('Boolean True', function() { - var labelField = Blockly.FieldLabel.fromJson({ text:true }); - assertValue(labelField, 'true'); - }); - test('Boolean False', function() { - var labelField = Blockly.FieldLabel.fromJson({ text:false }); - assertValue(labelField, 'false'); - }); - }); + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ + var validValueTestCases = [ + {title: 'String', value: 'value', expectedValue: 'value'}, + {title: 'Boolean true', value: true, expectedValue: 'true'}, + {title: 'Boolean false', value: false, expectedValue: 'false'}, + {title: 'Number (Truthy)', value: 1, expectedValue: '1'}, + {title: 'Number (Falsy)', value: 0, expectedValue: '0'}, + {title: 'NaN', value: NaN, expectedValue: 'NaN'}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = [testCase.value]; + testCase.json = {'text': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = ''; + /** + * Asserts that the field property values are set to default. + * @param {!Blockly.FieldNumber} field The field to check. + */ + var assertFieldDefault = function(field) { + testHelpers.assertFieldValue(field, defaultFieldValue); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldNumber} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + testHelpers.assertFieldValue(field, testCase.expectedValue); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldLabel, validValueTestCases, invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldLabel, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { suite('Empty -> New Value', function() { setup(function() { - this.labelField = new Blockly.FieldLabel(); - }); - test('Null', function() { - this.labelField.setValue(null); - assertValueDefault(this.labelField); - }); - test('Undefined', function() { - this.labelField.setValue(undefined); - assertValueDefault(this.labelField); - }); - test('New String', function() { - this.labelField.setValue('newValue'); - assertValue(this.labelField, 'newValue'); - }); - test('Number (Truthy)', function() { - this.labelField.setValue(1); - assertValue(this.labelField, '1'); - }); - test('Number (Falsy)', function() { - this.labelField.setValue(0); - assertValue(this.labelField, '0'); - }); - test('Boolean True', function() { - this.labelField.setValue(true); - assertValue(this.labelField, 'true'); - }); - test('Boolean False', function() { - this.labelField.setValue(false); - assertValue(this.labelField, 'false'); + this.field = new Blockly.FieldLabel(); }); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, defaultFieldValue); test('With source block', function() { - this.labelField.setSourceBlock(createTestBlock()); - this.labelField.setValue('newValue'); - assertValue(this.labelField, 'newValue'); + this.field.setSourceBlock(createTestBlock()); + this.field.setValue('value'); + testHelpers.assertFieldValue(this.field, 'value'); }); }); suite('Value -> New Value', function() { + var initialValue = 'oldValue'; setup(function() { - this.labelField = new Blockly.FieldLabel('value'); + this.field = new Blockly.FieldLabel(initialValue); }); - test('Null', function() { - this.labelField.setValue(null); - assertValue(this.labelField, 'value'); - }); - test('Undefined', function() { - this.labelField.setValue(undefined); - assertValue(this.labelField, 'value'); - }); - test('New String', function() { - this.labelField.setValue('newValue'); - assertValue(this.labelField, 'newValue'); - }); - test('Number (Truthy)', function() { - this.labelField.setValue(1); - assertValue(this.labelField, '1'); - }); - test('Number (Falsy)', function() { - this.labelField.setValue(0); - assertValue(this.labelField, '0'); - }); - test('Boolean True', function() { - this.labelField.setValue(true); - assertValue(this.labelField, 'true'); - }); - test('Boolean False', function() { - this.labelField.setValue(false); - assertValue(this.labelField, 'false'); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, initialValue); + test('With source block', function() { + this.field.setSourceBlock(createTestBlock()); + this.field.setValue('value'); + testHelpers.assertFieldValue(this.field, 'value'); }); }); }); + suite('Customizations', function() { + function assertHasClass(labelField, cssClass) { + labelField.fieldGroup_ = + Blockly.utils.dom.createSvgElement('g', {}, null); + labelField.constants_ = { + FIELD_TEXT_BASELINE_Y: 13 + }; + labelField.initView(); + chai.assert.isTrue(Blockly.utils.dom.hasClass( + labelField.textElement_, cssClass)); + } + function assertDoesNotHaveClass(labelField, cssClass) { + labelField.fieldGroup_ = + Blockly.utils.dom.createSvgElement('g', {}, null); + labelField.constants_ = { + FIELD_TEXT_BASELINE_Y: 13 + }; + labelField.initView(); + chai.assert.isFalse(Blockly.utils.dom.hasClass( + labelField.textElement_, cssClass)); + } + test('JS Constructor', function() { var field = new Blockly.FieldLabel('text', 'testClass'); assertHasClass(field, 'testClass'); diff --git a/tests/mocha/field_number_test.js b/tests/mocha/field_number_test.js index fcb74d4ab..b18bb1c0e 100644 --- a/tests/mocha/field_number_test.js +++ b/tests/mocha/field_number_test.js @@ -5,383 +5,212 @@ */ suite('Number Fields', function() { - function assertValue(numberField, expectedValue, opt_expectedText) { - var actualValue = numberField.getValue(); - var actualText = numberField.getText(); - opt_expectedText = opt_expectedText || String(expectedValue); - chai.assert.equal(String(actualValue), String(expectedValue)); - chai.assert.equal(Number(actualValue), expectedValue); - chai.assert.equal(actualText, opt_expectedText); - } - function assertValueDefault(numberField) { - assertValue(numberField, 0); - } - function assertNumberField(numberField, expectedMin, expectedMax, + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + {title: 'NaN', value: NaN}, + {title: 'Non-Parsable String', value: 'bad'}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ + var validValueTestCases = [ + {title: 'Integer', value: 1, expectedValue: 1}, + {title: 'Float', value: 1.5, expectedValue: 1.5}, + {title: 'Integer String', value: '1', expectedValue: 1}, + {title: 'Float String', value: '1.5', expectedValue: 1.5}, + {title: 'Infinity', value: Infinity, expectedValue: Infinity}, + {title: 'Negative Infinity', value: -Infinity, expectedValue: -Infinity}, + {title: 'Infinity String', value: 'Infinity', expectedValue: Infinity}, + {title: 'Negative Infinity String', value: '-Infinity', + expectedValue: -Infinity}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = Array(4).fill(testCase.value); + testCase.json = {'value': testCase.value, 'min': testCase.value, + 'max': testCase.value, 'precision': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = 0; + /** + * Asserts that the field property values are as expected. + * @param {!Blockly.FieldNumber} field The field to check. + * @param {!number} expectedMin The expected min. + * @param {!number} expectedMax The expected max. + * @param {!number} expectedPrecision The expected precision. + * @param {!number} expectedValue The expected value. + */ + function assertNumberField(field, expectedMin, expectedMax, expectedPrecision, expectedValue) { - assertValue(numberField, expectedValue); - chai.assert.equal(numberField.getMin(), expectedMin); - chai.assert.equal(numberField.getMax(), expectedMax); - chai.assert.equal(numberField.getPrecision(), expectedPrecision); + testHelpers.assertFieldValue(field, expectedValue); + chai.assert.equal(field.getMin(), expectedMin, 'Min'); + chai.assert.equal(field.getMax(), expectedMax, 'Max'); + chai.assert.equal( + field.getPrecision(), expectedPrecision, 'Precision'); } - function assertNumberFieldDefault(numberField) { - assertNumberField(numberField, -Infinity, Infinity, 0, 0); - } - function createNumberFieldSameValuesConstructor(value) { - return new Blockly.FieldNumber(value, value, value, value); - } - function createNumberFieldSameValuesJson(value) { - return Blockly.FieldNumber.fromJson( - { 'value': value, min: value, max: value, precision: value }); - } - function assertNumberFieldSameValues(numberField, value) { - assertNumberField(numberField, value, value, value, value); - } - suite('Constructor', function() { - test('Empty', function() { - var numberField = new Blockly.FieldNumber(); - assertNumberFieldDefault(numberField); - }); - test('Undefined', function() { - var numberField = createNumberFieldSameValuesConstructor(undefined); - assertNumberFieldDefault(numberField); - }); - test('NaN', function() { - var numberField = createNumberFieldSameValuesConstructor(NaN); - assertNumberFieldDefault(numberField); - }); - test('Integer', function() { - var numberField = createNumberFieldSameValuesConstructor(1); - assertNumberFieldSameValues(numberField, 1); - }); - test('Float', function() { - var numberField = createNumberFieldSameValuesConstructor(1.5); - assertNumberFieldSameValues(numberField, 1.5); - }); - test('Integer String', function() { - var numberField = createNumberFieldSameValuesConstructor('1'); - assertNumberFieldSameValues(numberField, 1); - }); - test('Float String', function() { - var numberField = createNumberFieldSameValuesConstructor('1.5'); - assertNumberFieldSameValues(numberField, 1.5); - }); - test('Infinity', function() { - var numberField = createNumberFieldSameValuesConstructor('Infinity'); - assertNumberFieldSameValues(numberField, Infinity); - }); - test('Negative Infinity String', function() { - var numberField = createNumberFieldSameValuesConstructor('-Infinity'); - assertNumberFieldSameValues(numberField, -Infinity); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var numberField = Blockly.FieldNumber.fromJson({}); - assertNumberFieldDefault(numberField); - }); - test('Undefined', function() { - var numberField = createNumberFieldSameValuesJson(undefined); - assertNumberFieldDefault(numberField); - }); - test('NaN', function() { - var numberField = createNumberFieldSameValuesJson(NaN); - assertNumberFieldDefault(numberField); - }); - test('Integer', function() { - var numberField = createNumberFieldSameValuesJson(1); - assertNumberFieldSameValues(numberField, 1); - }); - test('Float', function() { - var numberField = createNumberFieldSameValuesJson(1.5); - assertNumberFieldSameValues(numberField, 1.5); - }); - test('Integer String', function() { - var numberField = createNumberFieldSameValuesJson('1'); - assertNumberFieldSameValues(numberField, 1); - }); - test('Float String', function() { - var numberField = createNumberFieldSameValuesJson('1.5'); - assertNumberFieldSameValues(numberField, 1.5); - }); - test('Infinity', function() { - var numberField = createNumberFieldSameValuesJson('Infinity'); - assertNumberFieldSameValues(numberField, Infinity); - }); - test('Negative Infinity String', function() { - var numberField = createNumberFieldSameValuesJson('-Infinity'); - assertNumberFieldSameValues(numberField, -Infinity); - }); - }); + /** + * Asserts that the field property values are set to default. + * @param {!Blockly.FieldNumber} field The field to check. + */ + var assertFieldDefault = function(field) { + assertNumberField(field, -Infinity, Infinity, 0, defaultFieldValue); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldNumber} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + assertNumberField( + field, testCase.expectedValue, testCase.expectedValue, + testCase.expectedValue, testCase.expectedValue); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldNumber, validValueTestCases, invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldNumber, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { - suite('Value Types', function() { - suite('Empty -> New Value', function() { - setup(function() { - this.numberField = new Blockly.FieldNumber(); - }); - test('Null', function() { - this.numberField.setValue(null); - assertValueDefault(this.numberField); - }); - test('Undefined', function() { - this.numberField.setValue(undefined); - assertValueDefault(this.numberField); - }); - test('Non-Parsable String', function() { - this.numberField.setValue('bad'); - assertValueDefault(this.numberField); - }); - test('NaN', function() { - this.numberField.setValue(NaN); - assertValueDefault(this.numberField); - }); - test('Integer', function() { - this.numberField.setValue(2); - assertValue(this.numberField, 2); - }); - test('Float', function() { - this.numberField.setValue(2.5); - assertValue(this.numberField, 2.5); - }); - test('Integer String', function() { - this.numberField.setValue('2'); - assertValue(this.numberField, 2); - }); - test('Float String', function() { - this.numberField.setValue('2.5'); - assertValue(this.numberField, 2.5); - }); - test('Infinity', function() { - this.numberField.setValue(Infinity); - assertValue(this.numberField, Infinity); - }); - test('Negative Infinity String', function() { - this.numberField.setValue('-Infinity'); - assertValue(this.numberField, -Infinity); - }); - test('With source block', function() { - this.numberField.setSourceBlock(createTestBlock()); - this.numberField.setValue(2.5); - assertValue(this.numberField, 2.5); - }); + suite('Empty -> New Value', function() { + setup(function() { + this.field = new Blockly.FieldNumber(); }); - suite('Value -> New Value', function() { - setup(function() { - this.numberField = new Blockly.FieldNumber(1); - }); - test('Null', function() { - this.numberField.setValue(null); - assertValue(this.numberField, 1); - }); - test('Undefined', function() { - this.numberField.setValue(undefined); - assertValue(this.numberField, 1); - }); - test('Non-Parsable String', function() { - this.numberField.setValue('bad'); - assertValue(this.numberField, 1); - }); - test('NaN', function() { - this.numberField.setValue(NaN); - assertValue(this.numberField, 1); - }); - test('Integer', function() { - this.numberField.setValue(2); - assertValue(this.numberField, 2); - }); - test('Float', function() { - this.numberField.setValue(2.5); - assertValue(this.numberField, 2.5); - }); - test('Integer String', function() { - this.numberField.setValue('2'); - assertValue(this.numberField, 2); - }); - test('Float String', function() { - this.numberField.setValue('2.5'); - assertValue(this.numberField, 2.5); - }); - test('Infinity', function() { - this.numberField.setValue(Infinity); - assertValue(this.numberField, Infinity); - }); - test('Negative Infinity String', function() { - this.numberField.setValue('-Infinity'); - assertValue(this.numberField, -Infinity); - }); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, defaultFieldValue); + }); + suite('Value -> New Value', function() { + var initialValue = 1; + setup(function() { + this.field = new Blockly.FieldNumber(initialValue); }); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, initialValue); }); suite('Constraints', function() { + var testCases = [ + {title: 'Float', json: {}, value: 123.456, expectedValue: 123.456}, + {title: '0.01', json: {precision: .01}, value: 123.456, + expectedValue: 123.46}, + {title: '0.5', json: {precision: .5}, value: 123.456, + expectedValue: 123.5}, + {title: '1', json: {precision: 1}, value: 123.456, + expectedValue: 123}, + {title: '1.5', json: {precision: 1.5}, value: 123.456, + expectedValue: 123}, + ]; suite('Precision', function() { - test('Float', function() { - var numberField = new Blockly.FieldNumber(); - numberField.setValue(123.456); - assertValue(numberField, 123.456); - }); - test('0.01', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ precision: .01 }); - numberField.setValue(123.456); - assertValue(numberField, 123.46); - }); - test('0.5', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ precision: .5 }); - numberField.setValue(123.456); - assertValue(numberField, 123.5); - }); - test('1', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ precision: 1 }); - numberField.setValue(123.456); - assertValue(numberField, 123); - }); - test('1.5', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ precision: 1.5 }); - numberField.setValue(123.456); - assertValue(numberField, 123); + testHelpers.runTestCases(testCases, function(testCase) { + return function() { + var field = Blockly.FieldNumber.fromJson(testCase.json); + field.setValue(testCase.value); + testHelpers.assertFieldValue(field, testCase.expectedValue); + }; }); test('Null', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ precision: null}); - chai.assert.equal(numberField.getPrecision(), 0); + var field = Blockly.FieldNumber.fromJson({precision: null}); + chai.assert.equal(field.getPrecision(), 0); }); }); + var setValueBoundsTestFn = function(testCase) { + return function() { + var field = Blockly.FieldNumber.fromJson(testCase.json); + testCase.values.forEach(function(value, i) { + field.setValue(value); + testHelpers.assertFieldValue( + field, testCase.expectedValues[i]); + }); + }; + }; suite('Min', function() { - test('-10', function() { - var numberField = new Blockly.FieldNumber.fromJson({ min: -10 }); - numberField.setValue(-20); - assertValue(numberField, -10); - numberField.setValue(0); - assertValue(numberField, 0); - numberField.setValue(20); - assertValue(numberField, 20); - }); - test('0', function() { - var numberField = new Blockly.FieldNumber.fromJson({ min: 0 }); - numberField.setValue(-20); - assertValue(numberField, 0); - numberField.setValue(0); - assertValue(numberField, 0); - numberField.setValue(20); - assertValue(numberField, 20); - }); - test('+10', function() { - var numberField = new Blockly.FieldNumber.fromJson({ min: 10 }); - numberField.setValue(-20); - assertValue(numberField, 10); - numberField.setValue(0); - assertValue(numberField, 10); - numberField.setValue(20); - assertValue(numberField, 20); - }); + var testCases = [ + {title: '-10', json: {min: -10}, values: [-20, 0, 20], + expectedValues: [-10, 0, 20]}, + {title: '0', json: {min: 0}, values: [-20, 0, 20], + expectedValues: [0, 0, 20]}, + {title: '+10', json: {min: 10}, values: [-20, 0, 20], + expectedValues: [10, 10, 20]}, + ]; + testHelpers.runTestCases(testCases, setValueBoundsTestFn); test('Null', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ min: null}); - chai.assert.equal(numberField.getMin(), -Infinity); + var field = Blockly.FieldNumber.fromJson({min: null}); + chai.assert.equal(field.getMin(), -Infinity); }); }); suite('Max', function() { - test('-10', function() { - var numberField = new Blockly.FieldNumber.fromJson({ max: -10 }); - numberField.setValue(-20); - assertValue(numberField, -20); - numberField.setValue(0); - assertValue(numberField, -10); - numberField.setValue(20); - assertValue(numberField, -10); - }); - test('0', function() { - var numberField = new Blockly.FieldNumber.fromJson({ max: 0 }); - numberField.setValue(-20); - assertValue(numberField, -20); - numberField.setValue(0); - assertValue(numberField, 0); - numberField.setValue(20); - assertValue(numberField, 0); - }); - test('+10', function() { - var numberField = new Blockly.FieldNumber.fromJson({ max: 10 }); - numberField.setValue(-20); - assertValue(numberField, -20); - numberField.setValue(0); - assertValue(numberField, 0); - numberField.setValue(20); - assertValue(numberField, 10); - }); - test('null', function() { - var numberField = new Blockly.FieldNumber - .fromJson({ max: null}); - chai.assert.equal(numberField.getMax(), Infinity); + var testCases = [ + {title: '-10', json: {max: -10}, values: [-20, 0, 20], + expectedValues: [-20, -10, -10]}, + {title: '0', json: {max: 0}, values: [-20, 0, 20], + expectedValues: [-20, 0, 0]}, + {title: '+10', json: {max: 10}, values: [-20, 0, 20], + expectedValues: [-20, 0, 10]}, + ]; + testHelpers.runTestCases(testCases, setValueBoundsTestFn); + test('Null', function() { + var field = Blockly.FieldNumber.fromJson({max: null}); + chai.assert.equal(field.getMax(), Infinity); }); }); }); }); suite('Validators', function() { setup(function() { - this.numberField = new Blockly.FieldNumber(1); - this.numberField.htmlInput_ = Object.create(null); - this.numberField.htmlInput_.oldValue_ = '1'; - this.numberField.htmlInput_.untypedDefaultValue_ = 1; - this.stub = sinon.stub(this.numberField, 'resizeEditor_'); + this.field = new Blockly.FieldNumber(1); + this.field.htmlInput_ = Object.create(null); + this.field.htmlInput_.oldValue_ = '1'; + this.field.htmlInput_.untypedDefaultValue_ = 1; + this.stub = sinon.stub(this.field, 'resizeEditor_'); }); teardown(function() { - this.numberField.setValidator(null); - this.numberField.htmlInput_ = null; - if (this.stub) { - this.stub.restore(); - } + sinon.restore(); }); - suite('Null Validator', function() { - setup(function() { - this.numberField.setValidator(function() { - return null; + var testSuites = [ + {title: 'Null Validator', + validator: + function() { + return null; + }, + value: 2, expectedValue: 1}, + {title: 'Force End with 6 Validator', + validator: + function(newValue) { + return String(newValue).replace(/.$/, '6'); + }, + value: 25, expectedValue: 26}, + {title: 'Returns Undefined Validator', validator: function() {}, value: 2, + expectedValue: 2}, + ]; + testSuites.forEach(function(suiteInfo) { + suite(suiteInfo.title, function() { + setup(function() { + this.field.setValidator(suiteInfo.validator); }); - }); - test('When Editing', function() { - this.numberField.isBeingEdited_ = true; - this.numberField.htmlInput_.value = '2'; - this.numberField.onHtmlInputChange_(null); - assertValue(this.numberField, 1, '2'); - this.numberField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.numberField.setValue(2); - assertValue(this.numberField, 1); - }); - }); - suite('Force End with 6 Validator', function() { - setup(function() { - this.numberField.setValidator(function(newValue) { - return String(newValue).replace(/.$/, "6"); + test('When Editing', function() { + this.field.isBeingEdited_ = true; + this.field.htmlInput_.value = String(suiteInfo.value); + this.field.onHtmlInputChange_(null); + testHelpers.assertFieldValue( + this.field, suiteInfo.expectedValue, String(suiteInfo.value)); + }); + test('When Not Editing', function() { + this.field.setValue(suiteInfo.value); + testHelpers.assertFieldValue(this.field, suiteInfo.expectedValue); }); - }); - test('When Editing', function() { - this.numberField.isBeingEdited_ = true; - this.numberField.htmlInput_.value = '25'; - this.numberField.onHtmlInputChange_(null); - assertValue(this.numberField, 26, '25'); - this.numberField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.numberField.setValue(25); - assertValue(this.numberField, 26); - }); - }); - suite('Returns Undefined Validator', function() { - setup(function() { - this.numberField.setValidator(function() {}); - }); - test('When Editing', function() { - this.numberField.isBeingEdited_ = true; - this.numberField.htmlInput_.value = '2'; - this.numberField.onHtmlInputChange_(null); - assertValue(this.numberField, 2); - this.numberField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.numberField.setValue(2); - assertValue(this.numberField, 2); }); }); }); diff --git a/tests/mocha/field_textinput_test.js b/tests/mocha/field_textinput_test.js index f529452d8..f51c1bf92 100644 --- a/tests/mocha/field_textinput_test.js +++ b/tests/mocha/field_textinput_test.js @@ -5,218 +5,137 @@ */ suite('Text Input Fields', function() { - function assertValue(textInputField, expectedValue, opt_expectedText) { - var actualValue = textInputField.getValue(); - var actualText = textInputField.getText(); - opt_expectedText = opt_expectedText || expectedValue; - chai.assert.equal(actualValue, expectedValue); - chai.assert.equal(actualText, opt_expectedText); - } - function assertValueDefault(textInputField) { - assertValue(textInputField, ''); - } - suite('Constructor', function() { - test('Empty', function() { - var textInputField = new Blockly.FieldTextInput(); - assertValueDefault(textInputField); - }); - test('Undefined', function() { - var textInputField = new Blockly.FieldTextInput(undefined); - assertValueDefault(textInputField); - }); - test('String', function() { - var textInputField = new Blockly.FieldTextInput('value'); - assertValue(textInputField, 'value'); - }); - test('Number (Truthy)', function() { - var textInputField = new Blockly.FieldTextInput(1); - assertValue(textInputField, '1'); - }); - test('Number (Falsy)', function() { - var textInputField = new Blockly.FieldTextInput(0); - assertValue(textInputField, '0'); - }); - test('Boolean True', function() { - var textInputField = new Blockly.FieldTextInput(true); - assertValue(textInputField, 'true'); - }); - test('Boolean False', function() { - var textInputField = new Blockly.FieldTextInput(false); - assertValue(textInputField, 'false'); - }); - }); - suite('fromJson', function() { - test('Empty', function() { - var textInputField = new Blockly.FieldTextInput.fromJson({}); - assertValueDefault(textInputField); - }); - test('Undefined', function() { - var textInputField = new Blockly.FieldTextInput - .fromJson({ text: undefined}); - assertValueDefault(textInputField); - }); - test('String', function() { - var textInputField = Blockly.FieldTextInput.fromJson({ text:'value' }); - assertValue(textInputField, 'value'); - }); - test('Number (Truthy)', function() { - var textInputField = Blockly.FieldTextInput.fromJson({ text:1 }); - assertValue(textInputField, '1'); - }); - test('Number (Falsy)', function() { - var textInputField = Blockly.FieldTextInput.fromJson({ text:0 }); - assertValue(textInputField, '0'); - }); - test('Boolean True', function() { - var textInputField = Blockly.FieldTextInput.fromJson({ text:true }); - assertValue(textInputField, 'true'); - }); - test('Boolean False', function() { - var textInputField = Blockly.FieldTextInput.fromJson({ text:false }); - assertValue(textInputField, 'false'); - }); - }); + /** + * Configuration for field tests with invalid values. + * @type {!Array} + */ + var invalidValueTestCases = [ + {title: 'Undefined', value: undefined}, + {title: 'Null', value: null}, + ]; + /** + * Configuration for field tests with valid values. + * @type {!Array} + */ + var validValueTestCases = [ + {title: 'String', value: 'value', expectedValue: 'value'}, + {title: 'Boolean true', value: true, expectedValue: 'true'}, + {title: 'Boolean false', value: false, expectedValue: 'false'}, + {title: 'Number (Truthy)', value: 1, expectedValue: '1'}, + {title: 'Number (Falsy)', value: 0, expectedValue: '0'}, + {title: 'NaN', value: NaN, expectedValue: 'NaN'}, + ]; + var addArgsAndJson = function(testCase) { + testCase.args = [testCase.value]; + testCase.json = {'text': testCase.value}; + }; + invalidValueTestCases.forEach(addArgsAndJson); + validValueTestCases.forEach(addArgsAndJson); + + /** + * The expected default value for the field being tested. + * @type {*} + */ + var defaultFieldValue = ''; + /** + * Asserts that the field property values are set to default. + * @param {!Blockly.FieldNumber} field The field to check. + */ + var assertFieldDefault = function(field) { + testHelpers.assertFieldValue(field, defaultFieldValue); + }; + /** + * Asserts that the field properties are correct based on the test case. + * @param {!Blockly.FieldNumber} field The field to check. + * @param {!FieldValueTestCase} testCase The test case. + */ + var validTestCaseAssertField = function(field, testCase) { + testHelpers.assertFieldValue(field, testCase.expectedValue); + }; + + testHelpers.runConstructorSuiteTests( + Blockly.FieldTextInput, validValueTestCases, invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + + testHelpers.runFromJsonSuiteTests( + Blockly.FieldTextInput, validValueTestCases,invalidValueTestCases, + validTestCaseAssertField, assertFieldDefault); + suite('setValue', function() { suite('Empty -> New Value', function() { setup(function() { - this.textInputField = new Blockly.FieldTextInput(); - }); - test('Null', function() { - this.textInputField.setValue(null); - assertValueDefault(this.textInputField); - }); - test('Undefined', function() { - this.textInputField.setValue(undefined); - assertValueDefault(this.textInputField); - }); - test('New String', function() { - this.textInputField.setValue('newValue'); - assertValue(this.textInputField, 'newValue'); - }); - test('Number (Truthy)', function() { - this.textInputField.setValue(1); - assertValue(this.textInputField, '1'); - }); - test('Number (Falsy)', function() { - this.textInputField.setValue(0); - assertValue(this.textInputField, '0'); - }); - test('Boolean True', function() { - this.textInputField.setValue(true); - assertValue(this.textInputField, 'true'); - }); - test('Boolean False', function() { - this.textInputField.setValue(false); - assertValue(this.textInputField, 'false'); + this.field = new Blockly.FieldTextInput(); }); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, defaultFieldValue); test('With source block', function() { - this.textInputField.setSourceBlock(createTestBlock()); - this.textInputField.setValue('newValue'); - assertValue(this.textInputField, 'newValue'); + this.field.setSourceBlock(createTestBlock()); + this.field.setValue('value'); + testHelpers.assertFieldValue(this.field, 'value'); }); }); suite('Value -> New Value', function() { + var initialValue = 'oldValue'; setup(function() { - this.textInputField = new Blockly.FieldTextInput('value'); + this.field = new Blockly.FieldTextInput(initialValue); }); - test('Null', function() { - this.textInputField.setValue(null); - assertValue(this.textInputField, 'value'); - }); - test('Undefined', function() { - this.textInputField.setValue(undefined); - assertValue(this.textInputField, 'value'); - }); - test('New String', function() { - this.textInputField.setValue('newValue'); - assertValue(this.textInputField, 'newValue'); - }); - test('Number (Truthy)', function() { - this.textInputField.setValue(1); - assertValue(this.textInputField, '1'); - }); - test('Number (Falsy)', function() { - this.textInputField.setValue(0); - assertValue(this.textInputField, '0'); - }); - test('Boolean True', function() { - this.textInputField.setValue(true); - assertValue(this.textInputField, 'true'); - }); - test('Boolean False', function() { - this.textInputField.setValue(false); - assertValue(this.textInputField, 'false'); + testHelpers.runSetValueTests( + validValueTestCases, invalidValueTestCases, initialValue); + test('With source block', function() { + this.field.setSourceBlock(createTestBlock()); + this.field.setValue('value'); + testHelpers.assertFieldValue(this.field, 'value'); }); }); }); + suite('Validators', function() { setup(function() { - this.textInputField = new Blockly.FieldTextInput('value'); - this.textInputField.htmlInput_ = Object.create(null); - this.textInputField.htmlInput_.oldValue_ = 'value'; - this.textInputField.htmlInput_.untypedDefaultValue_ = 'value'; - this.stub = sinon.stub(this.textInputField, 'resizeEditor_'); + this.field = new Blockly.FieldTextInput('value'); + this.field.htmlInput_ = Object.create(null); + this.field.htmlInput_.oldValue_ = 'value'; + this.field.htmlInput_.untypedDefaultValue_ = 'value'; + this.stub = sinon.stub(this.field, 'resizeEditor_'); }); teardown(function() { - this.textInputField.setValidator(null); - Blockly.FieldTextInput.htmlInput_ = null; - if (this.stub) { - this.stub.restore(); - } + sinon.restore(); }); - suite('Null Validator', function() { - setup(function() { - this.textInputField.setValidator(function() { - return null; + var testSuites = [ + {title: 'Null Validator', + validator: + function() { + return null; + }, + value: 'newValue', expectedValue: 'value'}, + {title: 'Remove \'a\' Validator', + validator: + function(newValue) { + return newValue.replace(/a/g, ''); + }, + value: 'bbbaaa', expectedValue: 'bbb'}, + {title: 'Returns Undefined Validator', validator: function() {}, + value: 'newValue', expectedValue: 'newValue', expectedText: 'newValue'}, + ]; + testSuites.forEach(function(suiteInfo) { + suite(suiteInfo.title, function() { + setup(function() { + this.field.setValidator(suiteInfo.validator); }); - }); - test('When Editing', function() { - this.textInputField.isBeingEdited_ = true; - this.textInputField.htmlInput_.value = 'newValue'; - this.textInputField.onHtmlInputChange_(null); - assertValue(this.textInputField, 'value', 'newValue'); - this.textInputField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.textInputField.setValue('newValue'); - assertValue(this.textInputField, 'value'); - }); - }); - suite('Remove \'a\' Validator', function() { - setup(function() { - this.textInputField.setValidator(function(newValue) { - return newValue.replace(/a/g, ''); + test('When Editing', function() { + this.field.isBeingEdited_ = true; + this.field.htmlInput_.value = suiteInfo.value; + this.field.onHtmlInputChange_(null); + testHelpers.assertFieldValue( + this.field, suiteInfo.expectedValue, suiteInfo.value); + }); + test('When Not Editing', function() { + this.field.setValue(suiteInfo.value); + testHelpers.assertFieldValue(this.field, suiteInfo.expectedValue); }); - }); - test('When Editing', function() { - this.textInputField.isBeingEdited_ = true; - this.textInputField.htmlInput_.value = 'bbbaaa'; - this.textInputField.onHtmlInputChange_(null); - assertValue(this.textInputField, 'bbb', 'bbbaaa'); - this.textInputField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.textInputField.setValue('bbbaaa'); - assertValue(this.textInputField, 'bbb'); - }); - }); - suite('Returns Undefined Validator', function() { - setup(function() { - this.textInputField.setValidator(function() {}); - }); - test('When Editing', function() { - this.textInputField.isBeingEdited_ = true; - this.textInputField.htmlInput_.value = 'newValue'; - this.textInputField.onHtmlInputChange_(null); - assertValue(this.textInputField, 'newValue'); - this.textInputField.isBeingEdited_ = false; - }); - test('When Not Editing', function() { - this.textInputField.setValue('newValue'); - assertValue(this.textInputField, 'newValue'); }); }); }); + suite('Customization', function() { suite('Spellcheck', function() { setup(function() { diff --git a/tests/mocha/index.html b/tests/mocha/index.html index 65eb54f0c..bc236ad93 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -26,6 +26,7 @@ +