Search in sources :

Example 6 with FeatureDecision

use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.

the class OptimizelyTest method isFeatureEnabledWithListenerUserInExperimentFeatureOff.

/**
 * Verify that the {@link Optimizely#isFeatureEnabled(String, String, Map<String, String>)}
 * notification listener of isFeatureEnabled is called when feature is in experiment and feature is false
 */
@Test
public void isFeatureEnabledWithListenerUserInExperimentFeatureOff() throws Exception {
    assumeTrue(datafileVersion >= Integer.parseInt(ProjectConfig.Version.V4.toString()));
    isListenerCalled = false;
    final String validFeatureKey = FEATURE_MULTI_VARIATE_FEATURE_KEY;
    Optimizely optimizely = optimizelyBuilder.withDecisionService(mockDecisionService).build();
    final Map<String, String> testUserAttributes = new HashMap<>();
    testUserAttributes.put(ATTRIBUTE_HOUSE_KEY, AUDIENCE_GRYFFINDOR_VALUE);
    final Map<String, String> testSourceInfo = new HashMap<>();
    testSourceInfo.put(VARIATION_KEY, "variation_toggled_off");
    testSourceInfo.put(EXPERIMENT_KEY, "multivariate_experiment");
    final Map<String, Object> testDecisionInfoMap = new HashMap<>();
    testDecisionInfoMap.put(FEATURE_KEY, validFeatureKey);
    testDecisionInfoMap.put(FEATURE_ENABLED, false);
    testDecisionInfoMap.put(SOURCE, FeatureDecision.DecisionSource.FEATURE_TEST.toString());
    testDecisionInfoMap.put(SOURCE_INFO, testSourceInfo);
    int notificationId = optimizely.addDecisionNotificationHandler(getDecisionListener(NotificationCenter.DecisionNotificationType.FEATURE.toString(), genericUserId, testUserAttributes, testDecisionInfoMap));
    Experiment activatedExperiment = validProjectConfig.getExperimentKeyMapping().get(EXPERIMENT_MULTIVARIATE_EXPERIMENT_KEY);
    Variation variation = new Variation("2", "variation_toggled_off", false, null);
    FeatureDecision featureDecision = new FeatureDecision(activatedExperiment, variation, FeatureDecision.DecisionSource.FEATURE_TEST);
    doReturn(DecisionResponse.responseNoReasons(featureDecision)).when(mockDecisionService).getVariationForFeature(any(FeatureFlag.class), any(OptimizelyUserContext.class), any(ProjectConfig.class));
    assertFalse(optimizely.isFeatureEnabled(validFeatureKey, genericUserId, testUserAttributes));
    eventHandler.expectImpression(activatedExperiment.getId(), variation.getId(), genericUserId, testUserAttributes);
    logbackVerifier.expectMessage(Level.INFO, "Feature \"" + validFeatureKey + "\" is enabled for user \"" + genericUserId + "\"? false");
    // Verify that listener being called
    assertTrue(isListenerCalled);
    assertTrue(optimizely.notificationCenter.removeNotificationListener(notificationId));
}
Also used : FeatureDecision(com.optimizely.ab.bucketing.FeatureDecision) Test(org.junit.Test)

Example 7 with FeatureDecision

use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.

the class OptimizelyTest method getFeatureVariableValueReturnsDefaultValueWhenFeatureEnabledIsFalse.

/**
 * Verify {@link Optimizely#getFeatureVariableValueForType(String, String, String, Map, FeatureVariable.VariableType)}
 * is called when the variation is not null and feature enabled is false
 * returns the default variable value
 */
@Test
public void getFeatureVariableValueReturnsDefaultValueWhenFeatureEnabledIsFalse() throws Exception {
    assumeTrue(datafileVersion >= Integer.parseInt(ProjectConfig.Version.V4.toString()));
    String validFeatureKey = FEATURE_MULTI_VARIATE_FEATURE_KEY;
    String validVariableKey = VARIABLE_FIRST_LETTER_KEY;
    String expectedValue = VARIABLE_FIRST_LETTER_DEFAULT_VALUE;
    Experiment multivariateExperiment = validProjectConfig.getExperimentKeyMapping().get(EXPERIMENT_MULTIVARIATE_EXPERIMENT_KEY);
    Optimizely optimizely = optimizelyBuilder.withDecisionService(mockDecisionService).build();
    FeatureDecision featureDecision = new FeatureDecision(multivariateExperiment, VARIATION_MULTIVARIATE_EXPERIMENT_GRED, FeatureDecision.DecisionSource.FEATURE_TEST);
    doReturn(DecisionResponse.responseNoReasons(featureDecision)).when(mockDecisionService).getVariationForFeature(FEATURE_FLAG_MULTI_VARIATE_FEATURE, optimizely.createUserContext(genericUserId, Collections.singletonMap(ATTRIBUTE_HOUSE_KEY, AUDIENCE_GRYFFINDOR_VALUE)), validProjectConfig);
    String value = optimizely.getFeatureVariableValueForType(validFeatureKey, validVariableKey, genericUserId, Collections.singletonMap(ATTRIBUTE_HOUSE_KEY, AUDIENCE_GRYFFINDOR_VALUE), FeatureVariable.STRING_TYPE);
    logbackVerifier.expectMessage(Level.INFO, "Feature \"multi_variate_feature\" is not enabled for user \"genericUserId\". Returning the default variable value \"H\".");
    assertEquals(expectedValue, value);
}
Also used : FeatureDecision(com.optimizely.ab.bucketing.FeatureDecision) Test(org.junit.Test)

Example 8 with FeatureDecision

use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.

the class Optimizely method isFeatureEnabled.

/**
 * Determine whether a boolean feature is enabled.
 * Send an impression event if the user is bucketed into an experiment using the feature.
 *
 * @param featureKey The unique key of the feature.
 * @param userId The ID of the user.
 * @param attributes The user's attributes.
 * @return True if the feature is enabled.
 *         False if the feature is disabled.
 *         False if the feature is not found.
 */
@Nonnull
public Boolean isFeatureEnabled(@Nonnull String featureKey, @Nonnull String userId, @Nonnull Map<String, String> attributes) {
    if (featureKey == null) {
        logger.warn("The featureKey parameter must be nonnull.");
        return false;
    } else if (userId == null) {
        logger.warn("The userId parameter must be nonnull.");
        return false;
    }
    FeatureFlag featureFlag = projectConfig.getFeatureKeyMapping().get(featureKey);
    if (featureFlag == null) {
        logger.info("No feature flag was found for key \"{}\".", featureKey);
        return false;
    }
    Map<String, String> filteredAttributes = filterAttributes(projectConfig, attributes);
    FeatureDecision featureDecision = decisionService.getVariationForFeature(featureFlag, userId, filteredAttributes);
    if (featureDecision.variation == null || !featureDecision.variation.getFeatureEnabled()) {
        logger.info("Feature \"{}\" is not enabled for user \"{}\".", featureKey, userId);
        return false;
    } else {
        if (featureDecision.decisionSource.equals(FeatureDecision.DecisionSource.EXPERIMENT)) {
            sendImpression(projectConfig, featureDecision.experiment, userId, filteredAttributes, featureDecision.variation);
        } else {
            logger.info("The user \"{}\" is not included in an experiment for feature \"{}\".", userId, featureKey);
        }
        logger.info("Feature \"{}\" is enabled for user \"{}\".", featureKey, userId);
        return true;
    }
}
Also used : FeatureDecision(com.optimizely.ab.bucketing.FeatureDecision) FeatureFlag(com.optimizely.ab.config.FeatureFlag) Nonnull(javax.annotation.Nonnull)

Example 9 with FeatureDecision

use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.

the class OptimizelyTest method getFeatureVariableValueReturnsVariationValueWhenUserGetsBucketedToVariation.

/**
 * Verify {@link Optimizely#getFeatureVariableValueForType(String, String, String, Map, LiveVariable.VariableType)}
 * returns the variable value of the variation the user is bucketed into
 * if the variation is not null and the variable has a usage within the variation.
 * @throws ConfigParseException
 */
@Test
public void getFeatureVariableValueReturnsVariationValueWhenUserGetsBucketedToVariation() throws ConfigParseException {
    assumeTrue(datafileVersion >= Integer.parseInt(ProjectConfig.Version.V4.toString()));
    String validFeatureKey = FEATURE_MULTI_VARIATE_FEATURE_KEY;
    String validVariableKey = VARIABLE_FIRST_LETTER_KEY;
    LiveVariable variable = FEATURE_FLAG_MULTI_VARIATE_FEATURE.getVariableKeyToLiveVariableMap().get(validVariableKey);
    String expectedValue = VARIATION_MULTIVARIATE_EXPERIMENT_GRED.getVariableIdToLiveVariableUsageInstanceMap().get(variable.getId()).getValue();
    Experiment multivariateExperiment = validProjectConfig.getExperimentKeyMapping().get(EXPERIMENT_MULTIVARIATE_EXPERIMENT_KEY);
    Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler).withConfig(validProjectConfig).withDecisionService(mockDecisionService).build();
    FeatureDecision featureDecision = new FeatureDecision(multivariateExperiment, VARIATION_MULTIVARIATE_EXPERIMENT_GRED, FeatureDecision.DecisionSource.EXPERIMENT);
    doReturn(featureDecision).when(mockDecisionService).getVariationForFeature(FEATURE_FLAG_MULTI_VARIATE_FEATURE, genericUserId, Collections.singletonMap(ATTRIBUTE_HOUSE_KEY, AUDIENCE_GRYFFINDOR_VALUE));
    String value = optimizely.getFeatureVariableValueForType(validFeatureKey, validVariableKey, genericUserId, Collections.singletonMap(ATTRIBUTE_HOUSE_KEY, AUDIENCE_GRYFFINDOR_VALUE), LiveVariable.VariableType.STRING);
    assertEquals(expectedValue, value);
}
Also used : FeatureDecision(com.optimizely.ab.bucketing.FeatureDecision) Experiment(com.optimizely.ab.config.Experiment) Matchers.anyString(org.mockito.Matchers.anyString) LiveVariable(com.optimizely.ab.config.LiveVariable) Test(org.junit.Test)

Example 10 with FeatureDecision

use of com.optimizely.ab.bucketing.FeatureDecision in project java-sdk by optimizely.

the class Optimizely method getAllFeatureVariables.

/**
 * Get the values of all variables in the feature.
 *
 * @param featureKey  The unique key of the feature.
 * @param userId      The ID of the user.
 * @param attributes  The user's attributes.
 * @return An OptimizelyJSON instance for all variable values.
 * Null if the feature could not be found.
 */
@Nullable
public OptimizelyJSON getAllFeatureVariables(@Nonnull String featureKey, @Nonnull String userId, @Nonnull Map<String, ?> attributes) {
    if (featureKey == null) {
        logger.warn("The featureKey parameter must be nonnull.");
        return null;
    } else if (userId == null) {
        logger.warn("The userId parameter must be nonnull.");
        return null;
    }
    ProjectConfig projectConfig = getProjectConfig();
    if (projectConfig == null) {
        logger.error("Optimizely instance is not valid, failing getAllFeatureVariableValues call. type");
        return null;
    }
    FeatureFlag featureFlag = projectConfig.getFeatureKeyMapping().get(featureKey);
    if (featureFlag == null) {
        logger.info("No feature flag was found for key \"{}\".", featureKey);
        return null;
    }
    Map<String, ?> copiedAttributes = copyAttributes(attributes);
    FeatureDecision featureDecision = decisionService.getVariationForFeature(featureFlag, createUserContext(userId, copiedAttributes), projectConfig, Collections.emptyList()).getResult();
    Boolean featureEnabled = false;
    Variation variation = featureDecision.variation;
    if (variation != null) {
        featureEnabled = variation.getFeatureEnabled();
        if (featureEnabled) {
            logger.info("Feature \"{}\" is enabled for user \"{}\".", featureKey, userId);
        } else {
            logger.info("Feature \"{}\" is not enabled for user \"{}\".", featureKey, userId);
        }
    } else {
        logger.info("User \"{}\" was not bucketed into any variation for feature flag \"{}\". " + "The default values are being returned.", userId, featureKey);
    }
    Map<String, Object> valuesMap = new HashMap<String, Object>();
    for (FeatureVariable variable : featureFlag.getVariables()) {
        String value = variable.getDefaultValue();
        if (featureEnabled) {
            FeatureVariableUsageInstance instance = variation.getVariableIdToFeatureVariableUsageInstanceMap().get(variable.getId());
            if (instance != null) {
                value = instance.getValue();
            }
        }
        Object convertedValue = convertStringToType(value, variable.getType());
        if (convertedValue instanceof OptimizelyJSON) {
            convertedValue = ((OptimizelyJSON) convertedValue).toMap();
        }
        valuesMap.put(variable.getKey(), convertedValue);
    }
    DecisionNotification decisionNotification = DecisionNotification.newFeatureVariableDecisionNotificationBuilder().withUserId(userId).withAttributes(copiedAttributes).withFeatureKey(featureKey).withFeatureEnabled(featureEnabled).withVariableValues(valuesMap).withFeatureDecision(featureDecision).build();
    notificationCenter.send(decisionNotification);
    return new OptimizelyJSON(valuesMap);
}
Also used : FeatureDecision(com.optimizely.ab.bucketing.FeatureDecision) OptimizelyJSON(com.optimizely.ab.optimizelyjson.OptimizelyJSON) Nullable(javax.annotation.Nullable)

Aggregations

FeatureDecision (com.optimizely.ab.bucketing.FeatureDecision)16 Test (org.junit.Test)10 OptimizelyJSON (com.optimizely.ab.optimizelyjson.OptimizelyJSON)3 VisibleForTesting (com.optimizely.ab.annotations.VisibleForTesting)2 FeatureFlag (com.optimizely.ab.config.FeatureFlag)2 LiveVariable (com.optimizely.ab.config.LiveVariable)2 Nonnull (javax.annotation.Nonnull)2 Experiment (com.optimizely.ab.config.Experiment)1 LiveVariableUsageInstance (com.optimizely.ab.config.LiveVariableUsageInstance)1 Nullable (javax.annotation.Nullable)1 Matchers.anyString (org.mockito.Matchers.anyString)1