@@ -1419,4 +1419,322 @@ describe('DecisionService', () => {
1419
1419
} ) ;
1420
1420
} ) ;
1421
1421
} ) ;
1422
+
1423
+
1424
+ describe ( 'forced variation management' , ( ) => {
1425
+ it ( 'should return true for a valid forcedVariation in setForcedVariation' , function ( ) {
1426
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1427
+ const { decisionService } = getDecisionService ( ) ;
1428
+
1429
+ const didSetVariation = decisionService . setForcedVariation (
1430
+ config ,
1431
+ 'testExperiment' ,
1432
+ 'user1' ,
1433
+ 'control'
1434
+ ) ;
1435
+ expect ( didSetVariation ) . toBe ( true ) ;
1436
+ } ) ;
1437
+
1438
+ it ( 'should return the same variation from getVariation as was set in setVariation' , function ( ) {
1439
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1440
+ const { decisionService } = getDecisionService ( ) ;
1441
+ decisionService . setForcedVariation (
1442
+ config ,
1443
+ 'testExperiment' ,
1444
+ 'user1' ,
1445
+ 'control'
1446
+ ) ;
1447
+
1448
+ const variation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1449
+ expect ( variation ) . toBe ( 'control' ) ;
1450
+ } ) ;
1451
+
1452
+ it ( 'should return null from getVariation if no forced variation was set for a valid experimentKey' , function ( ) {
1453
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1454
+ const { decisionService } = getDecisionService ( ) ;
1455
+
1456
+ expect ( config . experimentKeyMap [ 'testExperiment' ] ) . toBeDefined ( ) ;
1457
+ const variation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1458
+
1459
+ expect ( variation ) . toBe ( null ) ;
1460
+ } ) ;
1461
+
1462
+ it ( 'should return null from getVariation for an invalid experimentKey' , function ( ) {
1463
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1464
+ const { decisionService } = getDecisionService ( ) ;
1465
+
1466
+ expect ( config . experimentKeyMap [ 'definitely_not_valid_exp_key' ] ) . not . toBeDefined ( ) ;
1467
+ const variation = decisionService . getForcedVariation ( config , 'definitely_not_valid_exp_key' , 'user1' ) . result ;
1468
+
1469
+ expect ( variation ) . toBe ( null ) ;
1470
+ } ) ;
1471
+
1472
+ it ( 'should return null when a forced decision is set on another experiment key' , function ( ) {
1473
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1474
+ const { decisionService } = getDecisionService ( ) ;
1475
+
1476
+ decisionService . setForcedVariation ( config , 'testExperiment' , 'user1' , 'control' ) ;
1477
+ var variation = decisionService . getForcedVariation ( config , 'testExperimentLaunched' , 'user1' ) . result ;
1478
+ expect ( variation ) . toBe ( null ) ;
1479
+ } ) ;
1480
+
1481
+ it ( 'should not set forced variation for an invalid variation key and return false' , function ( ) {
1482
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1483
+ const { decisionService } = getDecisionService ( ) ;
1484
+
1485
+ const wasSet = decisionService . setForcedVariation (
1486
+ config ,
1487
+ 'testExperiment' ,
1488
+ 'user1' ,
1489
+ 'definitely_not_valid_variation_key'
1490
+ ) ;
1491
+
1492
+ expect ( wasSet ) . toBe ( false ) ;
1493
+ const variation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1494
+ expect ( variation ) . toBe ( null ) ;
1495
+ } ) ;
1496
+
1497
+ it ( 'should reset the forcedVariation if null is passed to setForcedVariation' , function ( ) {
1498
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1499
+ const { decisionService } = getDecisionService ( ) ;
1500
+
1501
+ const didSetVariation = decisionService . setForcedVariation (
1502
+ config ,
1503
+ 'testExperiment' ,
1504
+ 'user1' ,
1505
+ 'control'
1506
+ ) ;
1507
+
1508
+ expect ( didSetVariation ) . toBe ( true ) ;
1509
+
1510
+ let variation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1511
+ expect ( variation ) . toBe ( 'control' ) ;
1512
+
1513
+ const didSetVariationAgain = decisionService . setForcedVariation (
1514
+ config ,
1515
+ 'testExperiment' ,
1516
+ 'user1' ,
1517
+ null
1518
+ ) ;
1519
+
1520
+ expect ( didSetVariationAgain ) . toBe ( true ) ;
1521
+
1522
+ variation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1523
+ expect ( variation ) . toBe ( null ) ;
1524
+ } ) ;
1525
+
1526
+ it ( 'should be able to add variations for multiple experiments for one user' , function ( ) {
1527
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1528
+ const { decisionService } = getDecisionService ( ) ;
1529
+
1530
+ const didSetVariation1 = decisionService . setForcedVariation (
1531
+ config ,
1532
+ 'testExperiment' ,
1533
+ 'user1' ,
1534
+ 'control'
1535
+ ) ;
1536
+ expect ( didSetVariation1 ) . toBe ( true ) ;
1537
+
1538
+ const didSetVariation2 = decisionService . setForcedVariation (
1539
+ config ,
1540
+ 'testExperimentLaunched' ,
1541
+ 'user1' ,
1542
+ 'controlLaunched'
1543
+ ) ;
1544
+ expect ( didSetVariation2 ) . toBe ( true ) ;
1545
+
1546
+ const variation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1547
+ const variation2 = decisionService . getForcedVariation ( config , 'testExperimentLaunched' , 'user1' ) . result ;
1548
+ expect ( variation ) . toBe ( 'control' ) ;
1549
+ expect ( variation2 ) . toBe ( 'controlLaunched' ) ;
1550
+ } ) ;
1551
+
1552
+ it ( 'should be able to forced variation to same experiment for multiple users' , function ( ) {
1553
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1554
+ const { decisionService } = getDecisionService ( ) ;
1555
+
1556
+ const didSetVariation1 = decisionService . setForcedVariation (
1557
+ config ,
1558
+ 'testExperiment' ,
1559
+ 'user1' ,
1560
+ 'control'
1561
+ ) ;
1562
+ expect ( didSetVariation1 ) . toBe ( true ) ;
1563
+
1564
+ const didSetVariation2 = decisionService . setForcedVariation (
1565
+ config ,
1566
+ 'testExperiment' ,
1567
+ 'user2' ,
1568
+ 'variation'
1569
+ ) ;
1570
+ expect ( didSetVariation2 ) . toBe ( true ) ;
1571
+
1572
+ const variationControl = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1573
+ const variationVariation = decisionService . getForcedVariation ( config , 'testExperiment' , 'user2' ) . result ;
1574
+
1575
+ expect ( variationControl ) . toBe ( 'control' ) ;
1576
+ expect ( variationVariation ) . toBe ( 'variation' ) ;
1577
+ } ) ;
1578
+
1579
+ it ( 'should be able to reset a variation for a user with multiple experiments' , function ( ) {
1580
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1581
+ const { decisionService } = getDecisionService ( ) ;
1582
+
1583
+ // Set the first time
1584
+ const didSetVariation1 = decisionService . setForcedVariation (
1585
+ config ,
1586
+ 'testExperiment' ,
1587
+ 'user1' ,
1588
+ 'control'
1589
+ ) ;
1590
+ expect ( didSetVariation1 ) . toBe ( true ) ;
1591
+
1592
+ const didSetVariation2 = decisionService . setForcedVariation (
1593
+ config ,
1594
+ 'testExperimentLaunched' ,
1595
+ 'user1' ,
1596
+ 'controlLaunched'
1597
+ ) ;
1598
+ expect ( didSetVariation2 ) . toBe ( true ) ;
1599
+
1600
+ let variation1 = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1601
+ let variation2 = decisionService . getForcedVariation ( config , 'testExperimentLaunched' , 'user1' ) . result ;
1602
+
1603
+ expect ( variation1 ) . toBe ( 'control' ) ;
1604
+ expect ( variation2 ) . toBe ( 'controlLaunched' ) ;
1605
+
1606
+ // Reset for one of the experiments
1607
+ const didSetVariationAgain = decisionService . setForcedVariation (
1608
+ config ,
1609
+ 'testExperiment' ,
1610
+ 'user1' ,
1611
+ 'variation'
1612
+ ) ;
1613
+ expect ( didSetVariationAgain ) . toBe ( true ) ;
1614
+
1615
+ variation1 = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1616
+ variation2 = decisionService . getForcedVariation ( config , 'testExperimentLaunched' , 'user1' ) . result ;
1617
+
1618
+ expect ( variation1 ) . toBe ( 'variation' ) ;
1619
+ expect ( variation2 ) . toBe ( 'controlLaunched' ) ;
1620
+ } ) ;
1621
+
1622
+ it ( 'should be able to unset a variation for a user with multiple experiments' , function ( ) {
1623
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1624
+ const { decisionService } = getDecisionService ( ) ;
1625
+
1626
+ // Set the first time
1627
+ const didSetVariation1 = decisionService . setForcedVariation (
1628
+ config ,
1629
+ 'testExperiment' ,
1630
+ 'user1' ,
1631
+ 'control'
1632
+ ) ;
1633
+ expect ( didSetVariation1 ) . toBe ( true ) ;
1634
+
1635
+ const didSetVariation2 = decisionService . setForcedVariation (
1636
+ config ,
1637
+ 'testExperimentLaunched' ,
1638
+ 'user1' ,
1639
+ 'controlLaunched'
1640
+ ) ;
1641
+ expect ( didSetVariation2 ) . toBe ( true ) ;
1642
+
1643
+ let variation1 = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1644
+ let variation2 = decisionService . getForcedVariation ( config , 'testExperimentLaunched' , 'user1' ) . result ;
1645
+
1646
+ expect ( variation1 ) . toBe ( 'control' ) ;
1647
+ expect ( variation2 ) . toBe ( 'controlLaunched' ) ;
1648
+
1649
+ // Unset for one of the experiments
1650
+ decisionService . setForcedVariation ( config , 'testExperiment' , 'user1' , null ) ;
1651
+
1652
+ variation1 = decisionService . getForcedVariation ( config , 'testExperiment' , 'user1' ) . result ;
1653
+ variation2 = decisionService . getForcedVariation ( config , 'testExperimentLaunched' , 'user1' ) . result ;
1654
+
1655
+ expect ( variation1 ) . toBe ( null ) ;
1656
+ expect ( variation2 ) . toBe ( 'controlLaunched' ) ;
1657
+ } ) ;
1658
+
1659
+ it ( 'should return false for an empty variation key' , function ( ) {
1660
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1661
+ const { decisionService } = getDecisionService ( ) ;
1662
+
1663
+ const didSetVariation = decisionService . setForcedVariation ( config , 'testExperiment' , 'user1' , '' ) ;
1664
+ expect ( didSetVariation ) . toBe ( false ) ;
1665
+ } ) ;
1666
+
1667
+ it ( 'should return null when a variation was previously set, and that variation no longer exists on the config object' , function ( ) {
1668
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1669
+ const { decisionService } = getDecisionService ( ) ;
1670
+
1671
+ const didSetVariation = decisionService . setForcedVariation (
1672
+ config ,
1673
+ 'testExperiment' ,
1674
+ 'user1' ,
1675
+ 'control'
1676
+ ) ;
1677
+ expect ( didSetVariation ) . toBe ( true ) ;
1678
+
1679
+ const newDatafile = cloneDeep ( testData ) ;
1680
+ // Remove 'control' variation from variations, traffic allocation, and datafile forcedVariations.
1681
+ newDatafile . experiments [ 0 ] . variations = [
1682
+ {
1683
+ key : 'variation' ,
1684
+ id : '111129' ,
1685
+ } ,
1686
+ ] ;
1687
+ newDatafile . experiments [ 0 ] . trafficAllocation = [
1688
+ {
1689
+ entityId : '111129' ,
1690
+ endOfRange : 9000 ,
1691
+ } ,
1692
+ ] ;
1693
+ newDatafile . experiments [ 0 ] . forcedVariations = {
1694
+ user1 : 'variation' ,
1695
+ user2 : 'variation' ,
1696
+ } ;
1697
+ // Now the only variation in testExperiment is 'variation'
1698
+ const newConfigObj = createProjectConfig ( newDatafile ) ;
1699
+ const forcedVar = decisionService . getForcedVariation ( newConfigObj , 'testExperiment' , 'user1' ) . result ;
1700
+ expect ( forcedVar ) . toBe ( null ) ;
1701
+ } ) ;
1702
+
1703
+ it ( "should return null when a variation was previously set, and that variation's experiment no longer exists on the config object" , function ( ) {
1704
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1705
+ const { decisionService } = getDecisionService ( ) ;
1706
+
1707
+ const didSetVariation = decisionService . setForcedVariation (
1708
+ config ,
1709
+ 'testExperiment' ,
1710
+ 'user1' ,
1711
+ 'control'
1712
+ ) ;
1713
+ expect ( didSetVariation ) . toBe ( true ) ;
1714
+
1715
+ const newConfigObj = createProjectConfig ( cloneDeep ( testDataWithFeatures ) ) ;
1716
+ const forcedVar = decisionService . getForcedVariation ( newConfigObj , 'testExperiment' , 'user1' ) . result ;
1717
+ expect ( forcedVar ) . toBe ( null ) ;
1718
+ } ) ;
1719
+
1720
+ it ( 'should return false from setForcedVariation and not set for invalid experiment key' , function ( ) {
1721
+ const config = createProjectConfig ( cloneDeep ( testData ) ) ;
1722
+ const { decisionService } = getDecisionService ( ) ;
1723
+
1724
+ const didSetVariation = decisionService . setForcedVariation (
1725
+ config ,
1726
+ 'definitelyNotAValidExperimentKey' ,
1727
+ 'user1' ,
1728
+ 'control'
1729
+ ) ;
1730
+ expect ( didSetVariation ) . toBe ( false ) ;
1731
+
1732
+ const variation = decisionService . getForcedVariation (
1733
+ config ,
1734
+ 'definitelyNotAValidExperimentKey' ,
1735
+ 'user1'
1736
+ ) . result ;
1737
+ expect ( variation ) . toBe ( null ) ;
1738
+ } ) ;
1739
+ } ) ;
1422
1740
} ) ;
0 commit comments