-
Notifications
You must be signed in to change notification settings - Fork 83
feat: implement decide API #634
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
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.
Looks good. A couple of changes and more tests suggested.
var expectedDecision = { | ||
variationKey: null, | ||
enabled: false, | ||
variables: null, |
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.
return empty variables (instead of null) on error. Same for other 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.
Can we have one more test validating api decide option ("EXCLUDE_VARIABLES") work together with defaultDecideOption ("DISABLE_DISPATCH_EVENT"), so we see both options are on.
assert.deepEqual(callArgs[0], expectedImpressionEvent); | ||
}); | ||
}); | ||
|
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.
Can we add validation for decision flag notification?
return { | ||
variationKey: null, | ||
enabled: false, | ||
variables: null, |
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.
Variable should be empty {} instead of null
}); | ||
} | ||
|
||
decide( |
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.
Can we make sure "decide", "decideAll" and "decideForKey" API in optimizely not open to public?
They should access those APIs via OptimizelyUserContext always.
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 can exclude them from the top-level type definitions.
8d98a5d
to
ff8745b
Compare
clientEngine: 'node-sdk', | ||
datafile: testData.getTestDecideProjectConfig(), | ||
errorHandler: errorHandler, | ||
eventDispatcher: eventDispatcher, |
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.
Using a real event dispatcher could cause event requests to be sent during test runs - we don't want that. We should pass in a fake event dispatcher.
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.
dispatchEvent
of eventDispatcher is being stubbed in the outer beforeEach
function, so I think we should be fine. @mjc1283 let me know if you think otherwise
clientEngine: 'node-sdk', | ||
datafile: testData.getTestDecideProjectConfig(), | ||
errorHandler: errorHandler, | ||
eventDispatcher: eventDispatcher, |
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 comment re: real event dispatcher.
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.
Please see my response above
} | ||
assert.deepEqual(decision, expectedDecision); | ||
sinon.assert.calledOnce(optlyInstance.eventDispatcher.dispatchEvent); | ||
var expectedImpressionEvent = { |
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.
IMO, asserting the whole structure of this object is a lot. We could do it one test, and then in the others, we could just check a few properties, or check that dispatchEvent
was called.
// Filter out all provided default decide options that are not in OptimizelyDecideOptions[] | ||
if (OptimizelyDecideOptions[option]) { | ||
defaultDecideOptions[option] = 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.
Perhaps we could log a warning here if we encounter an invalid value - @jaeopt WDYT?
* @return {[key: string]: boolean} Map of all provided decide options including default decide options | ||
*/ | ||
private getAllDecideOptions(options: OptimizelyDecideOptions[]): { [key: string]: boolean } { | ||
const allDecideOptions = {...this.defaultDecideOptions}; |
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 better! 👍
const featureFlag = projectConfig.getFeatureFromKey(configObj, key, this.logger); | ||
featureFlag?.variables.forEach(variable => { |
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 already have feature
declared on 1474. Are these the same? Can we just use that one?
export interface OptimizelyDecision { | ||
variationKey: string | null; | ||
enabled: boolean; | ||
variables: { [variableKey: string]: unknown } | null; |
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.
If following @jaeopt 's suggestion that this is an empty object when there is "no decision", we can remove | null
;
@@ -117,6 +117,15 @@ export interface Rollout { | |||
experiments: Experiment[]; | |||
} | |||
|
|||
//TODO: Move OptimizelyDecideOptions to @optimizely/optimizely-sdk/lib/utils/enums |
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 move it there?
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.
Thinking it might be a good idea to expose it for clients use. LMKWYT @mjc1283
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.
Good point 👍
} from '../shared_types'; | ||
import { OptimizelyDecision, newErrorDecision } from '../optimizely_decision/optimizely_decision'; |
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.
Consider: since there is only one file, we could name it optimizely_decision/index.ts
, then it can be imported like import {...} from '../optimizely_decision';
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.
Decide notification format should be changed.
type: DECISION_NOTIFICATION_TYPES.FLAG, | ||
userId: userId, | ||
attributes: attributes, | ||
decisionInfo: featureInfo, | ||
decisionEventDispatched: decisionEventDispatched, |
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 notification data is different from the format defined in the TDD. Can you fix it?
Also can we have a test case to validate the notification contents for decide call?
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.
Remove "source" from notification. Other than that, all looks good.
featureKey: 'feature_2', | ||
featureEnabled: true, | ||
flagKey: 'feature_2', | ||
enabled: true, | ||
source: 'feature-test', |
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.
remove "source"
decisionInfo: { | ||
flagKey: 'feature_2', | ||
enabled: true, | ||
source: 'feature-test', |
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.
remove "source"
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.
LGTM
Summary
decide
APITest
Issues