@@ -1718,6 +1718,205 @@ describe('DecisionService', () => {
1718
1718
} ) ;
1719
1719
} ) ;
1720
1720
1721
+ describe ( 'resolveVariationForFeatureList - sync' , ( ) => {
1722
+ beforeEach ( ( ) => {
1723
+ mockBucket . mockReset ( ) ;
1724
+ } ) ;
1725
+
1726
+ it ( 'should skip cmab experiments' , async ( ) => {
1727
+ const { decisionService, cmabService } = getDecisionService ( ) ;
1728
+ const config = createProjectConfig ( getDecisionTestDatafile ( ) ) ;
1729
+
1730
+ const user = new OptimizelyUserContext ( {
1731
+ optimizely : { } as any ,
1732
+ userId : 'tester' ,
1733
+ attributes : {
1734
+ age : 15 , // should satisfy audience condition for all experiments and targeted delivery
1735
+ } ,
1736
+ } ) ;
1737
+
1738
+ mockBucket . mockImplementation ( ( param : BucketerParams ) => {
1739
+ const ruleKey = param . experimentKey ;
1740
+ if ( ruleKey === 'delivery_1' ) {
1741
+ return {
1742
+ result : '5004' ,
1743
+ reasons : [ ] ,
1744
+ } ;
1745
+ }
1746
+ return {
1747
+ result : null ,
1748
+ reasons : [ ] ,
1749
+ } ;
1750
+ } ) ;
1751
+
1752
+ const feature = config . featureKeyMap [ 'flag_1' ] ;
1753
+ const value = decisionService . resolveVariationsForFeatureList ( 'sync' , config , [ feature ] , user , { } ) . get ( ) ;
1754
+
1755
+ const variation = value [ 0 ] ;
1756
+
1757
+ expect ( variation . result ) . toEqual ( {
1758
+ experiment : config . experimentKeyMap [ 'delivery_1' ] ,
1759
+ variation : config . variationIdMap [ '5004' ] ,
1760
+ decisionSource : DECISION_SOURCES . ROLLOUT ,
1761
+ } ) ;
1762
+
1763
+ expect ( mockBucket ) . toHaveBeenCalledTimes ( 3 ) ;
1764
+ verifyBucketCall ( 0 , config , config . experimentKeyMap [ 'exp_1' ] , user ) ;
1765
+ verifyBucketCall ( 1 , config , config . experimentKeyMap [ 'exp_2' ] , user ) ;
1766
+ verifyBucketCall ( 2 , config , config . experimentKeyMap [ 'delivery_1' ] , user ) ;
1767
+
1768
+ expect ( cmabService . getDecision ) . not . toHaveBeenCalled ( ) ;
1769
+ } ) ;
1770
+
1771
+ it ( 'should ignore async user profile service' , async ( ) => {
1772
+ const { decisionService, userProfileServiceAsync } = getDecisionService ( {
1773
+ userProfileService : false ,
1774
+ userProfileServiceAsync : true ,
1775
+ } ) ;
1776
+
1777
+ userProfileServiceAsync ?. lookup . mockResolvedValue ( {
1778
+ user_id : 'tester' ,
1779
+ experiment_bucket_map : {
1780
+ '2002' : {
1781
+ variation_id : '5001' ,
1782
+ } ,
1783
+ } ,
1784
+ } ) ;
1785
+ userProfileServiceAsync ?. save . mockResolvedValue ( null ) ;
1786
+
1787
+ mockBucket . mockImplementation ( ( param : BucketerParams ) => {
1788
+ const ruleKey = param . experimentKey ;
1789
+ if ( ruleKey === 'exp_2' ) {
1790
+ return {
1791
+ result : '5002' ,
1792
+ reasons : [ ] ,
1793
+ } ;
1794
+ }
1795
+ return {
1796
+ result : null ,
1797
+ reasons : [ ] ,
1798
+ } ;
1799
+ } ) ;
1800
+
1801
+ const config = createProjectConfig ( getDecisionTestDatafile ( ) ) ;
1802
+
1803
+ const user = new OptimizelyUserContext ( {
1804
+ optimizely : { } as any ,
1805
+ userId : 'tester' ,
1806
+ attributes : {
1807
+ age : 55 , // should satisfy audience condition for exp_2 and exp_3
1808
+ } ,
1809
+ } ) ;
1810
+
1811
+ const feature = config . featureKeyMap [ 'flag_1' ] ;
1812
+ const value = decisionService . resolveVariationsForFeatureList ( 'sync' , config , [ feature ] , user , { } ) . get ( ) ;
1813
+
1814
+ const variation = value [ 0 ] ;
1815
+
1816
+ expect ( variation . result ) . toEqual ( {
1817
+ experiment : config . experimentKeyMap [ 'exp_2' ] ,
1818
+ variation : config . variationIdMap [ '5002' ] ,
1819
+ decisionSource : DECISION_SOURCES . FEATURE_TEST ,
1820
+ } ) ;
1821
+
1822
+ expect ( userProfileServiceAsync ?. lookup ) . not . toHaveBeenCalled ( ) ;
1823
+ expect ( userProfileServiceAsync ?. save ) . not . toHaveBeenCalled ( ) ;
1824
+ } ) ;
1825
+
1826
+ it ( 'should use sync user profile service' , async ( ) => {
1827
+ const { decisionService, userProfileService, userProfileServiceAsync } = getDecisionService ( {
1828
+ userProfileService : true ,
1829
+ userProfileServiceAsync : true ,
1830
+ } ) ;
1831
+
1832
+ userProfileService ?. lookup . mockImplementation ( ( userId : string ) => {
1833
+ if ( userId === 'tester-1' ) {
1834
+ return {
1835
+ user_id : 'tester-1' ,
1836
+ experiment_bucket_map : {
1837
+ '2002' : {
1838
+ variation_id : '5001' ,
1839
+ } ,
1840
+ } ,
1841
+ } ;
1842
+ }
1843
+ return null ;
1844
+ } ) ;
1845
+
1846
+ userProfileServiceAsync ?. lookup . mockResolvedValue ( null ) ;
1847
+ userProfileServiceAsync ?. save . mockResolvedValue ( null ) ;
1848
+
1849
+ mockBucket . mockImplementation ( ( param : BucketerParams ) => {
1850
+ const ruleKey = param . experimentKey ;
1851
+ if ( ruleKey === 'exp_2' ) {
1852
+ return {
1853
+ result : '5002' ,
1854
+ reasons : [ ] ,
1855
+ } ;
1856
+ }
1857
+ return {
1858
+ result : null ,
1859
+ reasons : [ ] ,
1860
+ } ;
1861
+ } ) ;
1862
+
1863
+ const config = createProjectConfig ( getDecisionTestDatafile ( ) ) ;
1864
+
1865
+ const user1 = new OptimizelyUserContext ( {
1866
+ optimizely : { } as any ,
1867
+ userId : 'tester-1' ,
1868
+ attributes : {
1869
+ age : 55 , // should satisfy audience condition for exp_2 and exp_3
1870
+ } ,
1871
+ } ) ;
1872
+
1873
+ const feature = config . featureKeyMap [ 'flag_1' ] ;
1874
+ const value = decisionService . resolveVariationsForFeatureList ( 'sync' , config , [ feature ] , user1 , { } ) . get ( ) ;
1875
+
1876
+ const variation = value [ 0 ] ;
1877
+
1878
+ expect ( variation . result ) . toEqual ( {
1879
+ experiment : config . experimentKeyMap [ 'exp_2' ] ,
1880
+ variation : config . variationIdMap [ '5001' ] ,
1881
+ decisionSource : DECISION_SOURCES . FEATURE_TEST ,
1882
+ } ) ;
1883
+
1884
+ expect ( userProfileService ?. lookup ) . toHaveBeenCalledTimes ( 1 ) ;
1885
+ expect ( userProfileService ?. lookup ) . toHaveBeenCalledWith ( 'tester-1' ) ;
1886
+
1887
+ const user2 = new OptimizelyUserContext ( {
1888
+ optimizely : { } as any ,
1889
+ userId : 'tester-2' ,
1890
+ attributes : {
1891
+ age : 55 , // should satisfy audience condition for exp_2 and exp_3
1892
+ } ,
1893
+ } ) ;
1894
+
1895
+ const value2 = decisionService . resolveVariationsForFeatureList ( 'sync' , config , [ feature ] , user2 , { } ) . get ( ) ;
1896
+ const variation2 = value2 [ 0 ] ;
1897
+ expect ( variation2 . result ) . toEqual ( {
1898
+ experiment : config . experimentKeyMap [ 'exp_2' ] ,
1899
+ variation : config . variationIdMap [ '5002' ] ,
1900
+ decisionSource : DECISION_SOURCES . FEATURE_TEST ,
1901
+ } ) ;
1902
+
1903
+ expect ( userProfileService ?. lookup ) . toHaveBeenCalledTimes ( 2 ) ;
1904
+ expect ( userProfileService ?. lookup ) . toHaveBeenNthCalledWith ( 2 , 'tester-2' ) ;
1905
+ expect ( userProfileService ?. save ) . toHaveBeenCalledTimes ( 1 ) ;
1906
+ expect ( userProfileService ?. save ) . toHaveBeenCalledWith ( {
1907
+ user_id : 'tester-2' ,
1908
+ experiment_bucket_map : {
1909
+ '2002' : {
1910
+ variation_id : '5002' ,
1911
+ } ,
1912
+ } ,
1913
+ } ) ;
1914
+
1915
+ expect ( userProfileServiceAsync ?. lookup ) . not . toHaveBeenCalled ( ) ;
1916
+ expect ( userProfileServiceAsync ?. save ) . not . toHaveBeenCalled ( ) ;
1917
+ } ) ;
1918
+ } ) ;
1919
+
1721
1920
describe ( 'getVariationsForFeatureList' , ( ) => {
1722
1921
beforeEach ( ( ) => {
1723
1922
mockBucket . mockReset ( ) ;
0 commit comments