@@ -659,6 +659,48 @@ public function testActivateWithAttributesTypedAudienceMismatch()
659659 $ this ->assertNull ($ optimizelyMock ->activate ('typed_audience_experiment ' , 'test_user ' , $ userAttributes ));
660660 }
661661
662+ public function testActivateWithAttributesComplexAudienceMatch ()
663+ {
664+ $ optimizelyMock = $ this ->getMockBuilder (Optimizely::class)
665+ ->setConstructorArgs (array ($ this ->typedAudiencesDataFile , null , null ))
666+ ->setMethods (array ('sendImpressionEvent ' ))
667+ ->getMock ();
668+
669+ $ userAttributes = [
670+ 'house ' => 'Welcome to Slytherin! ' ,
671+ 'lasers ' => 45.5
672+ ];
673+
674+ // Verify that sendImpressionEvent is called once with expected attributes
675+ $ optimizelyMock ->expects ($ this ->exactly (1 ))
676+ ->method ('sendImpressionEvent ' )
677+ ->with ('audience_combinations_experiment ' , 'A ' , 'test_user ' , $ userAttributes );
678+
679+ // Should be included via substring match string audience with id '3988293898', and
680+ // exact match number audience with id '3468206646'
681+ $ this ->assertEquals ('A ' , $ optimizelyMock ->activate ('audience_combinations_experiment ' , 'test_user ' , $ userAttributes ));
682+ }
683+
684+ public function testActivateWithAttributesComplexAudienceMismatch ()
685+ {
686+ $ userAttributes = [
687+ 'house ' => 'Hufflepuff ' ,
688+ 'lasers ' => 45.5
689+ ];
690+
691+ $ optimizelyMock = $ this ->getMockBuilder (Optimizely::class)
692+ ->setConstructorArgs (array ($ this ->typedAudiencesDataFile , null , $ this ->loggerMock ))
693+ ->setMethods (array ('sendImpressionEvent ' ))
694+ ->getMock ();
695+
696+ // Verify that sendImpressionEvent is not called
697+ $ optimizelyMock ->expects ($ this ->never ())
698+ ->method ('sendImpressionEvent ' );
699+
700+ // Call activate
701+ $ this ->assertNull ($ optimizelyMock ->activate ('audience_combinations_experiment ' , 'test_user ' , $ userAttributes ));
702+ }
703+
662704 public function testActivateExperimentNotRunning ()
663705 {
664706 $ optimizelyMock = $ this ->getMockBuilder (Optimizely::class)
@@ -1970,6 +2012,60 @@ public function testTrackWithAttributesTypedAudienceMismatch()
19702012 $ optlyObject ->track ('item_bought ' , 'test_user ' , $ userAttributes , array ('revenue ' => 42 ));
19712013 }
19722014
2015+ public function testTrackWithAttributesComplexAudienceMatch ()
2016+ {
2017+ $ userAttributes = [
2018+ 'house ' => 'Gryffindor ' ,
2019+ 'should_do_it ' => true
2020+ ];
2021+
2022+ $ this ->eventBuilderMock ->expects ($ this ->once ())
2023+ ->method ('createConversionEvent ' )
2024+ ->with (
2025+ $ this ->projectConfigForTypedAudience ,
2026+ 'user_signed_up ' ,
2027+ [
2028+ '1323241598 ' => '1423767504 ' ,
2029+ '1323241599 ' => '1423767505 '
2030+ ],
2031+ 'test_user ' ,
2032+ $ userAttributes ,
2033+ array ('revenue ' => 42 )
2034+ )
2035+ ->willReturn (new LogEvent ('logx.optimizely.com/track ' , ['param1 ' => 'val1 ' ], 'POST ' , []));
2036+
2037+ $ optlyObject = new Optimizely ($ this ->typedAudiencesDataFile , new ValidEventDispatcher (), $ this ->loggerMock );
2038+
2039+ $ eventBuilder = new \ReflectionProperty (Optimizely::class, '_eventBuilder ' );
2040+ $ eventBuilder ->setAccessible (true );
2041+ $ eventBuilder ->setValue ($ optlyObject , $ this ->eventBuilderMock );
2042+
2043+ // Should be included via exact match string audience with id '3468206642', and
2044+ // exact match boolean audience with id '3468206643'
2045+ $ optlyObject ->track ('user_signed_up ' , 'test_user ' , $ userAttributes , array ('revenue ' => 42 ));
2046+ }
2047+
2048+ public function testTrackWithAttributesComplexAudienceMismatch ()
2049+ {
2050+ $ userAttributes = [
2051+ 'house ' => 'Gryffindor ' ,
2052+ 'should_do_it ' => false
2053+ ];
2054+
2055+ $ this ->eventBuilderMock ->expects ($ this ->never ())
2056+ ->method ('createConversionEvent ' );
2057+
2058+ $ optlyObject = new Optimizely ($ this ->typedAudiencesDataFile , new ValidEventDispatcher (), $ this ->loggerMock );
2059+
2060+ $ eventBuilder = new \ReflectionProperty (Optimizely::class, '_eventBuilder ' );
2061+ $ eventBuilder ->setAccessible (true );
2062+ $ eventBuilder ->setValue ($ optlyObject , $ this ->eventBuilderMock );
2063+
2064+ // Should be excluded - exact match boolean audience with id '3468206643' does not match,
2065+ // so the overall conditions fail
2066+ $ optlyObject ->track ('user_signed_up ' , 'test_user ' , $ userAttributes , array ('revenue ' => 42 ));
2067+ }
2068+
19732069 public function testTrackWithEmptyUserID ()
19742070 {
19752071 $ userAttributes = [
@@ -2791,6 +2887,33 @@ public function testIsFeatureEnabledGivenFeatureRolloutTypedAudienceMismatch()
27912887 );
27922888 }
27932889
2890+ public function testIsFeatureEnabledGivenFeatureRolloutComplexAudienceMatch ()
2891+ {
2892+ $ userAttributes = [
2893+ 'house ' => '...Slytherinnn...sss. ' ,
2894+ 'favorite_ice_cream ' => 'matcha '
2895+ ];
2896+
2897+ // Should be included via substring match string audience with id '3988293898', and
2898+ // exists audience with id '3988293899'
2899+ $ this ->assertTrue (
2900+ $ this ->optimizelyTypedAudienceObject ->isFeatureEnabled ('feat2 ' , 'test_user ' , $ userAttributes )
2901+ );
2902+ }
2903+
2904+ public function testIsFeatureEnabledGivenFeatureRolloutComplexAudienceMismatch ()
2905+ {
2906+ $ userAttributes = [
2907+ 'house ' => 'Lannister '
2908+ ];
2909+
2910+ // Should be excluded - substring match string audience with id '3988293898' does not match,
2911+ // and no other audience matches either
2912+ $ this ->assertFalse (
2913+ $ this ->optimizelyTypedAudienceObject ->isFeatureEnabled ('feat2 ' , 'test_user ' , $ userAttributes )
2914+ );
2915+ }
2916+
27942917 public function testIsFeatureEnabledWithEmptyUserID ()
27952918 {
27962919 $ optimizelyMock = $ this ->getMockBuilder (Optimizely::class)
@@ -3423,6 +3546,26 @@ public function testGetFeatureVariableReturnsDefaultValueForTypedAudienceMismatc
34233546 $ this ->assertEquals ('x ' , $ this ->optimizelyTypedAudienceObject ->getFeatureVariableString ('feat_with_var ' , 'x ' , 'user1 ' , $ userAttributes ));
34243547 }
34253548
3549+ public function testGetFeatureVariableReturnsVariableValueForComplexAudienceMatch ()
3550+ {
3551+ $ userAttributes = [
3552+ 'house ' => 'Gryffindor ' ,
3553+ 'lasers ' => 700
3554+ ];
3555+
3556+ // Should be included via exact match string audience with id '3468206642', and
3557+ // greater than audience with id '3468206647'
3558+ $ this ->assertSame (150 , $ this ->optimizelyTypedAudienceObject ->getFeatureVariableInteger ('feat2_with_var ' , 'z ' , 'user1 ' , $ userAttributes ));
3559+ }
3560+
3561+ public function testGetFeatureVariableReturnsDefaultValueForComplexAudienceMismatch ()
3562+ {
3563+ $ userAttributes = [];
3564+
3565+ // Should be excluded - no audiences match with no attributes
3566+ $ this ->assertSame (10 , $ this ->optimizelyTypedAudienceObject ->getFeatureVariableInteger ('feat2_with_var ' , 'z ' , 'user1 ' , $ userAttributes ));
3567+ }
3568+
34263569 public function testSendImpressionEventWithNoAttributes ()
34273570 {
34283571 $ optlyObject = new OptimizelyTester ($ this ->datafile , new ValidEventDispatcher (), $ this ->loggerMock );
0 commit comments