public async Task ChannelsWithMessageUpdates_CanBeChanged() { var shortCircuited = false; var deleted = false; await RunTest(); Assert.IsTrue(shortCircuited, "Non-updating channel didn't short-circuit"); Assert.IsFalse(deleted, "Non-updating channel deleted activity"); await RunTest(middleware => middleware.ChannelsWithMessageUpdates.Add(Channels.Test)); Assert.IsFalse(shortCircuited, "Updating channel short-circuited"); Assert.IsTrue(deleted, "Updating channel didn't delete activity"); async Task RunTest(Action <CardManagerMiddleware> action = null) { const string ActionId = "action ID"; var botState = CreateUserState(); var middleware = new CardManagerMiddleware(new CardManager(botState)); var adapter = new TestAdapter().Use(middleware); var cardActivity = MessageFactory.Attachment(new HeroCard(buttons: new List <CardAction> { new CardAction(ActionTypes.PostBack, value: new object()), }).ToAttachment()); var actionActivity = new Activity(value: new JObject { { DataIdScopes.Action, ActionId } }.WrapLibraryData()); action?.Invoke(middleware); middleware.UpdatingOptions.IdOptions.Set(DataIdScopes.Action, ActionId); middleware.NonUpdatingOptions.IdOptions.Set(DataIdScopes.Action, ActionId); await new TestFlow(adapter, async(turnContext, cancellationToken) => { if (turnContext.Activity.Value == null) { await turnContext.SendActivityAsync(cardActivity); } shortCircuited = false; await botState.SaveChangesAsync(turnContext); }) .Send("hi") .Do(() => Assert.IsTrue(adapter.ActiveQueue.Contains(cardActivity))) .Send(actionActivity) .Do(() => deleted = !adapter.ActiveQueue.Contains(cardActivity)) .Do(() => shortCircuited = true) .Send(actionActivity) .StartTestAsync(); } }
public async Task OnDeleteActivity_Ignore() { const string UserSays_PleaseDelete = "please delete"; await RunTest(true, 1); await RunTest(false, 0); async Task RunTest(bool ignore, int activityCount) { var botState = CreateUserState(); var accessor = botState.CreateProperty <CardManagerState>(nameof(CardManagerState)); var middleware = new CardManagerMiddleware(new CardManager(botState)); var adapter = new TestAdapter().Use(middleware); var cardActivity = MessageFactory.Attachment(new HeroCard(buttons: new List <CardAction> { new CardAction(ActionTypes.PostBack, value: new JObject()), }).ToAttachment()); ResourceResponse response = null; middleware.ChannelsWithMessageUpdates.Add(Channels.Test); await new TestFlow(adapter, async(turnContext, cancellationToken) => { if (turnContext.Activity.Text == UserSays_PleaseDelete) { if (ignore) { var ignoreDelete = turnContext.TurnState.Get <CardManagerTurnState>()?.MiddlewareIgnoreDelete; ignoreDelete?.Add(response.Id); } await turnContext.DeleteActivityAsync(response.Id); } else { response = await turnContext.SendActivityAsync(cardActivity); } var state = await accessor.GetNotNullAsync(turnContext, () => new CardManagerState()); await turnContext.SendActivityAsync($"Saved: {state.SavedActivities.Count}"); await botState.SaveChangesAsync(turnContext); }) .Send("hi") .AssertReply(cardActivity, EqualityComparer <IActivity> .Default) .AssertReply($"Saved: {1}") .Send(UserSays_PleaseDelete) .AssertReply($"Saved: {activityCount}") .StartTestAsync(); } }
public AdapterWithMiddleware( IConfiguration configuration, InspectionState inspectionState, ConversationState conversationState, CardManager cardManager, ILogger <BotFrameworkHttpAdapter> logger) : base(configuration, logger) { // Inspection needs credentials because it will be sending the Activities and User and Conversation State to the emulator var credentials = new MicrosoftAppCredentials(configuration["MicrosoftAppId"], configuration["MicrosoftAppPassword"]); Use(new InspectionMiddleware(inspectionState, null, conversationState, credentials)); var cardManagerMiddleware = new CardManagerMiddleware(cardManager); cardManagerMiddleware.NonUpdatingOptions.AutoClearEnabledOnSend = false; Use(cardManagerMiddleware .SetAutoApplyIds(false) .SetIdOptions(new DataIdOptions(new[] { DataIdScopes.Action, DataIdScopes.Card, DataIdScopes.Carousel, DataIdScopes.Batch, }))); OnTurnError = async(turnContext, exception) => { // Log any leaked exception from the application. logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); // Send a message to the user await turnContext.SendActivityAsync("The bot encountered an error or bug."); await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); // Send a trace activity, which will be displayed in the Bot Framework Emulator await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); }; }
public async Task IdTrackingStyle_Disabled() { const string ActionId = "action ID"; var botState = CreateUserState(); var accessor = botState.CreateProperty <CardManagerState>(nameof(CardManagerState)); var middleware = new CardManagerMiddleware(new CardManager(botState)); var adapter = new TestAdapter().Use(middleware); var cardActivity = MessageFactory.Attachment(new HeroCard(buttons: new List <CardAction> { new CardAction(ActionTypes.PostBack, value: new object()), }).ToAttachment()); var actionActivity = new Activity(value: new JObject { { DataIdScopes.Action, ActionId } }.WrapLibraryData()); middleware.NonUpdatingOptions.IdTrackingStyle = TrackingStyle.TrackDisabled; middleware.NonUpdatingOptions.IdOptions.Set(DataIdScopes.Action, ActionId); await new TestFlow(adapter, async(turnContext, cancellationToken) => { if (turnContext.Activity.Value == null) { await turnContext.SendActivityAsync(cardActivity); } var state = await accessor.GetNotNullAsync(turnContext, () => new CardManagerState()); await turnContext.SendActivityAsync( $"Tracked: {state.DataIdsByScope.TryGetValue(DataIdScopes.Action, out var set) && set.Contains(ActionId)}"); }) .Send("hi") .AssertReply(cardActivity, EqualityComparer <IActivity> .Default) .AssertReply($"Tracked: {false}") .Send(actionActivity) .AssertReply($"Tracked: {true}") .StartTestAsync(); }
private static async Task TestAutoDeactivate( bool useChannelWithMessageUpdates, string autoDeactivateInAction, bool autoDeactivateInOptions) { const string ActionId = "action ID"; var botState = CreateUserState(); var accessor = botState.CreateProperty <CardManagerState>(nameof(CardManagerState)); var middleware = new CardManagerMiddleware(new CardManager(botState)); var adapter = new TestAdapter().Use(middleware); var expectedToDeactivate = autoDeactivateInAction == BehaviorSwitch.On || (autoDeactivateInAction != BehaviorSwitch.Off && autoDeactivateInOptions); var expectedInStateBefore = !useChannelWithMessageUpdates; var expectedInQueueBefore = true; var expectedInStateAfter = !(useChannelWithMessageUpdates || expectedToDeactivate); var expectedInQueueAfter = !(useChannelWithMessageUpdates && expectedToDeactivate); var isInState = false; var isInQueue = false; var activitiesProcessed = 0; var cardActivity = MessageFactory.Attachment(new HeroCard(buttons: new List <CardAction> { new CardAction(ActionTypes.PostBack, value: new Dictionary <string, object> { { Behaviors.AutoDeactivate, autoDeactivateInAction }, }.WrapLibraryData()), }).ToAttachment()); var actionActivity = new Activity(value: new JObject { { Behaviors.AutoDeactivate, autoDeactivateInAction }, { DataIdScopes.Action, ActionId }, }.WrapLibraryData()); if (useChannelWithMessageUpdates) { middleware.ChannelsWithMessageUpdates.Add(Channels.Test); middleware.UpdatingOptions.IdOptions.Set(DataIdScopes.Action, ActionId); middleware.UpdatingOptions.AutoDeleteOnAction = autoDeactivateInOptions; } else { middleware.NonUpdatingOptions.IdOptions.Set(DataIdScopes.Action, ActionId); middleware.NonUpdatingOptions.AutoDisableOnAction = autoDeactivateInOptions; middleware.NonUpdatingOptions.AutoClearEnabledOnSend = false; } void AssertCard(bool expected, bool useState) => Assert.AreEqual( expected, useState ? isInState : isInQueue, $"Card activity {(expected ? "wasn't" : "was")} found in {(useState ? "state" : "queue")}"); await new TestFlow(adapter, async(turnContext, cancellationToken) => { if (turnContext.Activity.Value == null) { await turnContext.SendActivityAsync(cardActivity); } var state = await accessor.GetNotNullAsync(turnContext, () => new CardManagerState()); isInState = state.DataIdsByScope.TryGetValue(DataIdScopes.Action, out var set) && set.Contains(ActionId); isInQueue = adapter.ActiveQueue.Contains(cardActivity); activitiesProcessed++; await botState.SaveChangesAsync(turnContext); }) .Send("hi") .Do(() => AssertCard(expectedInStateBefore, true)) .Do(() => AssertCard(expectedInQueueBefore, false)) .Send(actionActivity) .Do(() => AssertCard(expectedInStateAfter, true)) .Do(() => AssertCard(expectedInQueueAfter, false)) .StartTestAsync(); Assert.AreEqual(2, activitiesProcessed); }