@@ -5752,39 +5752,50 @@ def test_decide_returns_error_decision_when_decision_service_fails(self):
57525752 self .assertIn ('CMAB service failed to fetch decision' , decision .reasons )
57535753
57545754 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."""
57565756 import copy
5757+ from typing import List
57575758 config_dict = copy .deepcopy (self .config_dict_with_features )
57585759 config_dict ['experiments' ][0 ]['cmab' ] = {'attributeIds' : ['808797688' , '808797689' ], 'trafficAllocation' : 4000 }
57595760 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 )
57615775 user_context = opt_obj .create_user_context ('test_user' )
57625776 project_config = opt_obj .config_manager .get_config ()
57635777
57645778 # Mock decision service to return a CMAB result
57655779 expected_cmab_uuid = 'uuid-cmab'
57665780 mock_experiment = project_config .get_experiment_from_key ('test_experiment' )
57675781 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- }
57785782
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
57795792 with mock .patch .object (
57805793 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+ }]
57885799 ):
57895800 # Call decide
57905801 decision = user_context .decide ('test_feature_in_experiment' )
@@ -5795,32 +5806,21 @@ def test_decide_includes_cmab_uuid_in_dispatched_event(self):
57955806 self .assertEqual (decision .rule_key , 'test_experiment' )
57965807 self .assertEqual (decision .flag_key , 'test_feature_in_experiment' )
57975808
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