8000 Feature Notification Center by mfahadahmed · Pull Request #35 · optimizely/csharp-sdk · GitHub
[go: up one dir, main page]

Skip to content

Feature Notification Center #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
remvoed feature experiment and featurue rollout notifications.
  • Loading branch information
msohailh committed Nov 22, 2017
commit 3478d57dd4d9f08b82031f900a093ae5be59e8de
21 changes: 1 addition & 20 deletions OptimizelySDK.Tests/NotificationTests/NotificationCenterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ public class NotificationCenterTests

private NotificationType NotificationTypeActivate = NotificationType.Activate;
private NotificationType NotificationTypeTrack = NotificationType.Track;
private NotificationType NotificationTypeFeatureExperiment = NotificationType.FeatureExperiment;
private NotificationType NotificationTypeFeatureRollout = NotificationType.FeatureRollout;

[SetUp]
public void Setup()
Expand Down Expand Up @@ -96,17 +94,10 @@ public void TestAddInvalidNotificationListeners()
// Verify that AddNotification gets failed on adding invalid notification listeners.
Assert.AreEqual(0, NotificationCenter.AddNotification(NotificationTypeTrack,
TestNotificationCallbacks.TestActivateCallback));
Assert.AreEqual(0, NotificationCenter.AddNotification(NotificationTypeFeatureExperiment,
TestNotificationCallbacks.TestTrackCallback));
Assert.AreEqual(0, NotificationCenter.AddNotification(NotificationTypeActivate,
TestNotificationCallbacks.TestFeatureExperimentCallback));


LoggerMock.Verify(l => l.Log(LogLevel.ERROR, $@"Invalid notification type provided for ""{NotificationTypeActivate}"" callback."),
Times.Once);
LoggerMock.Verify(l => l.Log(LogLevel.ERROR, $@"Invalid notification type provided for ""{NotificationTypeTrack}"" callback."),
Times.Once);
LoggerMock.Verify(l => l.Log(LogLevel.ERROR, $@"Invalid notification type provided for ""{NotificationTypeFeatureExperiment}"" callback."),
Times.Once);

// Verify that no notifion has been added.
Assert.AreEqual(0, NotificationCenter.NotificationsCount);
Expand Down Expand Up @@ -181,7 +172,6 @@ public void TestSendNotifications()
// Adding decision notifications.
NotificationCenter.AddNotification(NotificationTypeActivate, notificationCallbackMock.Object.TestActivateCallback);
NotificationCenter.AddNotification(NotificationTypeActivate, notificationCallbackMock.Object.TestAnotherActivateCallback);
NotificationCenter.AddNotification(NotificationTypeFeatureRollout, notificationCallbackMock.Object.TestFeatureRolloutCallback);


// Adding track notifications.
Expand All @@ -202,11 +192,6 @@ public void TestSendNotifications()
It.IsAny<UserAttributes>(), It.IsAny<EventTags>(), It.IsAny<LogEvent>()), Times.Never);


// Fire feature rollout notification
NotificationCenter.SendNotifications(NotificationTypeFeatureRollout, "featureKey", "testUser", new UserAttributes(), null);

notificationCallbackMock.Verify(nc => nc.TestFeatureRolloutCallback(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<Audience[]>()), Times.Once);


// Verify that after clearing notifications, SendNotification should not call any notification
Expand All @@ -227,10 +212,6 @@ public void TestSendNotifications()

notificationCallbackMock.Verify(nc => nc.TestTrackCallback(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<EventTags>(), It.IsAny<LogEvent>()), Times.Never);

notificationCallbackMock.Verify(nc => nc.TestFeatureRolloutCallback(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<Audience[]>()), Times.Never);

}
}

Expand Down
89 changes: 0 additions & 89 deletions OptimizelySDK.Tests/OptimizelyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,95 +1640,6 @@ public void TestTrackListener(UserAttributes userAttributes, EventTags eventTags
NotificationCallbackMock.Verify(nc => nc.TestTrackCallback(eventKey, TestUserId, userAttributes, eventTags, logEvent), Times.Exactly(1));
NotificationCallbackMock.Verify(nc => nc.TestAnotherTrackCallback(eventKey, TestUserId, userAttributes, eventTags, logEvent), Times.Exactly(1));
}

[Test]
public void TestFeatureExperimentListener()
{
var featureKey = "boolean_feature";
var featureFlag = Config.GetFeatureFlagFromKey(featureKey);
var experiment = Config.GetExperimentFromId(featureFlag.ExperimentIds[0]);
var variation = experiment.Variations[0];
var logEvent = new LogEvent("https://logx.optimizely.com/v1/events", OptimizelyHelper.SingleParameter,
"POST", new Dictionary<string, string> { });
var userAttributes = new UserAttributes
{
{ "device_type", "iPhone" },
{ "company", "Optimizely" },
{ "location", "San Francisco" }
};

// Mocking objects.
NotificationCallbackMock.Setup(nc => nc.TestActivateCallback(It.IsAny<Experiment>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<Variation>(), It.IsAny<LogEvent>()));
NotificationCallbackMock.Setup(nc => nc.TestFeatureExperimentCallback(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<Experiment>(), It.IsAny<Variation>()));
EventBuilderMock.Setup(ebm => ebm.CreateImpressionEvent(It.IsAny<ProjectConfig>(), It.IsAny<Experiment>(),
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UserAttributes>())).Returns(logEvent);
DecisionServiceMock.Setup(ds => ds.GetVariationForFeature(featureFlag, TestUserId, userAttributes)).Returns(variation);

// Adding notification listeners.
NotificationCenter.AddNotification(NotificationCenter.NotificationType.Activate,
NotificationCallbackMock.Object.TestActivateCallback);
NotificationCenter.AddNotification(NotificationCenter.NotificationType.FeatureExperiment,
NotificationCallbackMock.Object.TestFeatureExperimentCallback);

var optly = Helper.CreatePrivateOptimizely();
optly.SetFieldOrProperty("NotificationCenter", NotificationCenter);
optly.SetFieldOrProperty("DecisionService", DecisionServiceMock.Object);
optly.SetFieldOrProperty("EventBuilder", EventBuilderMock.Object);

// Calling IsFeatureEnabled.
optly.Invoke("IsFeatureEnabled", featureKey, TestUserId, userAttributes);

// Verify that both of the activate and feature experiment callbacks are called in case of feature experiment.
NotificationCallbackMock.Verify(nc => nc.TestActivateCallback(experiment, TestUserId, userAttributes, variation, logEvent), Times.Exactly(1));
NotificationCallbackMock.Verify(nc => nc.TestFeatureExperimentCallback(featureKey, TestUserId, userAttributes, experiment, variation), Times.Exactly(1));
}

[Test]
public void TestFeatureRolloutListener()
{
var featureKey = "boolean_single_variable_feature";
var featureFlag = Config.GetFeatureFlagFromKey(featureKey);
var rollout = Config.GetRolloutFromId(featureFlag.RolloutId);
var experiment = rollout.Experiments[0];
var variation = experiment.Variations[0];
var logEvent = new LogEvent("https://logx.optimizely.com/v1/events", OptimizelyHelper.SingleParameter,
"POST", new Dictionary<string, string> { });
var userAttributes = new UserAttributes
{
{ "device_type", "iPhone" },
{ "company", "Optimizely" },
{ "location", "San Francisco" }
};

// Mocking objects.
NotificationCallbackMock.Setup(nc => nc.TestActivateCallback(It.IsAny<Experiment>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<Variation>(), It.IsAny<LogEvent>()));
NotificationCallbackMock.Setup(nc => nc.TestFeatureRolloutCallback(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<UserAttributes>(), It.IsAny<Audience[]>()));
EventBuilderMock.Setup(ebm => ebm.CreateImpressionEvent(It.IsAny<ProjectConfig>(), It.IsAny<Experiment>(),
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<UserAttributes>())).Returns(logEvent);
DecisionServiceMock.Setup(ds => ds.GetVariationForFeature(featureFlag, TestUserId, userAttributes)).Returns(variation);

// Adding notification listeners.
NotificationCenter.AddNotification(NotificationCenter.NotificationType.Activate,
NotificationCallbackMock.Object.TestActivateCallback);
NotificationCenter.AddNotification(NotificationCenter.NotificationType.FeatureRollout,
NotificationCallbackMock.Object.TestFeatureRolloutCallback);

var optly = Helper.CreatePrivateOptimizely();
optly.SetFieldOrProperty("NotificationCenter", NotificationCenter);
optly.SetFieldOrProperty("DecisionService", DecisionServiceMock.Object);
optly.SetFieldOrProperty("EventBuilder", EventBuilderMock.Object);

// Calling IsFeatureEnabled.
optly.Invoke("IsFeatureEnabled", featureKey, TestUserId, userAttributes);

// Verify that only feature rollout callback gets called in case of rollout rule.
NotificationCallbackMock.Verify(nc => nc.TestFeatureRolloutCallback(featureKey, TestUserId, userAttributes, It.IsAny<Audience[]>()), Times.Exactly(1));
NotificationCallbackMock.Verify(nc => nc.TestActivateCallback(experiment, TestUserId, userAttributes, variation, logEvent), Times.Never);
}

#endregion // Test NotificationCenter
}
Expand Down
54 changes: 1 addition & 53 deletions OptimizelySDK/Notifications/NotificationCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ public class NotificationCenter
public enum NotificationType
{
Activate, // Activate called.
Track, // Event tracked.
FeatureExperiment, // Feature accessed from experiment.
FeatureRollout // Feature accessed from rollout rule.
Track
};

/// <summary>
Expand All @@ -61,27 +59,6 @@ public delegate void ActivateCallback(Experiment experiment, string userId, User
public delegate void TrackCallback(string eventKey, string userId, UserAttributes userAttributes, EventTags eventTags,
LogEvent logEvent);

/// <summary>
/// Delegate for feature experiment notifcations.
/// </summary>
/// <param name="featureKey">The feature key</param>
/// <param name="userId">The user identifier</param>
/// <param name="userAttributes">Associative array of attributes for the user</param>
/// <param name="experiment">The experiment entity</param>
/// <param name="variation">The variation entity</param>
public delegate void FeatureExperimentCallback(string featureKey, string userId, UserAttributes userAttributes,
Experiment experiment, Variation variation);

/// <summary>
/// Delegate for feature rollout notifcations.
/// </summary>
/// <param name="featureKey">The feature key</param>
/// <param name="userId">The user identifier</param>
/// <param name="userAttributes">Associative array of attributes for the user</param>
/// <param name="audiences">Array of audience</param>
public delegate void FeatureRolloutCallback(string featureKey, string userId, UserAttributes userAttributes,
Audience[] audiences);

private ILogger Logger;

// Notification Id represeting number of notifications.
Expand Down Expand Up @@ -152,35 +129,6 @@ public int AddNotification(NotificationType notificationType, TrackCallback trac
return AddNotification(notificationType, (object)trackCallback);
}

/// <summary>
/// Add a notification callback of feature experiment type to the notification center.
/// </summary>
/// <param name="notificationType">Notification type</param>
/// <param name="featureExperimentCallback">Callback function to call when event gets triggered</param>
/// <returns>int | 0 for invalid notification type, -1 for adding existing notification
/// or the notification id of newly added notification.</returns>
public int AddNotification(NotificationType notificationType, FeatureExperimentCallback featureExperimentCallback)
{
if (!IsNotificationTypeValid(notificationType, NotificationType.FeatureExperiment))
return 0;

return AddNotification(notificationType, (object)featureExperimentCallback);
}

/// <summary>
/// Add a notification callback of feature rollout type to the notification center.
/// </summary>
/// <param name="notificationType">Notification type</param>
/// <param name="featureRolloutCallback">Callback function to call when event gets triggered</param>
/// <returns>int | 0 for invalid notification type, -1 for adding existing notification
/// or the notification id of newly added notification.</returns>
public int AddNotification(NotificationType notificationType, FeatureRolloutCallback featureRolloutCallback)
{
if (!IsNotificationTypeValid(notificationType, NotificationType.FeatureRollout))
return 0;

return AddNotification(notificationType, (object)featureRolloutCallback);
}

/// <summary>
/// Validate notification type.
Expand Down
4 changes: 0 additions & 4 deletions OptimizelySDK/Optimizely.cs
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,6 @@ public Variation GetForcedVariation(string experimentKey, string userId)
if (!string.IsNullOrEmpty(experiment.Key))
{
SendImpressionEvent(experiment, variation, userId, userAttributes);
NotificationCenter.SendNotifications(NotificationCenter.NotificationType.FeatureExperiment, featureKey, userId,
userAttributes, experiment, variation);
}
else
{
Expand All @@ -382,8 +380,6 @@ public Variation GetForcedVariation(string experimentKey, string userId)
audiences[0] = Config.GetAudience(rolloutRule.AudienceIds[0]);
}

NotificationCenter.SendNotifications(NotificationCenter.NotificationType.FeatureRollout, featureKey, userId,
userAttributes, audiences);
Logger.Log(LogLevel.INFO, $@"The user ""{userId}"" is not being experimented on feature ""{featureKey}"".");
}

Expand Down
0