-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Field Value Tests #2459
Added Field Value Tests #2459
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still need to work through the test cases, but wanted to ask why you're changing the behavior in labels and text inputs.
core/field_label.js
Outdated
* @param {string=} opt_class Optional CSS class for the field's text. | ||
* @extends {Blockly.Field} | ||
* @constructor | ||
*/ | ||
Blockly.FieldLabel = function(text, opt_class) { | ||
if (!text) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be false for the empty string as well, which I don't think is a behavior change you intended to make.
In general, why are you adding this check? It looks like setText will handled it by casting to a String if it's not null. Is it a problem with validators?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, Fixed =)
core/field_textinput.js
Outdated
@@ -46,6 +46,9 @@ goog.require('goog.userAgent'); | |||
* @constructor | |||
*/ | |||
Blockly.FieldTextInput = function(text, opt_validator) { | |||
if (!text) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue, and empty string should be a valid starting point for text input fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed Angle and Checkbox.
- This is really thorough. Impressive work. =)
- In general, we should probably fix any fields that reset to the default when they get bad input. I'll file an issue.
tests/mocha/field_angle_test.js
Outdated
test('Value -> Undefined', function() { | ||
var angleField = new Blockly.FieldAngle(1); | ||
angleField.setValue(undefined); | ||
// TODO: Is this how we want this to work? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bug in field angle. Should probably be treated the same as null.
tests/mocha/field_angle_test.js
Outdated
test('Value -> Non-Parsable String', function() { | ||
var angleField = new Blockly.FieldAngle(1); | ||
angleField.setValue('bad'); | ||
// TODO: Is this how we want this to work? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto. Should probably not change the value if the input is invalid.
var actualValue = checkboxField.getValue(); | ||
var actualText = checkboxField.getText(); | ||
assertEquals(actualValue, expectedValue); | ||
assertEquals(actualText, expectedText); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for checking both the value and the text. That'll make supporting screen readers easier.
tests/mocha/field_checkbox_test.js
Outdated
assertValue(checkboxField, 'TRUE', 'true'); | ||
}); | ||
}); | ||
suite('Always True Validator', function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/True/False
Filed #2462 for to track bad value handling in fields. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
colour and date reviewed.
tests/mocha/field_colour_test.js
Outdated
var colourField = new Blockly.FieldColour('bad'); | ||
assertValueDefault(colourField); | ||
}); | ||
// TODO: Do we want the colour to convert to uppercase or to lowercase? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lowercase sgtm.
tests/mocha/field_colour_test.js
Outdated
}); | ||
suite('setValue', function() { | ||
test('#ffffff -> Null', function() { | ||
var colourField = new Blockly.FieldColour('#ffffff'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating the colourField can be moved into setup for this suite. Also, you should use a value other than the default so you can distinguish when it's falling back to the default vs the current value.
tests/mocha/field_colour_test.js
Outdated
suite('Validators', function() { | ||
var colourField; | ||
setup(function() { | ||
colourField = new Blockly.FieldColour('#ffffff'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a colour string other than the default so you can distinguish default vs previous value.
assertEquals(actualText, expectedText); | ||
} | ||
function assertValueDefault(colourField) { | ||
var expectedValue = Blockly.FieldColour.COLOURS[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For testing consistency you might want to change Blockly.FieldColour.COLOURS to a specific set of colours in setup and change it back in teardown.
tests/mocha/field_date_test.js
Outdated
var actualValue = dateField.getValue(); | ||
var actualText = dateField.getText(); | ||
var stringExpectedValue = String(expectedValue); | ||
assertEquals(String(actualValue), stringExpectedValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you compare the values as strings?
tests/mocha/field_date_test.js
Outdated
assertValue(dateField, '2020-02-20'); | ||
}); | ||
test('Invalid Date - Month(2020-13-20)', function() { | ||
// TODO: What do we want it to do in this case? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test as written seems reasonable to me.
tests/mocha/field_date_test.js
Outdated
assertValueDefault(dateField); | ||
}); | ||
test('Invalid Date - Day(2020-02-32)', function() { | ||
// TODO: What do we want it to do in this case? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto.
tests/mocha/field_date_test.js
Outdated
test('Value -> Undefined', function() { | ||
var dateField = new Blockly.FieldDate('2020-02-20'); | ||
dateField.setValue(undefined); | ||
// TODO: Is this how we want this to work? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, probably want it to leave the current value instead of reverting to the default.
For tests that fail now because the fields do the wrong thing--you can write them as The tests will show up on the index page, but won't be run. Then you can enable them as you fix the bugs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed remaining test files.
core/field_image.js
Outdated
@@ -48,11 +48,20 @@ Blockly.FieldImage = function(src, width, height, | |||
opt_alt, opt_onClick, opt_flipRtl) { | |||
this.sourceBlock_ = null; | |||
|
|||
if (!src) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a change in behavior. I think there's a valid use case for initializing src to null or an empty string and setting it later, so you should probably revert this and let the image element handle the error.
tests/mocha/field_dropdown_test.js
Outdated
function assertValue(dropdownField, expectedValue, expectedText) { | ||
var actualValue = dropdownField.getValue(); | ||
var actualText = dropdownField.getText(); | ||
assertEquals(String(actualValue), expectedValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the cast to string?
tests/mocha/field_image_test.js
Outdated
}); | ||
test.skip('Without Alt', function() { | ||
var imageField = new Blockly.FieldImage('src', 1, 1); | ||
// TODO: currently getText returns undefined, is that what we want? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably makes more sense to have it default to an empty string like you're testing for. =)
}); | ||
suite('setValue', function() { | ||
test('Null', function() { | ||
var labelField = new Blockly.FieldLabelSerializable('value'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pull out into setup for the setValue suite.
tests/mocha/field_label_test.js
Outdated
}); | ||
suite('setValue', function() { | ||
test('Null', function() { | ||
var labelField = new Blockly.FieldLabel('value'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pull out into setup method
tests/mocha/field_number_test.js
Outdated
}); | ||
test('When Not Editing', function() { | ||
numberFieldField.setValue(2); | ||
assertValue(numberFieldField, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't a null validator cause the value to be reverted?
tests/mocha/field_textinput_test.js
Outdated
}); | ||
suite('setValue', function() { | ||
test('Null', function() { | ||
var textInputField = new Blockly.FieldTextInput('value'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pull out into setup?
@@ -8,54 +8,46 @@ suite('Variable Fields', function() { | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we forgot to add a license header. Would you mind adding one?
tests/mocha/field_variable_test.js
Outdated
assertNotNull(actualText); | ||
assertNotUndefined(actualText); | ||
} | ||
function assertValueName(variableField, expectedText) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally you'd want to assert the id and the text are as expected. You may need to replace the method that generates ids for variables with a mock to do this, though. Specificially getOrCreateVariablePackage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up stubbing Blockly.utils.genUid and Blockly.Variables.generateUniqueName instead. It should work the same.
tests/mocha/field_variable_test.js
Outdated
{ variable:variableName }), workspace); | ||
} | ||
function assertValueDefault(variableField) { | ||
var actualValue = variableField.getValue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From code, the default name will be 'i' and the default value will be a random UUID. It might be worth mocking some of the methods in Blockly.Variables so you can control the defaults and make the tests for default clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: It looks like sinon is the proper way to do mocking in mocha.
Example: https://github.com/google/blockly/blob/develop/tests/mocha/event_test.js#L84
Docs: https://sinonjs.org/
@RoboErikG should be good to go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good to me. A few final comments and I think Rachel wanted to glance over it too.
This was a lot of work. Thanks for doing it so thoroughly and thoughtfully, Beks!
core/field_image.js
Outdated
* @param {string=} opt_alt Optional alt text for when block is collapsed. | ||
* @param {Function=} opt_onClick Optional function to be called when the image | ||
* is clicked. If opt_onClick is defined, opt_alt must also be defined. | ||
* @param {boolean=} opt_flipRtl Whether to flip the icon in RTL. | ||
* @extends {Blockly.Field} | ||
* @constructor | ||
*/ | ||
Blockly.FieldImage = function(src, width, height, | ||
Blockly.FieldImage = function(opt_src, width, height, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We typically only label something opt if you can leave it out of the list of parameters. Since it's before width and height you have to supply something, but it's allowed to be null.
assertValue(labelField, '1'); | ||
}); | ||
test('Boolean', function() { | ||
var labelField = new Blockly.FieldLabel(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized, you're testing for true but not for false. Will false fail since you've updated the code to replace falsey things with an empty string?
core/field_label.js
Outdated
* @param {string=} opt_class Optional CSS class for the field's text. | ||
* @extends {Blockly.Field} | ||
* @constructor | ||
*/ | ||
Blockly.FieldLabel = function(text, opt_class) { | ||
this.size_ = new goog.math.Size(0, 17.5); | ||
this.class_ = opt_class; | ||
this.setValue(text); | ||
this.setValue(text || ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't think enough about this before. In your tests you require 1 -> '1' and true -> 'true', but not 0 -> '0' and false -> 'false' . It looks like those values will result in the empty string instead.
Here and elsewhere can we update this to explicitly check for null/undefined instead and let the majority of things be auto-cast to strings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed for all applicable fields & added tests to cover the changes.
I'm taking a look now, will comment when I'm done. @RoboErikG thanks for the thorough review, and thanks @BeksOmega for the thorough tests! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have one comment on a specific test, and one comment on structure.
tests/mocha/field_angle_test.js
Outdated
assertValue(angleField, 1); | ||
}); | ||
test('Value -> >360°', function() { | ||
var angleField = new Blockly.FieldAngle(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set initial value to 2 to make sure it changed.
tests/mocha/field_angle_test.js
Outdated
}); | ||
}); | ||
suite.skip('Validators', function() { | ||
var angleField; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is angleField
defined here instead of in setup?
What I expected to see:
setup(function() {
this.angleField = new Blockly.FieldAngle(1);
...
});
test('Test name', function() {
this.angleField.isBeingEdited_ = true;
...
});
I'm happy with this! @RoboErikG please confirm and then merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed lgtm.
The basics
The details
Resolves
Work on #2169 specifically this.
Proposed Changes
Adds tests to document how fields should react to different values.
Also clarifies which fields have default values and which do not.
Reason for Changes
Tests needed to be added before #2441 possibly breaks the world.
Test Coverage
This is tests silly!
Additional Information
So... a lot of these tests are actually failing! But that's not because the tests are broken, it's because the fields are broken.
Examples:
Plus a smattering of other field-specific bugs.
Important information
I have some TODO notes in the tests, these are requests for information on what the intended behavior is.
For example, most fields will revert to a default value (meaning the value they would have had had they been constructed no parameters) when passed a non-parsable value. I believe this is a bug, and non-parsable values should validated to null inside a field's doClassValidation_ function, but I wanted confirmation.