@@ -5752,39 +5752,50 @@ def test_decide_returns_error_decision_when_decision_service_fails(self):
5752
5752
self .assertIn ('CMAB service failed to fetch decision' , decision .reasons )
5753
5753
5754
5754
def test_decide_includes_cmab_uuid_in_dispatched_event (self ):
5755
- """Test that decide calls UserEventFactory.create_impression_event with correct CMAB UUID."""
5755
+ """Test that decide dispatches event with correct CMAB UUID."""
5756
5756
import copy
5757
+ from typing import List
5757
5758
config_dict = copy .deepcopy (self .config_dict_with_features )
5758
5759
config_dict ['experiments' ][0 ]['cmab' ] = {'attributeIds' : ['808797688' , '808797689' ], 'trafficAllocation' : 4000 }
5759
5760
config_dict ['experiments' ][0 ]['trafficAllocation' ] = []
5760
- opt_obj = optimizely .Optimizely (json .dumps (config_dict ))
5761
+
5762
+ class TestEventDispatcher :
5763
+ """Custom event dispatcher for testing that captures dispatched events."""
5764
+
5765
+ def __init__ (self ):
5766
+ self .dispatched_events : List [event_builder .Event ] = []
5767
+
5768
+ def dispatch_event (self , event : event_builder .Event ) -> None :
5769
+ """Capture the event instead of actually dispatching it."""
5770
+ self .dispatched_events .append (event )
5771
+
5772
+ test_dispatcher = TestEventDispatcher ()
5773
+
5774
+ opt_obj = optimizely .Optimizely (json .dumps (config_dict ), event_dispatcher = test_dispatcher )
5761
5775
user_context = opt_obj .create_user_context ('test_user' )
5762
5776
project_config = opt_obj .config_manager .get_config ()
5763
5777
5764
5778
# Mock decision service to return a CMAB result
5765
5779
expected_cmab_uuid = 'uuid-cmab'
5766
5780
mock_experiment = project_config .get_experiment_from_key ('test_experiment' )
5767
5781
mock_variation = project_config .get_variation_from_id ('test_experiment' , '111129' )
5768
- decision_result = {
5769
- 'decision' : decision_service .Decision (
5770
- mock_experiment ,
5771
- mock_variation ,
5772
- enums .DecisionSources .FEATURE_TEST ,
5773
- expected_cmab_uuid
5774
- ),
5775
- 'reasons' : [],
5776
- 'error' : False
5777
- }
5778
5782
5783
+ # Create decision with CMAB UUID
5784
+ decision_with_cmab = decision_service .Decision (
5785
+ mock_experiment ,
5786
+ mock_variation ,
5787
+ enums .DecisionSources .FEATURE_TEST ,
5788
+ expected_cmab_uuid
5789
+ )
5790
+
5791
+ # Mock the decision service method that's actually called by decide
5779
5792
with mock .patch .object (
5780
5793
opt_obj .decision_service , 'get_variations_for_feature_list' ,
5781
- return_value = [decision_result ]
5782
- ), mock .patch (
5783
- 'optimizely.event.user_event_factory.UserEventFactory.create_impression_event'
5784
- ) as mock_create_impression , mock .patch (
5785
- 'time.time' , return_value = 42
5786
- ), mock .patch (
5787
- 'uuid.uuid4' , return_value = 'a68cf1ad-0393-4e18-af87-efe8f01a7c9c'
5794
+ return_value = [{
5795
+ 'decision' : decision_with_cmab ,
5796
+ 'reasons' : [],
5797
+ 'error' : False
5798
+ }]
5788
5799
):
5789
5800
# Call decide
5790
5801
decision = user_context .decide ('test_feature_in_experiment' )
@@ -5795,32 +5806,21 @@ def test_decide_includes_cmab_uuid_in_dispatched_event(self):
5795
5806
self .assertEqual (decision .rule_key , 'test_experiment' )
5796
5807
self .assertEqual (decision .flag_key , 'test_feature_in_experiment' )
5797
5808
5798
- # Verify that create_impression_event was called once
5799
- mock_create_impression .assert_called_once ()
5800
-
5801
- # Get the call arguments
5802
- call_args = mock_create_impression .call_args [0 ]
5803
-
5804
- # Verify the correct parameters were passed
5805
- project_config_arg = call_args [0 ]
5806
- experiment_arg = call_args [1 ]
5807
- variation_id_arg = call_args [2 ]
5808
- flag_key_arg = call_args [3 ]
5809
- rule_key_arg = call_args [4 ]
5810
- rule_type_arg = call_args [5 ]
5811
- enabled_arg = call_args [6 ]
5812
- user_id_arg = call_args [7 ]
5813
- attributes_arg = call_args [8 ]
5814
- cmab_uuid_arg = call_args [9 ]
5815
-
5816
- # Verify all parameters
5817
- self .assertEqual (project_config_arg , project_config )
5818
- self .assertEqual (experiment_arg , mock_experiment )
5819
- self .assertEqual (variation_id_arg , '111129' ) # variation.id
5820
- self .assertEqual (flag_key_arg , 'test_feature_in_experiment' )
5821
- self .assertEqual (rule_key_arg , 'test_experiment' )
5822
- self .assertEqual (rule_type_arg , str (enums .DecisionSources .FEATURE_TEST ))
5823
- self .assertTrue (enabled_arg )
5824
- self .assertEqual (user_id_arg , 'test_user' )
5825
- self .assertEqual (attributes_arg , {})
5826
- self .assertEqual (cmab_uuid_arg , expected_cmab_uuid )
5809
+ # Verify an event was dispatched
5810
+ time .sleep (0.1 )
5811
+ self .assertEqual (len (test_dispatcher .dispatched_events ), 1 )
5812
+
5813
+ dispatched_event = test_dispatcher .dispatched_events [0 ]
5814
+
5815
+ # Verify the structure exists before accessing
5816
+ self .assertIn ('visitors' , dispatched_event .params )
5817
+ self .assertTrue (len (dispatched_event .params ['visitors' ]) > 0 )
5818
+ self .assertIn ('snapshots' , dispatched_event .params ['visitors' ][0 ])
5819
+ self .assertTrue (len (dispatched_event .params ['visitors' ][0 ]['snapshots' ]) > 0 )
5820
+ self .assertIn ('decisions' , dispatched_event .params ['visitors' ][0 ]['snapshots' ][0 ])
5821
+ self .assertTrue (len (dispatched_event .params ['visitors' ][0 ]['snapshots' ][0 ]['decisions' ]) > 0 )
5822
+
5823
+ # Get the metadata and assert CMAB UUID
5824
+ metadata = dispatched_event .params ['visitors' ][0 ]['snapshots' ][0 ]['decisions' ][0 ]['metadata' ]
5825
+ self .assertIn ('cmab_uuid' , metadata )
5826
+ self .assertEqual (metadata ['cmab_uuid' ], expected_cmab_uuid )
0 commit comments