@@ -20,7 +20,7 @@ import OptimizelyUserContext from '../../optimizely_user_context';
20
20
import { bucket } from '../bucketer' ;
21
21
import { getTestProjectConfig , getTestProjectConfigWithFeatures } from '../../tests/test_data' ;
22
22
import { createProjectConfig , ProjectConfig } from '../../project_config/project_config' ;
23
- import { Experiment } from '../../shared_types' ;
23
+ import { BucketerParams , Experiment } from '../../shared_types' ;
24
24
import { CONTROL_ATTRIBUTES , DECISION_SOURCES } from '../../utils/enums' ;
25
25
import { getDecisionTestDatafile } from '../../tests/decision_test_datafile' ;
26
26
@@ -736,5 +736,121 @@ describe('DecisionService', () => {
736
736
expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 2 ,
737
737
config , config . experimentKeyMap [ 'exp_2' ] , user , false , expect . anything ( ) ) ;
738
738
} ) ;
739
+
740
+ describe ( 'when no variation is found for any experiment and a target delivery audience condition is satisfied' , ( ) => {
741
+ beforeEach ( ( ) => {
742
+ mockBucket . mockReset ( ) ;
743
+ } ) ;
744
+
745
+ it ( 'should return variation from the target delivery for which audience condition is satisfied if the user is bucketed into it' , ( ) => {
746
+ const { decisionService } = getDecisionService ( ) ;
747
+
748
+ const resolveVariationSpy = vi . spyOn ( decisionService as any , 'resolveVariation' )
749
+ . mockReturnValue ( {
750
+ result : null ,
751
+ reasons : [ ] ,
752
+ } ) ;
753
+
754
+ const config = createProjectConfig ( getDecisionTestDatafile ( ) ) ;
755
+
756
+ const user = new OptimizelyUserContext ( {
757
+ optimizely : { } as any ,
758
+ userId : 'tester' ,
759
+ attributes : {
760
+ age : 55 , // this should satisfy the audience condition for the targeted delivery with key delivery_2
761
+ } ,
762
+ } ) ;
763
+
764
+ mockBucket . mockImplementation ( ( param : BucketerParams ) => {
765
+ const ruleKey = param . experimentKey ;
766
+ if ( ruleKey === 'delivery_2' ) {
767
+ return {
768
+ result : '5005' ,
769
+ reasons : [ ] ,
770
+ } ;
771
+ }
772
+ return {
773
+ result : null ,
774
+ reasons : [ ] ,
775
+ } ;
776
+ } ) ;
777
+
778
+ const feature = config . featureKeyMap [ 'flag_1' ] ;
779
+ const variation = decisionService . getVariationForFeature ( config , feature , user ) ;
780
+
781
+ expect ( variation . result ) . toEqual ( {
782
+ experiment : config . experimentIdMap [ '3002' ] ,
783
+ variation : config . variationIdMap [ '5005' ] ,
784
+ decisionSource : DECISION_SOURCES . ROLLOUT ,
785
+ } ) ;
786
+
787
+ expect ( resolveVariationSpy ) . toHaveBeenCalledTimes ( 3 ) ;
788
+ expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 1 ,
789
+ config , config . experimentKeyMap [ 'exp_1' ] , user , false , expect . anything ( ) ) ;
790
+ expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 2 ,
791
+ config , config . experimentKeyMap [ 'exp_2' ] , user , false , expect . anything ( ) ) ;
792
+ expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 3 ,
793
+ config , config . experimentKeyMap [ 'exp_3' ] , user , false , expect . anything ( ) ) ;
794
+
795
+ expect ( mockBucket ) . toHaveBeenCalledTimes ( 1 ) ;
796
+ verifyBucketCall ( 0 , config , config . experimentIdMap [ '3002' ] , user ) ;
797
+ } ) ;
798
+
799
+ it ( 'should skip to everyone else targeting rule if the user is not bucketed into the targeted delivery for which \
800
+ audience condition is satisfied' , ( ) => {
801
+ const { decisionService } = getDecisionService ( ) ;
802
+
803
+ const resolveVariationSpy = vi . spyOn ( decisionService as any , 'resolveVariation' )
804
+ . mockReturnValue ( {
805
+ result : null ,
806
+ reasons : [ ] ,
807
+ } ) ;
808
+
809
+ const config = createProjectConfig ( getDecisionTestDatafile ( ) ) ;
810
+
811
+ const user = new OptimizelyUserContext ( {
812
+ optimizely : { } as any ,
813
+ userId : 'tester' ,
814
+ attributes : {
815
+ age : 55 , // this should satisfy the audience condition for the targeted delivery with key delivery_2
816
+ } ,
817
+ } ) ;
818
+
819
+ mockBucket . mockImplementation ( ( param : BucketerParams ) => {
820
+ const ruleKey = param . experimentKey ;
821
+ if ( ruleKey === 'default-rollout-key' ) {
822
+ return {
823
+ result : '5007' ,
824
+ reasons : [ ] ,
825
+ } ;
826
+ }
827
+ return {
828
+ result : null ,
829
+ reasons : [ ] ,
830
+ } ;
831
+ } ) ;
832
+
833
+ const feature = config . featureKeyMap [ 'flag_1' ] ;
834
+ const variation = decisionService . getVariationForFeature ( config , feature , user ) ;
835
+
836
+ expect ( variation . result ) . toEqual ( {
837
+ experiment : config . experimentIdMap [ 'default-rollout-id' ] ,
838
+ variation : config . variationIdMap [ '5007' ] ,
839
+ decisionSource : DECISION_SOURCES . ROLLOUT ,
840
+ } ) ;
841
+
842
+ expect ( resolveVariationSpy ) . toHaveBeenCalledTimes ( 3 ) ;
843
+ expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 1 ,
844
+ config , config . experimentKeyMap [ 'exp_1' ] , user , false , expect . anything ( ) ) ;
845
+ expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 2 ,
846
+ config , config . experimentKeyMap [ 'exp_2' ] , user , false , expect . anything ( ) ) ;
847
+ expect ( resolveVariationSpy ) . toHaveBeenNthCalledWith ( 3 ,
848
+ config , config . experimentKeyMap [ 'exp_3' ] , user , false , expect . anything ( ) ) ;
849
+
850
+ expect ( mockBucket ) . toHaveBeenCalledTimes ( 2 ) ;
851
+ verifyBucketCall ( 0 , config , config . experimentIdMap [ '3002' ] , user ) ;
852
+ verifyBucketCall ( 1 , config , config . experimentIdMap [ 'default-rollout-id' ] , user ) ;
853
+ } ) ;
854
+ } ) ;
739
855
} ) ;
740
856
} ) ;
0 commit comments