@@ -659,6 +659,48 @@ public function testActivateWithAttributesTypedAudienceMismatch()
659
659
$ this ->assertNull ($ optimizelyMock ->activate ('typed_audience_experiment ' , 'test_user ' , $ userAttributes ));
660
660
}
661
661
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
+
662
704
public function testActivateExperimentNotRunning ()
663
705
{
664
706
$ optimizelyMock = $ this ->getMockBuilder (Optimizely::class)
@@ -1970,6 +2012,60 @@ public function testTrackWithAttributesTypedAudienceMismatch()
1970
2012
$ optlyObject ->track ('item_bought ' , 'test_user ' , $ userAttributes , array ('revenue ' => 42 ));
1971
2013
}
1972
2014
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
+
1973
2069
public function testTrackWithEmptyUserID ()
1974
2070
{
1975
2071
$ userAttributes = [
@@ -2791,6 +2887,33 @@ public function testIsFeatureEnabledGivenFeatureRolloutTypedAudienceMismatch()
2791
2887
);
2792
2888
}
2793
2889
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
+
2794
2917
public function testIsFeatureEnabledWithEmptyUserID ()
2795
2918
{
2796
2919
$ optimizelyMock = $ this ->getMockBuilder (Optimizely::class)
@@ -3423,6 +3546,26 @@ public function testGetFeatureVariableReturnsDefaultValueForTypedAudienceMismatc
3423
3546
$ this ->assertEquals ('x ' , $ this ->optimizelyTypedAudienceObject ->getFeatureVariableString ('feat_with_var ' , 'x ' , 'user1 ' , $ userAttributes ));
3424
3547
}
3425
3548
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
+
3426
3569
public function testSendImpressionEventWithNoAttributes ()
3427
3570
{
3428
3571
$ optlyObject = new OptimizelyTester ($ this ->datafile , new ValidEventDispatcher (), $ this ->loggerMock );
0 commit comments