Conversation
mnoman09
left a comment
There was a problem hiding this comment.
Overall looks good. Added some comments.
packages/optimizely-sdk/lib/core/custom_attribute_condition_evaluator/index.tests.js
Show resolved
Hide resolved
packages/optimizely-sdk/lib/core/custom_attribute_condition_evaluator/index.tests.js
Show resolved
Hide resolved
| const userValueType = typeof userValue; | ||
| const conditionValue = condition.value; | ||
|
|
||
| if (conditionValue === null || !isSafeInteger(conditionValue)) { |
There was a problem hiding this comment.
instead of repeating all these checks in every function put it in one function and use it from there see C# for reference. the only evaluation logic should be kept inside every evaluator.
There was a problem hiding this comment.
Consistency with previous written evaluators like greaterThanEvaluator, lessThanEvaluator etc will be lost.
There was a problem hiding this comment.
I agree with @mnoman09. If there is repeated logic for checking user inputs for numeric comparison conditions, let's use a shared helper function. If the logic is not exactly the same or it is awkward to share, don't worry about it.
| ['2.9.9-beta', '2.9.9-beta'], | ||
| ['2.1', '2.1.0'], | ||
| ['2', '2.12'], | ||
| ['2.9', '2.9.1'] |
There was a problem hiding this comment.
Add this test where targetSV = 2.1.3 and userver= 2.1.3+build and it should return 0 see this test
There was a problem hiding this comment.
No this is a corner case that we covered in all other sdks. you can see java link I shared above.
| const userValueType = typeof userValue; | ||
| const conditionValue = condition.value; | ||
|
|
||
| if (conditionValue === null || !isSafeInteger(conditionValue)) { |
There was a problem hiding this comment.
I agree with @mnoman09. If there is repeated logic for checking user inputs for numeric comparison conditions, let's use a shared helper function. If the logic is not exactly the same or it is awkward to share, don't worry about it.
| export const VERSION_TYPE = { | ||
| IS_PRE_RELEASE: '-', | ||
| IS_BUILD: '+' | ||
| } |
There was a problem hiding this comment.
TypeScript has enum and const enum declarations. Some can be compiled into constant values leading to smaller code size. Please check the documentation for enums. Let's not use an object with long property names unless necessary, to avoid bloating the code.
|
|
||
| } | ||
|
|
||
| export function compareVersion(conditionsVersion: string, userProvidedVersion: string): number | null { |
There was a problem hiding this comment.
Please add a documentation comment
| if (!userVersionParts || !conditionsVersionParts) | ||
| return null; |
There was a problem hiding this comment.
Style preference is to always use brackets with if statements.
| if (userVersionPartsLen <= idx) | ||
| return isPreReleaseInconditionsVersion || isBuildInconditionsVersion ? 1 : -1 | ||
| else if (!isNumber(userVersionParts[idx])) { | ||
| if (userVersionParts[idx] < conditionsVersionParts[idx]) { | ||
| return isPreReleaseInconditionsVersion && !isPreReleaseInuserProvidedVersion ? 1 : -1; | ||
| } | ||
| else if (userVersionParts[idx] > conditionsVersionParts[idx]) { | ||
| return !isPreReleaseInconditionsVersion && isPreReleaseInuserProvidedVersion ? -1 : 1; | ||
| } | ||
| } | ||
| else { | ||
| const userVersionPart = parseInt(userVersionParts[idx]) | ||
| const conditionsVersionPart = parseInt(conditionsVersionParts[idx]) | ||
| if (userVersionPart > conditionsVersionPart) | ||
| return 1; | ||
| else if (userVersionPart < conditionsVersionPart) | ||
| return -1; | ||
| } |
There was a problem hiding this comment.
Please try to simplify the control flow, there are a lot of nested conditionals.
| * | ||
| */ | ||
| function isNumber(content: string): boolean { | ||
| return content.match(/^[0-9]+$/) != null ? true : false; |
There was a problem hiding this comment.
Is this equivalent?
| return content.match(/^[0-9]+$/) != null ? true : false; | |
| return /^\d+$/.test(content); |
(see: Regular Expression docs for JS)
Also: I suggest declaring regular expression once higher up in module scope, then reference here (DIGIT_STRING_REGEXP.test(content)).
| * | ||
| */ | ||
| function hasWhiteSpaces(version: string): boolean { | ||
| return version.includes(' '); |
There was a problem hiding this comment.
What about other space characters (tab, newline, etc.)? Should we use space regexp character class?
| return version.includes(' '); | |
| return /\s/.test(version); |
- Minor concern:
String.prototype.includesis not supported in very old JS environments. - Is there any performance difference between
String.prototype.includesand regular expressiontestmethod?
| //check for pre release e.g. 1.0.0-alpha where 'alpha' is a pre release | ||
| //otherwise check for build e.g. 1.0.0+001 where 001 is a build metadata | ||
| if (isPreReleaseVersion(version)) { | ||
| targetPrefix = version.substring(0, version.indexOf(VERSION_TYPE.IS_PRE_RELEASE)); |
There was a problem hiding this comment.
IS_PRE_RELEASE sounds like a boolean. I prefer PRE_RELEASE_VERSION_DELIMITER.
| targetSuffix = version.substring(version.indexOf(VERSION_TYPE.IS_PRE_RELEASE) + 1); | ||
| } | ||
| else if (isBuildVersion(version)) { | ||
| targetPrefix = version.substring(0, version.indexOf(VERSION_TYPE.IS_BUILD)); |
| * @return {boolean} The array of version split into smaller parts i.e major, minor, patch etc | ||
| * null if given version is in invalid format |
There was a problem hiding this comment.
Would consumer code be clearer if we had an interface for semantic version components?
interface SemanticVersionComponents {
major: number;
minor: number;
patch: number;
preRelease?: number
build?: number
}Then:
function splitVersion(version: string): SemanticVersionComponents | null {
Summary
Test plan