-
-
Notifications
You must be signed in to change notification settings - Fork 96
Fix(automation): Handles undefined values in conditions #1933
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
base: master
Are you sure you want to change the base?
Fix(automation): Handles undefined values in conditions #1933
Conversation
Addresses an issue where conditions with the 'not_equals' operator incorrectly evaluated undefined values. This change ensures that empty string comparisons correctly identify missing values in automation rules.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| return fieldValue == value; | ||
| case 'not_equals': | ||
| // overload the edge case where we use empty string to check if a value does not exist | ||
| if (value === '' && fieldValue === undefined) { |
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.
Maybe it would be better to just do the inverse of equal?
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've implemented it in the 2nd commit.
Simplifies the 'not_equals' condition evaluation in automations by reusing the 'equals' condition, improving code readability and consistency. Fixes cpvalente#1932
Expanding test cases to cover various data types and edge case for each operators. Unexpected behavior have been mark with a TO_DO.
| expect(runTestCondition('null/undefined', null, 'equals', 'not-empty')).toBe(false); | ||
| expect(runTestCondition('boolean', false, 'equals', '')).toBe(false); | ||
|
|
||
| expect(runTestCondition('number', 0, 'equals', '')).toBe(true); // TO_DO: is this the desired behavior? |
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 case is probably wrong, especially if false != <empty/no 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.
yes, this seems incorrect. I believe my suggestion for comparing values could improve this
| it('should handle case sensitivity', () => { | ||
| // TO_DO: is this the desired behavior? | ||
| expect(runTestCondition('string', 'Title', 'contains', 'title')).toBe(false); | ||
| }); |
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.
contains only work on string, yet, it's case sensitive, contrary to equals.
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 good observation, contains and equals should have similar implementations.
I would suggest that contains and not_contains should also be case insensitive. what do you think?
| expect(runTestCondition('boolean', true, 'contains', 'true')).toBe(false); | ||
| expect(runTestCondition('boolean', false, 'contains', 'false')).toBe(false); | ||
| }); | ||
|
|
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 case that could go both way, especially if, on the client side, operation depends of field type.
But, my first instinct was that other type should match if theirs string representation match.
But again, that would be weird for boolean value that would alway contain a e.
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.
In the current implementation, contains only deals with string types. I think this is the correct way to do it
semantically boolean contains "rue" doesnt make sense
- Ensures that their is a default scenario. - Fixing Deepsource issue "No default cases in switch statements JS-0047"
alex-Arc
left a comment
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.
thanks for working on this.
the fix itself seams good, and you bring up some good questions in the tests
maybe we could start by merging the fix and take a bit more time to clean up the test
cpvalente
left a comment
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.
Thank you for these observations.
The code changes were slightly hard to parse since they were mixed with a refactoring of the test scenarios.
I suggest that we create a single PR for now.
- add tests for the edge cases with equals and contains you have brought up using the existing abstractions
- add fixes for equals as suggested
- add changes for casing in contains
we can then review separately whether the tests benefit from an abstraction. In general we avoid abstractions in testing. At this level we dont want to do any "hiding" and prefer all the changes to be explicit, also abstractions could introduce issues at abstraction level which make things hard to debug
| return fieldValue == value; | ||
| case 'not_equals': | ||
| return fieldValue != value; | ||
| return !evaluateCondition({ field, operator: 'equals', 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.
I believe the previous code attempted a loose comparison to allow matching "12" to 12.
This is to simplify automations
However, it has the side effects of matching all the falsy values 0, undefined, null, ""
how about creating a new helper isEquivalentValue which resolves this
- given two values of the same type, make a strict comparison
=== - given two values of different types:
- a) if the types are string a number, make a loose comparison
== - b) for all other cases return false
This could also help with the logic in the equals condition
| it('should handle case sensitivity', () => { | ||
| // TO_DO: is this the desired behavior? | ||
| expect(runTestCondition('string', 'Title', 'contains', 'title')).toBe(false); | ||
| }); |
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 good observation, contains and equals should have similar implementations.
I would suggest that contains and not_contains should also be case insensitive. what do you think?
| expect(runTestCondition('boolean', true, 'contains', 'true')).toBe(false); | ||
| expect(runTestCondition('boolean', false, 'contains', 'false')).toBe(false); | ||
| }); | ||
|
|
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.
In the current implementation, contains only deals with string types. I think this is the correct way to do it
semantically boolean contains "rue" doesnt make sense
| expect(runTestCondition('null/undefined', null, 'equals', 'not-empty')).toBe(false); | ||
| expect(runTestCondition('boolean', false, 'equals', '')).toBe(false); | ||
|
|
||
| expect(runTestCondition('number', 0, 'equals', '')).toBe(true); // TO_DO: is this the desired behavior? |
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.
yes, this seems incorrect. I believe my suggestion for comparing values could improve this
|
I've removed the abstraction in the last commit. But the Idea behind the abstraction was to have a better view of all the test and expected results. Compare how those file look (look at line 104): At first, I wanted even more abstraction with a matrix to generate all the test, but settle on this middle ground. I will come back to this after my day job.... |
Addresses an issue where conditions with the 'not_equals' operator incorrectly evaluated undefined values. This change ensures that empty string comparisons correctly identify missing values in automation rules.
Fix #1932