Skip to content

Commit be870fe

Browse files
authored
fix: Forced variation not available in experiment (#292)
* fixes * unit test fix * unit test added * refactor
1 parent ac29ac1 commit be870fe

File tree

5 files changed

+45
-12
lines changed

5 files changed

+45
-12
lines changed

lib/optimizely.rb

+18-9
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ def decide(user_context, key, decide_options = [])
214214
experiment = decision.experiment
215215
rule_key = experiment ? experiment['key'] : nil
216216
variation = decision['variation']
217-
variation_key = variation['key']
218-
feature_enabled = variation['featureEnabled']
217+
variation_key = variation ? variation['key'] : nil
218+
feature_enabled = variation ? variation['featureEnabled'] : false
219219
decision_source = decision.source
220220
end
221221

@@ -298,8 +298,17 @@ def decide_for_keys(user_context, keys, decide_options = [])
298298
decisions
299299
end
300300

301-
def get_flag_variation_by_key(flag_key, variation_key)
302-
project_config.get_variation_from_flag(flag_key, variation_key)
301+
# Gets variation using variation key or id and flag key.
302+
#
303+
# @param flag_key - flag key from which the variation is required.
304+
# @param target_value - variation value either id or key that will be matched.
305+
# @param attribute - string representing variation attribute.
306+
#
307+
# @return [variation]
308+
# @return [nil] if no variation found in flag_variation_map.
309+
310+
def get_flag_variation(flag_key, target_value, attribute)
311+
project_config.get_variation_from_flag(flag_key, target_value, attribute)
303312
end
304313

305314
# Buckets visitor and sends impression event to Optimizely.
@@ -1098,11 +1107,11 @@ def send_impression(config, experiment, variation_key, flag_key, rule_key, enabl
10981107
experiment_id = experiment['id']
10991108
experiment_key = experiment['key']
11001109

1101-
if experiment_id != ''
1102-
variation_id = config.get_variation_id_from_key_by_experiment_id(experiment_id, variation_key)
1103-
else
1104-
varaition = get_flag_variation_by_key(flag_key, variation_key)
1105-
variation_id = varaition ? varaition['id'] : ''
1110+
variation_id = config.get_variation_id_from_key_by_experiment_id(experiment_id, variation_key) unless experiment_id.empty?
1111+
1112+
unless variation_id
1113+
variation = !flag_key.empty? ? get_flag_variation(flag_key, variation_key, 'key') : nil
1114+
variation_id = variation ? variation['id'] : ''
11061115
end
11071116

11081117
metadata = {

lib/optimizely/config/datafile_project_config.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,9 @@ def get_audience_from_id(audience_id)
302302
nil
303303
end
304304

305-
def get_variation_from_flag(flag_key, variation_key)
305+
def get_variation_from_flag(flag_key, target_value, attribute)
306306
variations = @flag_variation_map[flag_key]
307-
return variations.select { |variation| variation['key'] == variation_key }.first if variations
307+
return variations.select { |variation| variation[attribute] == target_value }.first if variations
308308

309309
nil
310310
end

lib/optimizely/decision_service.rb

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ def get_variation_for_feature_experiment(project_config, feature_flag, user_cont
193193
next unless variation_id
194194

195195
variation = project_config.get_variation_from_id_by_experiment_id(experiment_id, variation_id)
196+
variation = project_config.get_variation_from_flag(feature_flag['key'], variation_id, 'id') if variation.nil?
196197

197198
return Decision.new(experiment, variation, DECISION_SOURCES['FEATURE_TEST']), decide_reasons
198199
end

lib/optimizely/optimizely_user_context.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def find_validated_forced_decision(context)
164164
reasons = []
165165
target = rule_key ? "flag (#{flag_key}), rule (#{rule_key})" : "flag (#{flag_key})"
166166
if variation_key
167-
variation = @optimizely_client.get_flag_variation_by_key(flag_key, variation_key)
167+
variation = @optimizely_client.get_flag_variation(flag_key, variation_key, 'key')
168168
if variation
169169
reason = "Variation (#{variation_key}) is mapped to #{target} and user (#{@user_id}) in the forced decision map."
170170
reasons.push(reason)

spec/optimizely_user_context_spec.rb

+23
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,29 @@
284284
expect(decision.reasons).to eq(['Variation (b) is mapped to flag (feature_1), rule (exp_with_audience) and user (tester) in the forced decision map.'])
285285
end
286286

287+
it 'should return an expected decision object when forced decision is called and variation of different experiment but same flag key' do
288+
user_id = 'tester'
289+
feature_key = 'feature_1'
290+
original_attributes = {}
291+
user_context_obj = Optimizely::OptimizelyUserContext.new(forced_decision_project_instance, user_id, original_attributes)
292+
context = Optimizely::OptimizelyUserContext::OptimizelyDecisionContext.new(feature_key, 'exp_with_audience')
293+
forced_decision = Optimizely::OptimizelyUserContext::OptimizelyForcedDecision.new('3324490633')
294+
user_context_obj.set_forced_decision(context, forced_decision)
295+
expected = expect do
296+
decision = user_context_obj.decide(feature_key, [Optimizely::Decide::OptimizelyDecideOption::INCLUDE_REASONS])
297+
expect(decision.variation_key).to eq('3324490633')
298+
expect(decision.rule_key).to eq('exp_with_audience')
299+
expect(decision.enabled).to be false
300+
expect(decision.flag_key).to eq(feature_key)
301+
expect(decision.user_context.user_id).to eq(user_id)
302+
expect(decision.user_context.user_attributes.length).to eq(0)
303+
expect(decision.user_context.forced_decisions.length).to eq(1)
304+
expect(decision.user_context.forced_decisions).to eq(context => forced_decision)
305+
expect(decision.reasons).to eq(['Variation (3324490633) is mapped to flag (feature_1), rule (exp_with_audience) and user (tester) in the forced decision map.'])
306+
end
307+
expected.to raise_error
308+
end
309+
287310
it 'should return correct variation if rule in forced decision is deleted' do
288311
impression_log_url = 'https://logx.optimizely.com/v1/events'
289312
time_now = Time.now

0 commit comments

Comments
 (0)