/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: Apache-2.0 */ goog.module('Blockly.test.fieldCheckbox'); const {assertFieldValue, runConstructorSuiteTests, runFromJsonSuiteTests, runSetValueTests} = goog.require('Blockly.test.helpers.fields'); const {sharedTestSetup, sharedTestTeardown, workspaceTeardown} = goog.require('Blockly.test.helpers.setupTeardown'); const {defineRowBlock} = goog.require('Blockly.test.helpers.blockDefinitions'); suite('Checkbox Fields', function() { setup(function() { sharedTestSetup.call(this); }); teardown(function() { sharedTestTeardown.call(this); }); /** * Configuration for field tests with invalid values. * @type {!Array} */ const 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} */ const validValueTestCases = [ {title: 'Boolean true', value: true, expectedValue: 'TRUE', expectedText: 'true'}, {title: 'Boolean false', value: false, expectedValue: 'FALSE', expectedText: 'false'}, {title: 'String TRUE', value: 'TRUE', expectedValue: 'TRUE', expectedText: 'true'}, {title: 'String FALSE', value: 'FALSE', expectedValue: 'FALSE', expectedText: 'false'}, ]; const 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 {*} */ const defaultFieldValue = 'FALSE'; /** * Asserts that the field property values are set to default. * @param {!Blockly.FieldCheckbox} field The field to check. */ const assertFieldDefault = function(field) { assertFieldValue( field, defaultFieldValue, defaultFieldValue.toLowerCase()); }; /** * Asserts that the field properties are correct based on the test case. * @param {!Blockly.FieldCheckbox} field The field to check. * @param {!FieldValueTestCase} testCase The test case. */ const validTestCaseAssertField = function(field, testCase) { assertFieldValue( field, testCase.expectedValue, testCase.expectedValue.toLowerCase()); }; runConstructorSuiteTests( Blockly.FieldCheckbox, validValueTestCases, invalidValueTestCases, validTestCaseAssertField, assertFieldDefault); runFromJsonSuiteTests( Blockly.FieldCheckbox, validValueTestCases, invalidValueTestCases, validTestCaseAssertField, assertFieldDefault); suite('setValue', function() { suite('True -> New Value', function() { setup(function() { this.field = new Blockly.FieldCheckbox('TRUE'); }); runSetValueTests( validValueTestCases, invalidValueTestCases, 'TRUE', 'true'); }); suite('False -> New Value', function() { setup(function() { this.field = new Blockly.FieldCheckbox('FALSE'); }); runSetValueTests( validValueTestCases, invalidValueTestCases, 'FALSE', 'false'); }); }); suite('Validators', function() { setup(function() { this.field = new Blockly.FieldCheckbox(true); }); const 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.field.setValue(suiteInfo.value); assertFieldValue( this.field, suiteInfo.expectedValue, String(suiteInfo.expectedValue).toLowerCase()); }); }); }); }); suite('Customizations', function() { suite('Check Character', function() { function assertCharacter(field, char) { field.fieldGroup_ = Blockly.utils.dom.createSvgElement( Blockly.utils.Svg.G, {}, null); field.sourceBlock_ = { RTL: false, rendered: true, workspace: { keyboardAccessibilityMode: false, }, render: function() {field.render_();}, bumpNeighbours: function() {}, }; field.constants_ = { FIELD_CHECKBOX_X_OFFSET: 2, FIELD_CHECKBOX_Y_OFFSET: 2, FIELD_BORDER_RECT_RADIUS: 4, FIELD_BORDER_RECT_HEIGHT: 16, FIELD_TEXT_BASELINE_CENTER: false, FIELD_TEXT_HEIGHT: 16, FIELD_TEXT_BASELINE: 13, }; field.initView(); field.render_(); chai.assert(field.textContent_.nodeValue, char); } test('Constant', function() { const checkChar = Blockly.FieldCheckbox.CHECK_CHAR; // Note: Developers shouldn't actually do this. IMO they should change // the file and then recompile. But this is fine for testing. Blockly.FieldCheckbox.CHECK_CHAR = '\u2661'; const field = new Blockly.FieldCheckbox(true); assertCharacter(field, '\u2661'); Blockly.FieldCheckbox.CHECK_CHAR = checkChar; }); test('JS Constructor', function() { const field = new Blockly.FieldCheckbox(true, null, { checkCharacter: '\u2661', }); assertCharacter(field, '\u2661'); }); test('JSON Definition', function() { const field = Blockly.FieldCheckbox.fromJson({ checkCharacter: '\u2661', }); assertCharacter(field, '\u2661'); }); test('setCheckCharacter', function() { const field = new Blockly.FieldCheckbox(); assertCharacter(field, Blockly.FieldCheckbox.CHECK_CHAR); field.setCheckCharacter('\u2661'); // Don't call assertCharacter b/c we don't want to re-initialize. chai.assert.equal(field.textContent_.nodeValue, '\u2661'); }); test('setCheckCharacter Before Init', function() { const field = new Blockly.FieldCheckbox(); field.setCheckCharacter('\u2661'); assertCharacter(field, '\u2661'); }); test('Remove Custom Character', function() { const field = new Blockly.FieldCheckbox(true, null, { 'checkCharacter': '\u2661', }); assertCharacter(field, '\u2661'); field.setCheckCharacter(null); chai.assert(field.textContent_.nodeValue, Blockly.FieldCheckbox.CHECK_CHAR); }); }); }); suite('Serialization', function() { setup(function() { this.workspace = new Blockly.Workspace(); defineRowBlock(); this.assertValue = (value) => { const block = this.workspace.newBlock('row_block'); const field = new Blockly.FieldCheckbox(value); block.getInput('INPUT').appendField(field, 'CHECK'); const jso = Blockly.serialization.blocks.save(block); chai.assert.deepEqual(jso['fields'], {'CHECK': value}); }; }); teardown(function() { workspaceTeardown.call(this, this.workspace); }); test('True', function() { this.assertValue(true); }); test('False', function() { this.assertValue(false); }); }); });