* Add TestBot.Shared project * Move duplicated code into TestBot.Shared project * Combine TestBot.Tests and TestBot.NetCore21.Tests Co-authored-by: Joel Mut <joel.mut@southworks.com>
This commit is contained in:
Родитель
b8982b2a2f
Коммит
2e852e299b
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,48 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Bots
|
||||
{
|
||||
public class DialogAndWelcomeBotTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ReturnsWelcomeCardOnConversationUpdate()
|
||||
{
|
||||
// Arrange
|
||||
var mockRootDialog = SimpleMockFactory.CreateMockDialog<Dialog>(null, "mockRootDialog");
|
||||
|
||||
// TODO: do we need state here?
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var sut = new DialogAndWelcomeBot<Dialog>(new ConversationState(memoryStorage), new UserState(memoryStorage), mockRootDialog.Object, null);
|
||||
var conversationUpdateActivity = new Activity
|
||||
{
|
||||
Type = ActivityTypes.ConversationUpdate,
|
||||
MembersAdded = new List<ChannelAccount>
|
||||
{
|
||||
new ChannelAccount { Id = "theUser" },
|
||||
},
|
||||
Recipient = new ChannelAccount { Id = "theBot" },
|
||||
};
|
||||
var testAdapter = new TestAdapter(Channels.Test);
|
||||
|
||||
// Act
|
||||
// Note: it is kind of obscure that we need to use OnTurnAsync to trigger OnMembersAdded so we get the card
|
||||
await testAdapter.ProcessActivityAsync(conversationUpdateActivity, sut.OnTurnAsync, CancellationToken.None);
|
||||
var reply = testAdapter.GetNextReply();
|
||||
|
||||
// Assert
|
||||
var m = (IMessageActivity)reply;
|
||||
Assert.Equal(1, m.Attachments.Count);
|
||||
Assert.Equal("application/vnd.microsoft.card.adaptive", m.Attachments.FirstOrDefault()?.ContentType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Bots
|
||||
{
|
||||
public class DialogBotTests
|
||||
{
|
||||
//[Fact]
|
||||
//public async Task LogsInformationToILogger()
|
||||
//{
|
||||
// // Arrange
|
||||
// var memoryStorage = new MemoryStorage();
|
||||
// var conversationState = new ConversationState(memoryStorage);
|
||||
// var userState = new UserState(memoryStorage);
|
||||
|
||||
// var mockRootDialog = SimpleMockFactory.CreateMockDialog<Dialog>(null, "mockRootDialog");
|
||||
// var mockLogger = new Mock<ILogger<DialogBot<Dialog>>>();
|
||||
// mockLogger.Setup(x =>
|
||||
// x.Log(It.IsAny<LogLevel>(), It.IsAny<EventId>(), It.IsAny<object>(), null, It.IsAny<Func<object, Exception, string>>()));
|
||||
|
||||
// // Run the bot
|
||||
// var sut = new DialogBot<Dialog>(conversationState, userState, mockRootDialog.Object, mockLogger.Object);
|
||||
// var testAdapter = new TestAdapter();
|
||||
// var testFlow = new TestFlow(testAdapter, sut);
|
||||
// await testFlow.Send("Hi").StartTestAsync();
|
||||
|
||||
// // Assert that log was changed with the expected parameters
|
||||
// mockLogger.Verify(
|
||||
// x => x.Log(
|
||||
// LogLevel.Information,
|
||||
// It.IsAny<EventId>(),
|
||||
// It.Is<object>(o => o.ToString() == "Running dialog with Message Activity."),
|
||||
// null,
|
||||
// It.IsAny<Func<object, Exception, string>>()),
|
||||
// Times.Once);
|
||||
//}
|
||||
|
||||
[Fact]
|
||||
public async Task SavesTurnStateUsingMockWithVirtualSaveChangesAsync()
|
||||
{
|
||||
// Note: this test requires that SaveChangesAsync is made virtual in order to be able to create a mock.
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var mockConversationState = new Mock<ConversationState>(memoryStorage)
|
||||
{
|
||||
CallBase = true,
|
||||
};
|
||||
|
||||
var mockUserState = new Mock<UserState>(memoryStorage)
|
||||
{
|
||||
CallBase = true,
|
||||
};
|
||||
|
||||
var mockRootDialog = SimpleMockFactory.CreateMockDialog<Dialog>(null, "mockRootDialog");
|
||||
var mockLogger = new Mock<ILogger<DialogBot<Dialog>>>();
|
||||
|
||||
// Act
|
||||
var sut = new DialogBot<Dialog>(mockConversationState.Object, mockUserState.Object, mockRootDialog.Object, mockLogger.Object);
|
||||
var testAdapter = new TestAdapter();
|
||||
var testFlow = new TestFlow(testAdapter, sut);
|
||||
await testFlow.Send("Hi").StartTestAsync();
|
||||
|
||||
// Assert that SaveChangesAsync was called
|
||||
mockConversationState.Verify(x => x.SaveChangesAsync(It.IsAny<TurnContext>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
mockUserState.Verify(x => x.SaveChangesAsync(It.IsAny<TurnContext>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact(Skip = "TODO: need to figure out how to implement this version of the test")]
|
||||
public async Task SavesTurnStateUsingMemoryStorage()
|
||||
{
|
||||
// TODO: Figure out how to implement this test.
|
||||
// Note: this doesn't require a virtual SaveChangesAsync and it manually inspects storage to ensure the save methods were called.
|
||||
var memoryStorage = new MemoryStorage();
|
||||
var conversationState = new ConversationState(memoryStorage);
|
||||
var userState = new UserState(memoryStorage);
|
||||
|
||||
var mockRootDialog = new Mock<Dialog>("mockRootDialog");
|
||||
mockRootDialog.Setup(x => x.ContinueDialogAsync(It.IsAny<DialogContext>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(new DialogTurnResult(DialogTurnStatus.Empty)));
|
||||
|
||||
var mockLogger = new Mock<ILogger<DialogBot<Dialog>>>();
|
||||
|
||||
// Run the bot
|
||||
var sut = new DialogBot<Dialog>(conversationState, userState, mockRootDialog.Object, mockLogger.Object);
|
||||
var testAdapter = new TestAdapter();
|
||||
var testFlow = new TestFlow(testAdapter, sut);
|
||||
await testFlow.Send("Hi").StartTestAsync();
|
||||
|
||||
// Assert that SaveChangesAsyncWasCalled
|
||||
Assert.True(false, "TODO");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Controllers
|
||||
{
|
||||
public class BotControllerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task PostAsyncCallsProcessAsyncOnAdapter()
|
||||
{
|
||||
// Create MVC infrastructure mocks and objects
|
||||
var request = new Mock<HttpRequest>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
var mockHttpContext = new Mock<HttpContext>();
|
||||
mockHttpContext.Setup(x => x.Request).Returns(request.Object);
|
||||
mockHttpContext.Setup(x => x.Response).Returns(response.Object);
|
||||
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ControllerActionDescriptor());
|
||||
|
||||
// Create BF mocks
|
||||
var mockAdapter = new Mock<IBotFrameworkHttpAdapter>();
|
||||
mockAdapter
|
||||
.Setup(x => x.ProcessAsync(It.IsAny<HttpRequest>(), It.IsAny<HttpResponse>(), It.IsAny<IBot>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
var mockBot = new Mock<IBot>();
|
||||
|
||||
// Create and initialize controller
|
||||
var sut = new BotController(mockAdapter.Object, (s) => mockBot.Object)
|
||||
{
|
||||
ControllerContext = new ControllerContext(actionContext),
|
||||
};
|
||||
|
||||
// Invoke the controller
|
||||
await sut.PostAsync("doesn't matter");
|
||||
|
||||
// Assert
|
||||
mockAdapter.Verify(
|
||||
x => x.ProcessAsync(
|
||||
It.Is<HttpRequest>(o => o == request.Object),
|
||||
It.Is<HttpResponse>(o => o == response.Object),
|
||||
It.Is<IBot>(o => o == mockBot.Object),
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class BookingDialogTests : BotTestBase
|
||||
{
|
||||
private readonly XUnitDialogTestLogger[] _middlewares;
|
||||
|
||||
public BookingDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
_middlewares = new[] { new XUnitDialogTestLogger(output) };
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(BookingDialogTestsDataGenerator.BookingFlows), MemberType = typeof(BookingDialogTestsDataGenerator))]
|
||||
public async Task DialogFlowUseCases(TestDataObject testData)
|
||||
{
|
||||
// Arrange
|
||||
var bookingTestData = testData.GetObject<BookingDialogTestCase>();
|
||||
var mockFlightBookingService = new Mock<IFlightBookingService>();
|
||||
mockFlightBookingService
|
||||
.Setup(x => x.BookFlight(It.IsAny<BookingDetails>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(bookingTestData.FlightBookingServiceResult));
|
||||
|
||||
var mockGetBookingDetailsDialog = SimpleMockFactory.CreateMockDialog<GetBookingDetailsDialog>(bookingTestData.GetBookingDetailsDialogResult).Object;
|
||||
|
||||
var sut = new BookingDialog(mockGetBookingDetailsDialog, mockFlightBookingService.Object);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
|
||||
|
||||
// Act/Assert
|
||||
Output.WriteLine($"Test Case: {bookingTestData.Name}");
|
||||
for (var i = 0; i < bookingTestData.UtterancesAndReplies.GetLength(0); i++)
|
||||
{
|
||||
var utterance = bookingTestData.UtterancesAndReplies[i, 0];
|
||||
|
||||
// Send the activity and receive the first reply or just pull the next
|
||||
// activity from the queue if there's nothing to send
|
||||
var reply = !string.IsNullOrEmpty(utterance)
|
||||
? await testClient.SendActivityAsync<IMessageActivity>(utterance)
|
||||
: testClient.GetNextReply<IMessageActivity>();
|
||||
|
||||
Assert.Equal(bookingTestData.UtterancesAndReplies[i, 1], reply.Text);
|
||||
}
|
||||
|
||||
Assert.Equal(bookingTestData.ExpectedDialogResult.Status, testClient.DialogTurnResult.Status);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class CancelAndHelpDialogTests : BotTestBase
|
||||
{
|
||||
private readonly XUnitDialogTestLogger[] _middlewares;
|
||||
|
||||
public CancelAndHelpDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
_middlewares = new[] { new XUnitDialogTestLogger(output) };
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hi", "Hi there", "cancel")]
|
||||
[InlineData("hi", "Hi there", "quit")]
|
||||
public async Task ShouldBeAbleToCancel(string utterance, string response, string cancelUtterance)
|
||||
{
|
||||
var sut = new TestCancelAndHelpDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
|
||||
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(utterance);
|
||||
Assert.Equal(response, reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
|
||||
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
|
||||
Assert.Equal("Cancelling", reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Complete, testClient.DialogTurnResult.Status);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hi", "Hi there", "help")]
|
||||
[InlineData("hi", "Hi there", "?")]
|
||||
public async Task ShouldBeAbleToGetHelp(string utterance, string response, string cancelUtterance)
|
||||
{
|
||||
var sut = new TestCancelAndHelpDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: _middlewares);
|
||||
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(utterance);
|
||||
Assert.Equal(response, reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
|
||||
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(cancelUtterance);
|
||||
Assert.Equal("Show Help...", reply.Text);
|
||||
Assert.Equal(DialogTurnStatus.Waiting, testClient.DialogTurnResult.Status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A concrete instance of <see cref="CancelAndHelpDialog"/> for testing.
|
||||
/// </summary>
|
||||
private class TestCancelAndHelpDialog : CancelAndHelpDialog
|
||||
{
|
||||
public TestCancelAndHelpDialog()
|
||||
: base(nameof(TestCancelAndHelpDialog))
|
||||
{
|
||||
AddDialog(new TextPrompt(nameof(TextPrompt)));
|
||||
var steps = new WaterfallStep[]
|
||||
{
|
||||
PromptStep,
|
||||
FinalStep,
|
||||
};
|
||||
AddDialog(new WaterfallDialog("testWaterfall", steps));
|
||||
InitialDialogId = "testWaterfall";
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> PromptStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Hi there") }, cancellationToken);
|
||||
}
|
||||
|
||||
private Task<DialogTurnResult> FinalStep(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class DateResolverDialogTests : BotTestBase
|
||||
{
|
||||
public DateResolverDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(DateResolverDialogTestsDataGenerator.DateResolverCases), MemberType = typeof(DateResolverDialogTestsDataGenerator))]
|
||||
public async Task DialogFlowTests(TestDataObject testData)
|
||||
{
|
||||
// Arrange
|
||||
var testCaseData = testData.GetObject<DateResolverDialogTestCase>();
|
||||
var sut = new DateResolverDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, testCaseData.InitialData, new[] { new XUnitDialogTestLogger(Output) });
|
||||
|
||||
// Act/Assert
|
||||
Output.WriteLine($"Test Case: {testCaseData.Name}");
|
||||
Output.WriteLine($"\r\nDialog Input: {testCaseData.InitialData}");
|
||||
for (var i = 0; i < testCaseData.UtterancesAndReplies.GetLength(0); i++)
|
||||
{
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(testCaseData.UtterancesAndReplies[i, 0]);
|
||||
Assert.Equal(testCaseData.UtterancesAndReplies[i, 1], reply?.Text);
|
||||
}
|
||||
|
||||
Output.WriteLine($"\r\nDialog result: {testClient.DialogTurnResult.Result}");
|
||||
Assert.Equal(testCaseData.ExpectedResult, testClient.DialogTurnResult.Result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class GetBookingDetailsDialogTests : BotTestBase
|
||||
{
|
||||
public GetBookingDetailsDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetBookingDetailsDialogTestsDataGenerator.BookingFlows), MemberType = typeof(GetBookingDetailsDialogTestsDataGenerator))]
|
||||
[MemberData(nameof(GetBookingDetailsDialogTestsDataGenerator.CancelFlows), MemberType = typeof(GetBookingDetailsDialogTestsDataGenerator))]
|
||||
public async Task DialogFlowUseCases(TestDataObject testData)
|
||||
{
|
||||
// Arrange
|
||||
var bookingTestData = testData.GetObject<GetBookingDetailsDialogTestCase>();
|
||||
var sut = new GetBookingDetailsDialog();
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, bookingTestData.InitialBookingDetails, new[] { new XUnitDialogTestLogger(Output) });
|
||||
|
||||
// Act/Assert
|
||||
Output.WriteLine($"Test Case: {bookingTestData.Name}");
|
||||
for (var i = 0; i < bookingTestData.UtterancesAndReplies.GetLength(0); i++)
|
||||
{
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>(bookingTestData.UtterancesAndReplies[i, 0]);
|
||||
Assert.Equal(bookingTestData.UtterancesAndReplies[i, 1], reply?.Text);
|
||||
}
|
||||
|
||||
if (testClient.DialogTurnResult.Result != null)
|
||||
{
|
||||
var bookingResults = (BookingDetails)testClient.DialogTurnResult.Result;
|
||||
Assert.Equal(bookingTestData.ExpectedBookingDetails.Origin, bookingResults.Origin);
|
||||
Assert.Equal(bookingTestData.ExpectedBookingDetails.Destination, bookingResults.Destination);
|
||||
Assert.Equal(bookingTestData.ExpectedBookingDetails.TravelDate, bookingResults.TravelDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// This sample uses the current classes and approach for testing bot conversations.
|
||||
/// Note: this is included just as a reference.
|
||||
/// </summary>
|
||||
public class MainDialogTestFlowTests : BotTestBase
|
||||
{
|
||||
[Fact(Skip = "Ignoring this one, this is just a sample on the old way of writing tests")]
|
||||
public async Task WholeEnchilada()
|
||||
{
|
||||
var mockFlightBookingService = new Mock<IFlightBookingService>();
|
||||
mockFlightBookingService.Setup(x => x.BookFlight(It.IsAny<BookingDetails>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
var mockBookingDialog = SimpleMockFactory.CreateMockDialog<BookingDialog>(null, mockFlightBookingService.Object).Object;
|
||||
var mockLogger = new Mock<ILogger<MainDialog>>();
|
||||
var sut = new MainDialog(mockLogger.Object, null, mockBookingDialog);
|
||||
|
||||
var testFlow = BuildTestFlow(sut);
|
||||
|
||||
await testFlow.Send("hi")
|
||||
.AssertReply("What can I help you with today?")
|
||||
.Send("hi")
|
||||
.AssertReply("Where would you like to travel to?")
|
||||
.Send("Bahamas")
|
||||
.AssertReply("Where are you traveling from?")
|
||||
.Send("New York")
|
||||
.AssertReply("When would you like to travel?")
|
||||
.Send("tomorrow at 5 PM")
|
||||
.AssertReply(activity =>
|
||||
{
|
||||
// TODO: I had to add the Yes No for the channelId = test, the emulator displays suggested actions instead.
|
||||
var message = (IMessageActivity)activity;
|
||||
Assert.Equal(
|
||||
"Please confirm, I have you traveling to: Bahamas from: New York on: 2019-04-18T17 (1) Yes or (2) No",
|
||||
message.Text);
|
||||
})
|
||||
.Send("Yes")
|
||||
.AssertReply("I have you booked to Bahamas from New York on tomorrow 5PM")
|
||||
.StartTestAsync();
|
||||
}
|
||||
|
||||
private static TestFlow BuildTestFlow(Dialog targetDialog)
|
||||
{
|
||||
var convoState = new ConversationState(new MemoryStorage());
|
||||
var testAdapter = new TestAdapter()
|
||||
.Use(new AutoSaveStateMiddleware(convoState));
|
||||
var dialogState = convoState.CreateProperty<DialogState>("DialogState");
|
||||
var testFlow = new TestFlow(testAdapter, async (turnContext, cancellationToken) =>
|
||||
{
|
||||
var state = await dialogState.GetAsync(turnContext, () => new DialogState(), cancellationToken);
|
||||
var dialogs = new DialogSet(dialogState);
|
||||
|
||||
dialogs.Add(targetDialog);
|
||||
|
||||
var dc = await dialogs.CreateContextAsync(turnContext, cancellationToken);
|
||||
|
||||
var results = await dc.ContinueDialogAsync(cancellationToken);
|
||||
switch (results.Status)
|
||||
{
|
||||
case DialogTurnStatus.Empty:
|
||||
await dc.BeginDialogAsync(targetDialog.Id, null, cancellationToken);
|
||||
break;
|
||||
case DialogTurnStatus.Complete:
|
||||
{
|
||||
// TODO: Dialog has ended, figure out a way of asserting that this is the case.
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return testFlow;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.CognitiveModels;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs
|
||||
{
|
||||
public class MainDialogTests : BotTestBase
|
||||
{
|
||||
private readonly BookingDialog _mockBookingDialog;
|
||||
private readonly Mock<ILogger<MainDialog>> _mockLogger;
|
||||
|
||||
public MainDialogTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
_mockLogger = new Mock<ILogger<MainDialog>>();
|
||||
|
||||
var mockFlightBookingService = new Mock<IFlightBookingService>();
|
||||
mockFlightBookingService
|
||||
.Setup(x => x.BookFlight(It.IsAny<BookingDetails>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
_mockBookingDialog = SimpleMockFactory.CreateMockDialog<BookingDialog>(null, new Mock<GetBookingDetailsDialog>().Object, mockFlightBookingService.Object).Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DialogConstructor()
|
||||
{
|
||||
var sut = new MainDialog(_mockLogger.Object, null, _mockBookingDialog);
|
||||
|
||||
Assert.Equal("MainDialog", sut.Id);
|
||||
Assert.IsType<TextPrompt>(sut.FindDialog("TextPrompt"));
|
||||
Assert.NotNull(sut.FindDialog("BookingDialog"));
|
||||
Assert.IsType<WaterfallDialog>(sut.FindDialog("WaterfallDialog"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShowsMessageIfLuisNotConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new MainDialog(_mockLogger.Object, null, _mockBookingDialog);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: new[] { new XUnitDialogTestLogger(Output) });
|
||||
|
||||
// Act/Assert
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
|
||||
Assert.Equal("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.", reply.Text);
|
||||
|
||||
reply = testClient.GetNextReply<IMessageActivity>();
|
||||
Assert.Equal("What can I help you with today?", reply.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShowsPromptIfLuisIsConfigured()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new MainDialog(_mockLogger.Object, SimpleMockFactory.CreateMockLuisRecognizer<IRecognizer>(null).Object, _mockBookingDialog);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: new[] { new XUnitDialogTestLogger(Output) });
|
||||
|
||||
// Act/Assert
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
|
||||
Assert.Equal("What can I help you with today?", reply.Text);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("I want to book a flight", "BookFlight", "BookingDialog mock invoked")]
|
||||
[InlineData("What's the weather like?", "GetWeather", "TODO: get weather flow here")]
|
||||
[InlineData("bananas", "None", "Sorry, I didn't get that. Please try asking in a different way (intent was None)")]
|
||||
public async Task TaskSelector(string utterance, string intent, string invokedDialogResponse)
|
||||
{
|
||||
var mockLuisRecognizer = SimpleMockFactory.CreateMockLuisRecognizer<IRecognizer, FlightBooking>(
|
||||
new FlightBooking
|
||||
{
|
||||
Intents = new Dictionary<FlightBooking.Intent, IntentScore>
|
||||
{
|
||||
{ Enum.Parse<FlightBooking.Intent>(intent), new IntentScore() { Score = 1 } },
|
||||
},
|
||||
Entities = new FlightBooking._Entities(),
|
||||
});
|
||||
|
||||
var sut = new MainDialog(_mockLogger.Object, mockLuisRecognizer.Object, _mockBookingDialog);
|
||||
var testClient = new DialogTestClient(Channels.Test, sut, middlewares: new[] { new XUnitDialogTestLogger(Output) });
|
||||
|
||||
var reply = await testClient.SendActivityAsync<IMessageActivity>("hi");
|
||||
Assert.Equal("What can I help you with today?", reply.Text);
|
||||
|
||||
reply = await testClient.SendActivityAsync<IMessageActivity>(utterance);
|
||||
Assert.Equal(invokedDialogResponse, reply.Text);
|
||||
|
||||
reply = testClient.GetNextReply<IMessageActivity>();
|
||||
Assert.Equal("What else can I do for you?", reply.Text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class BookingDialogTestCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name for the test case.
|
||||
/// </summary>
|
||||
/// <value>The test case name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public BookingDetails GetBookingDetailsDialogResult { get; set; }
|
||||
|
||||
public string[,] UtterancesAndReplies { get; set; }
|
||||
|
||||
public DialogTurnResult ExpectedDialogResult { get; set; }
|
||||
|
||||
public bool BookedSuccessfully { get; set; }
|
||||
|
||||
public bool FlightBookingServiceResult { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Ignoring to make code more readable")]
|
||||
public class BookingDialogTestsDataGenerator
|
||||
{
|
||||
public static IEnumerable<object[]> BookingFlows()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.Now.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "yes", "Booking your flight, this shouldn't take long..." },
|
||||
{ null, "I have you booked to Seattle from New York on tomorrow" },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow with 'no' at confirmation",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.Now.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "no", "OK, we can do this later" },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow with 'cancel' at confirmation",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.Now.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
true,
|
||||
new DialogTurnResult(DialogTurnStatus.Complete));
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow with failed call to FlightBookingService",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "GetBookingDetailsDialog mock invoked" },
|
||||
{ null, $"Please confirm, I have you traveling to: Seattle from: New York on: {DateTime.Now.AddDays(1):yyyy-MM-dd} (1) Yes or (2) No" },
|
||||
{ "yes", "Booking your flight, this shouldn't take long..." },
|
||||
{ null, "Sorry, I was unable to secure your reservation, please try another flight" },
|
||||
}, false);
|
||||
}
|
||||
|
||||
private static object[] BuildTestCaseObject(string testCaseName, BookingDetails inputBookingInfo, string[,] utterancesAndReplies, bool flightBookingServiceResult = true, DialogTurnResult expectedDialogTurnResult = null)
|
||||
{
|
||||
var testData = new BookingDialogTestCase
|
||||
{
|
||||
Name = testCaseName,
|
||||
GetBookingDetailsDialogResult = inputBookingInfo,
|
||||
UtterancesAndReplies = utterancesAndReplies,
|
||||
FlightBookingServiceResult = flightBookingServiceResult,
|
||||
ExpectedDialogResult = expectedDialogTurnResult ?? new DialogTurnResult(DialogTurnStatus.Complete),
|
||||
};
|
||||
return new object[] { new TestDataObject(testData) };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class DateResolverDialogTestCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name for the test case.
|
||||
/// </summary>
|
||||
/// <value>The test case name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public string InitialData { get; set; }
|
||||
|
||||
public string ExpectedResult { get; set; }
|
||||
|
||||
public string[,] UtterancesAndReplies { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Ignoring to make code more readable")]
|
||||
|
||||
public class DateResolverDialogTestsDataGenerator
|
||||
{
|
||||
public static IEnumerable<object[]> DateResolverCases()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"tomorrow",
|
||||
null,
|
||||
$"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "tomorrow", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"the day after tomorrow",
|
||||
null,
|
||||
$"{DateTime.Now.AddDays(2):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "the day after tomorrow", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"two days from now",
|
||||
null,
|
||||
$"{DateTime.Now.AddDays(2):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "two days from now", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"valid input given (tomorrow)",
|
||||
$"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
$"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"retry prompt",
|
||||
null,
|
||||
$"{DateTime.Now.AddDays(1):yyyy-MM-dd}",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "bananas", "I'm sorry, to make your booking please enter a full travel date including Day Month and Year." },
|
||||
{ "tomorrow", null },
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"fuzzy time ",
|
||||
null,
|
||||
$"2055-05-05",
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ "may 5th", "I'm sorry, to make your booking please enter a full travel date including Day Month and Year." },
|
||||
{ "may 5th 2055", null },
|
||||
});
|
||||
}
|
||||
|
||||
private static object[] BuildTestCaseObject(string testCaseName, string input, string result, string[,] utterancesAndReplies)
|
||||
{
|
||||
var testData = new DateResolverDialogTestCase
|
||||
{
|
||||
Name = testCaseName,
|
||||
InitialData = input,
|
||||
ExpectedResult = result,
|
||||
UtterancesAndReplies = utterancesAndReplies,
|
||||
};
|
||||
return new object[] { new TestDataObject(testData) };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class GetBookingDetailsDialogTestCase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name for the test case.
|
||||
/// </summary>
|
||||
/// <value>The test case name.</value>
|
||||
public string Name { get; set; }
|
||||
|
||||
public BookingDetails InitialBookingDetails { get; set; }
|
||||
|
||||
public string[,] UtterancesAndReplies { get; set; }
|
||||
|
||||
public BookingDetails ExpectedBookingDetails { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Ignoring to make code more readable")]
|
||||
public class GetBookingDetailsDialogTestsDataGenerator
|
||||
{
|
||||
public static IEnumerable<object[]> BookingFlows()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"Full flow",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "Seattle", "Where are you traveling from?" },
|
||||
{ "New York", "When would you like to travel?" },
|
||||
{ $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Destination given",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Bahamas",
|
||||
Origin = null,
|
||||
TravelDate = null,
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where are you traveling from?" },
|
||||
{ "New York", "When would you like to travel?" },
|
||||
{ $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Bahamas",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Destination and Origin given",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = null,
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "When would you like to travel?" },
|
||||
{ $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "New York",
|
||||
TravelDate = $"{DateTime.UtcNow.AddDays(1):yyyy-MM-dd}",
|
||||
});
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"All booking details given for today",
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "Bahamas",
|
||||
TravelDate = $"{DateTime.UtcNow:yyyy-MM-dd}",
|
||||
},
|
||||
new[,]
|
||||
{
|
||||
{ "hi", null },
|
||||
},
|
||||
new BookingDetails
|
||||
{
|
||||
Destination = "Seattle",
|
||||
Origin = "Bahamas",
|
||||
TravelDate = $"{DateTime.UtcNow:yyyy-MM-dd}",
|
||||
});
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CancelFlows()
|
||||
{
|
||||
yield return BuildTestCaseObject(
|
||||
"Cancel on origin prompt",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
null);
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Cancel on destination prompt",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "Seattle", "Where are you traveling from?" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
null);
|
||||
|
||||
yield return BuildTestCaseObject(
|
||||
"Cancel on date prompt",
|
||||
new BookingDetails(),
|
||||
new[,]
|
||||
{
|
||||
{ "hi", "Where would you like to travel to?" },
|
||||
{ "Seattle", "Where are you traveling from?" },
|
||||
{ "New York", "When would you like to travel?" },
|
||||
{ "cancel", "Cancelling" },
|
||||
},
|
||||
null);
|
||||
}
|
||||
|
||||
private static object[] BuildTestCaseObject(string testCaseName, BookingDetails inputBookingInfo, string[,] utterancesAndReplies, BookingDetails expectedBookingInfo)
|
||||
{
|
||||
var testData = new GetBookingDetailsDialogTestCase
|
||||
{
|
||||
Name = testCaseName,
|
||||
InitialBookingDetails = inputBookingInfo,
|
||||
UtterancesAndReplies = utterancesAndReplies,
|
||||
ExpectedBookingDetails = expectedBookingInfo,
|
||||
};
|
||||
return new object[] { new TestDataObject(testData) };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# Note
|
||||
This folder contains data generators and test case object definitions for Theory tests.
|
|
@ -1,90 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class with helper methods and properties to write bot tests.
|
||||
/// </summary>
|
||||
public abstract class BotTestBase
|
||||
{
|
||||
// A lazy configuration object that gets instantiated once during execution when is needed
|
||||
private static readonly Lazy<IConfiguration> _configurationLazy = new Lazy<IConfiguration>(() =>
|
||||
{
|
||||
LoadLaunchSettingsIntoEnvVariables("Properties//launchSettings.json");
|
||||
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddEnvironmentVariables();
|
||||
|
||||
return config.Build();
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BotTestBase"/> class.
|
||||
/// </summary>
|
||||
protected BotTestBase()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BotTestBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="output">
|
||||
/// An XUnit <see cref="ITestOutputHelper"/> instance.
|
||||
/// See <see href="https://xunit.net/docs/capturing-output.html">Capturing Output</see> in the XUnit documentation for additional details.
|
||||
/// </param>
|
||||
protected BotTestBase(ITestOutputHelper output)
|
||||
{
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public virtual IConfiguration Configuration => _configurationLazy.Value;
|
||||
|
||||
protected ITestOutputHelper Output { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Test runners don't load environment variables defined in launchSettings.json
|
||||
/// so this helper code loads it manually if the file is present.
|
||||
/// This is useful to be able to have your own key files in your local machine without
|
||||
/// having to put them in git.
|
||||
/// If you use launch settings, make sure you set the Copy to Output Directory property to Copy Always.
|
||||
/// </summary>
|
||||
/// <param name="launchSettingsFile">The relative path to the launch settings file (i.e.: "Properties//launchSettings.json").</param>
|
||||
private static void LoadLaunchSettingsIntoEnvVariables(string launchSettingsFile)
|
||||
{
|
||||
if (!File.Exists(launchSettingsFile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var file = File.OpenText(launchSettingsFile))
|
||||
{
|
||||
var reader = new JsonTextReader(file);
|
||||
var fileData = JObject.Load(reader);
|
||||
|
||||
var variables = fileData
|
||||
.GetValue("profiles")
|
||||
.SelectMany(profiles => profiles.Children())
|
||||
.SelectMany(profile => profile.Children<JProperty>())
|
||||
.Where(prop => prop.Name == "environmentVariables")
|
||||
.SelectMany(prop => prop.Value.Children<JProperty>())
|
||||
.ToList();
|
||||
|
||||
foreach (var variable in variables)
|
||||
{
|
||||
Environment.SetEnvironmentVariable(variable.Name, variable.Value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# Note
|
||||
This folder contains a set of helper classes and extensions that could eventually be moved to the testing framework.
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Framework
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains utility methods for creating simple mock objects based on <see href="https://github.com/moq/moq">moq</see>/>.
|
||||
/// </summary>
|
||||
public static class SimpleMockFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a simple mock dialog.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">A <see cref="Dialog"/> derived type.</typeparam>
|
||||
/// <param name="expectedResult">An object containing the results returned by the dialog ind the Dialog in the <see cref="DialogTurnResult"/>.</param>
|
||||
/// <param name="constructorParams">Optional constructor parameters for the dialog.</param>
|
||||
/// <returns>A <see cref="Mock{T}"/> object for the desired dialog type.</returns>
|
||||
public static Mock<T> CreateMockDialog<T>(object expectedResult = null, params object[] constructorParams)
|
||||
where T : Dialog
|
||||
{
|
||||
var mockDialog = new Mock<T>(constructorParams);
|
||||
var mockDialogNameTypeName = typeof(T).Name;
|
||||
mockDialog
|
||||
.Setup(x => x.BeginDialogAsync(It.IsAny<DialogContext>(), It.IsAny<object>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(async (DialogContext dialogContext, object options, CancellationToken cancellationToken) =>
|
||||
{
|
||||
await dialogContext.Context.SendActivityAsync($"{mockDialogNameTypeName} mock invoked", cancellationToken: cancellationToken);
|
||||
|
||||
return await dialogContext.EndDialogAsync(expectedResult, cancellationToken);
|
||||
});
|
||||
|
||||
return mockDialog;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a simple <see cref="IRecognizer"/> mock object that returns the desired <see cref="IRecognizerConvert"/> result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRecognizer">The type of <see cref="IRecognizer"/>to create.</typeparam>
|
||||
/// <typeparam name="TReturns">The type of <see cref="IRecognizerConvert"/> to return.</typeparam>
|
||||
/// <param name="returns">The value to return when <see cref="IRecognizer.RecognizeAsync{T}"/> gets called.</param>
|
||||
/// <returns>A <see cref="Mock{TRecognizer}"/> instance.</returns>
|
||||
public static Mock<TRecognizer> CreateMockLuisRecognizer<TRecognizer, TReturns>(TReturns returns)
|
||||
where TRecognizer : class, IRecognizer
|
||||
where TReturns : IRecognizerConvert, new()
|
||||
{
|
||||
var mockRecognizer = new Mock<TRecognizer>();
|
||||
mockRecognizer
|
||||
.Setup(x => x.RecognizeAsync<TReturns>(It.IsAny<ITurnContext>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() => Task.FromResult(returns));
|
||||
return mockRecognizer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a simple <see cref="IRecognizer"/> mock object that returns the desired <see cref="RecognizerResult"/> result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TRecognizer">The type of <see cref="IRecognizer"/>to create.</typeparam>
|
||||
/// <param name="returns">The value to return when <see cref="IRecognizer.RecognizeAsync"/> gets called.</param>
|
||||
/// <returns>A <see cref="Mock{TRecognizer}"/> instance.</returns>
|
||||
public static Mock<TRecognizer> CreateMockLuisRecognizer<TRecognizer>(RecognizerResult returns)
|
||||
where TRecognizer : class, IRecognizer
|
||||
{
|
||||
var mockRecognizer = new Mock<TRecognizer>();
|
||||
mockRecognizer
|
||||
.Setup(x => x.RecognizeAsync(It.IsAny<ITurnContext>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(() => Task.FromResult(returns));
|
||||
return mockRecognizer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AssemblyName>Microsoft.Bot.Builder.TestBot.NetCore21.Tests</AssemblyName>
|
||||
<RootNamespace>Microsoft.BotBuilderSamples.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="appsettings.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Testing\Microsoft.Bot.Builder.Testing.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.TestBot.NetCore21\Microsoft.Bot.Builder.TestBot.NetCore21.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Properties\launchSettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="xunit.runner.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"cognitiveModels": {
|
||||
"flightBooking": {
|
||||
"luisAppId": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpointKey": "Set the value here or in launchSettings.json for local dev",
|
||||
"luisEndpoint": "Set the value here or in launchSettings.json for local dev"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"settings": {
|
||||
"namingRules": {
|
||||
"allowCommonHungarianPrefixes": true,
|
||||
"allowedHungarianPrefixes": [
|
||||
"lu"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
|
||||
"parallelizeAssembly": true
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class BookingDetails
|
||||
{
|
||||
public string Destination { get; set; }
|
||||
|
||||
public string Origin { get; set; }
|
||||
|
||||
public string TravelDate { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class DialogAndWelcomeBot<T> : DialogBot<T>
|
||||
where T : Dialog
|
||||
{
|
||||
public DialogAndWelcomeBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
|
||||
: base(conversationState, userState, dialog, logger)
|
||||
{
|
||||
}
|
||||
|
||||
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var member in membersAdded)
|
||||
{
|
||||
// Greet anyone that was not the target (recipient) of this message.
|
||||
// To learn more about Adaptive Cards, see https://aka.ms/msbot-adaptivecards for more details.
|
||||
if (member.Id != turnContext.Activity.Recipient.Id)
|
||||
{
|
||||
var welcomeCard = CreateAdaptiveCardAttachment();
|
||||
var response = CreateResponse(turnContext.Activity, welcomeCard);
|
||||
await turnContext.SendActivityAsync(response, cancellationToken);
|
||||
await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load attachment from embedded resource.
|
||||
private Attachment CreateAdaptiveCardAttachment()
|
||||
{
|
||||
var rootNamespace = typeof(Startup).Namespace;
|
||||
var cardResourcePath = $"{rootNamespace}.Cards.welcomeCard.json";
|
||||
|
||||
using (var stream = GetType().Assembly.GetManifestResourceStream(cardResourcePath))
|
||||
{
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var adaptiveCard = reader.ReadToEnd();
|
||||
return new Attachment()
|
||||
{
|
||||
ContentType = "application/vnd.microsoft.card.adaptive",
|
||||
Content = JsonConvert.DeserializeObject(adaptiveCard),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create an attachment message response.
|
||||
private Activity CreateResponse(IActivity activity, Attachment attachment)
|
||||
{
|
||||
var response = ((Activity)activity).CreateReply();
|
||||
response.Attachments = new List<Attachment>() { attachment };
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
// This IBot implementation can run any type of Dialog. The use of type parameterization is to allows multiple different bots
|
||||
// to be run at different endpoints within the same project. This can be achieved by defining distinct Controller types
|
||||
// each with dependency on distinct IBot types, this way ASP Dependency Injection can glue everything together without ambiguity.
|
||||
// The ConversationState is used by the Dialog system. The UserState isn't, however, it might have been used in a Dialog implementation,
|
||||
// and the requirement is that all BotState objects are saved at the end of a turn.
|
||||
public class DialogBot<T> : ActivityHandler
|
||||
where T : Dialog
|
||||
{
|
||||
public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
|
||||
{
|
||||
ConversationState = conversationState;
|
||||
UserState = userState;
|
||||
Dialog = dialog;
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
protected Dialog Dialog { get; }
|
||||
|
||||
protected BotState ConversationState { get; }
|
||||
|
||||
protected BotState UserState { get; }
|
||||
|
||||
protected ILogger Logger { get; }
|
||||
|
||||
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
await base.OnTurnAsync(turnContext, cancellationToken);
|
||||
|
||||
// Save any state changes that might have occurred during the turn.
|
||||
await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
|
||||
await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
Logger.LogInformation("Running dialog with Message Activity.");
|
||||
|
||||
// Run the Dialog with the new message Activity.
|
||||
await Dialog.Run(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
// <auto-generated>
|
||||
// Code generated by LUISGen C:\Projects\Repos\botbuilder-dotnet\tests\Microsoft.Bot.Builder.TestBot\CognitiveModels\FlightBooking.json -cs Microsoft.BotBuilderSamples.CognitiveModels.FlightBooking -o C:\Projects\Repos\botbuilder-dotnet\tests\Microsoft.Bot.Builder.TestBot\CognitiveModels
|
||||
// Tool github: https://github.com/microsoft/botbuilder-tools
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// </auto-generated>
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.CognitiveModels
|
||||
{
|
||||
public class FlightBooking: IRecognizerConvert
|
||||
{
|
||||
public string Text;
|
||||
public string AlteredText;
|
||||
public enum Intent {
|
||||
BookFlight,
|
||||
Cancel,
|
||||
GetWeather,
|
||||
None
|
||||
};
|
||||
public Dictionary<Intent, IntentScore> Intents;
|
||||
|
||||
public class _Entities
|
||||
{
|
||||
|
||||
// Built-in entities
|
||||
public DateTimeSpec[] datetime;
|
||||
|
||||
// Lists
|
||||
public string[][] Airport;
|
||||
|
||||
// Composites
|
||||
public class _InstanceFrom
|
||||
{
|
||||
public InstanceData[] Airport;
|
||||
}
|
||||
public class FromClass
|
||||
{
|
||||
public string[][] Airport;
|
||||
[JsonProperty("$instance")]
|
||||
public _InstanceFrom _instance;
|
||||
}
|
||||
public FromClass[] From;
|
||||
|
||||
public class _InstanceTo
|
||||
{
|
||||
public InstanceData[] Airport;
|
||||
}
|
||||
public class ToClass
|
||||
{
|
||||
public string[][] Airport;
|
||||
[JsonProperty("$instance")]
|
||||
public _InstanceTo _instance;
|
||||
}
|
||||
public ToClass[] To;
|
||||
|
||||
// Instance
|
||||
public class _Instance
|
||||
{
|
||||
public InstanceData[] datetime;
|
||||
public InstanceData[] Airport;
|
||||
public InstanceData[] From;
|
||||
public InstanceData[] To;
|
||||
}
|
||||
[JsonProperty("$instance")]
|
||||
public _Instance _instance;
|
||||
}
|
||||
public _Entities Entities;
|
||||
|
||||
[JsonExtensionData(ReadData = true, WriteData = true)]
|
||||
public IDictionary<string, object> Properties {get; set; }
|
||||
|
||||
public void Convert(dynamic result)
|
||||
{
|
||||
var app = JsonConvert.DeserializeObject<FlightBooking>(JsonConvert.SerializeObject(result));
|
||||
Text = app.Text;
|
||||
AlteredText = app.AlteredText;
|
||||
Intents = app.Intents;
|
||||
Entities = app.Entities;
|
||||
Properties = app.Properties;
|
||||
}
|
||||
|
||||
public (Intent intent, double score) TopIntent()
|
||||
{
|
||||
Intent maxIntent = Intent.None;
|
||||
var max = 0.0;
|
||||
foreach (var entry in Intents)
|
||||
{
|
||||
if (entry.Value.Score > max)
|
||||
{
|
||||
maxIntent = entry.Key;
|
||||
max = entry.Value.Score.Value;
|
||||
}
|
||||
}
|
||||
return (maxIntent, max);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Debugging
|
||||
{
|
||||
public class DebugAdapter : BotFrameworkHttpAdapter
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class BookingDialog : CancelAndHelpDialog
|
||||
{
|
||||
private readonly IFlightBookingService _flightBookingService;
|
||||
|
||||
public BookingDialog(GetBookingDetailsDialog getBookingDetailsDialog, IFlightBookingService flightBookingService)
|
||||
: base(nameof(BookingDialog))
|
||||
{
|
||||
_flightBookingService = flightBookingService;
|
||||
AddDialog(getBookingDetailsDialog);
|
||||
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
|
||||
var steps = new WaterfallStep[]
|
||||
{
|
||||
GetBookingDetailsActionAsync,
|
||||
ConfirmActionAsync,
|
||||
FinalActionAsync,
|
||||
};
|
||||
|
||||
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), steps));
|
||||
|
||||
// The initial child Dialog to run.
|
||||
InitialDialogId = nameof(WaterfallDialog);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> GetBookingDetailsActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var bookingDetails = (BookingDetails)stepContext.Options ?? new BookingDetails();
|
||||
|
||||
return await stepContext.BeginDialogAsync(nameof(GetBookingDetailsDialog), bookingDetails, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> ConfirmActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var bookingDetails = (BookingDetails)stepContext.Result;
|
||||
|
||||
// Store the booking details in the waterfall state so we can use it once the user confirms
|
||||
stepContext.Values["BookingInfo"] = bookingDetails;
|
||||
|
||||
var msg = $"Please confirm, I have you traveling to: {bookingDetails.Destination} from: {bookingDetails.Origin} on: {bookingDetails.TravelDate}";
|
||||
return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text(msg) }, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> FinalActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
string msg;
|
||||
if ((bool)stepContext.Result)
|
||||
{
|
||||
// Pull the booking details from the waterfall state.
|
||||
var bookingDetails = (BookingDetails)stepContext.Values["BookingInfo"];
|
||||
|
||||
// Now we have all the booking information to call the booking service.
|
||||
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Booking your flight, this shouldn't take long..."), cancellationToken);
|
||||
|
||||
var flightBooked = await _flightBookingService.BookFlight(bookingDetails, cancellationToken);
|
||||
if (flightBooked)
|
||||
{
|
||||
// If the call to the booking service was successful tell the user.
|
||||
var timeProperty = new TimexProperty(bookingDetails.TravelDate);
|
||||
var travelDateMsg = timeProperty.ToNaturalLanguage(DateTime.Now);
|
||||
msg = $"I have you booked to {bookingDetails.Destination} from {bookingDetails.Origin} on {travelDateMsg}";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Sorry, I was unable to secure your reservation, please try another flight";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "OK, we can do this later";
|
||||
}
|
||||
|
||||
await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);
|
||||
return await stepContext.EndDialogAsync(null, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public abstract class CancelAndHelpDialog : ComponentDialog
|
||||
{
|
||||
protected CancelAndHelpDialog(string id)
|
||||
: base(id)
|
||||
{
|
||||
}
|
||||
|
||||
protected override async Task<DialogTurnResult> OnBeginDialogAsync(DialogContext innerDc, object options, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await InterruptAsync(innerDc, cancellationToken);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return await base.OnBeginDialogAsync(innerDc, options, cancellationToken);
|
||||
}
|
||||
|
||||
protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await InterruptAsync(innerDc, cancellationToken);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return await base.OnContinueDialogAsync(innerDc, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
|
||||
{
|
||||
if (innerDc.Context.Activity.Type == ActivityTypes.Message)
|
||||
{
|
||||
var text = innerDc.Context.Activity.Text.ToLowerInvariant();
|
||||
|
||||
switch (text)
|
||||
{
|
||||
case "help":
|
||||
case "?":
|
||||
await innerDc.Context.SendActivityAsync("Show Help...", cancellationToken: cancellationToken);
|
||||
return new DialogTurnResult(DialogTurnStatus.Waiting);
|
||||
|
||||
case "cancel":
|
||||
case "quit":
|
||||
await innerDc.Context.SendActivityAsync("Cancelling", cancellationToken: cancellationToken);
|
||||
return await innerDc.CancelAllDialogsAsync(cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class DateResolverDialog : CancelAndHelpDialog
|
||||
{
|
||||
public DateResolverDialog(string id = null)
|
||||
: base(id ?? nameof(DateResolverDialog))
|
||||
{
|
||||
AddDialog(new DateTimePrompt(nameof(DateTimePrompt), DateTimePromptValidator));
|
||||
var steps = new WaterfallStep[]
|
||||
{
|
||||
InitialActionAsync,
|
||||
FinalActionAsync,
|
||||
};
|
||||
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), steps));
|
||||
|
||||
// The initial child Dialog to run.
|
||||
InitialDialogId = nameof(WaterfallDialog);
|
||||
}
|
||||
|
||||
private static Task<bool> DateTimePromptValidator(PromptValidatorContext<IList<DateTimeResolution>> promptContext, CancellationToken cancellationToken)
|
||||
{
|
||||
if (promptContext.Recognized.Succeeded)
|
||||
{
|
||||
// This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
|
||||
// TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
|
||||
var timex = promptContext.Recognized.Value[0].Timex.Split('T')[0];
|
||||
|
||||
// If this is a definite Date including year, month and day we are good otherwise reprompt.
|
||||
// A better solution might be to let the user know what part is actually missing.
|
||||
var isDefinite = new TimexProperty(timex).Types.Contains(Constants.TimexTypes.Definite);
|
||||
|
||||
return Task.FromResult(isDefinite);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> InitialActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var timex = (string)stepContext.Options;
|
||||
|
||||
var promptMsg = "When would you like to travel?";
|
||||
var repromptMsg = "I'm sorry, to make your booking please enter a full travel date including Day Month and Year.";
|
||||
|
||||
if (timex == null)
|
||||
{
|
||||
// We were not given any date at all so prompt the user.
|
||||
return await stepContext.PromptAsync(
|
||||
nameof(DateTimePrompt),
|
||||
new PromptOptions
|
||||
{
|
||||
Prompt = MessageFactory.Text(promptMsg),
|
||||
RetryPrompt = MessageFactory.Text(repromptMsg),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
// We have a Date we just need to check it is unambiguous.
|
||||
var timexProperty = new TimexProperty(timex);
|
||||
if (!timexProperty.Types.Contains(Constants.TimexTypes.Definite))
|
||||
{
|
||||
// This is essentially a "reprompt" of the data we were given up front.
|
||||
return await stepContext.PromptAsync(
|
||||
nameof(DateTimePrompt),
|
||||
new PromptOptions
|
||||
{
|
||||
Prompt = MessageFactory.Text(repromptMsg),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
return await stepContext.NextAsync(new List<DateTimeResolution> { new DateTimeResolution { Timex = timex } }, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> FinalActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var timex = ((List<DateTimeResolution>)stepContext.Result)[0].Timex;
|
||||
return await stepContext.EndDialogAsync(timex, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class GetBookingDetailsDialog : CancelAndHelpDialog
|
||||
{
|
||||
public GetBookingDetailsDialog()
|
||||
: base(nameof(GetBookingDetailsDialog))
|
||||
{
|
||||
AddDialog(new TextPrompt(nameof(TextPrompt)));
|
||||
AddDialog(new DateResolverDialog());
|
||||
var steps = new WaterfallStep[]
|
||||
{
|
||||
DestinationActionAsync,
|
||||
OriginActionAsync,
|
||||
TravelDateActionAsync,
|
||||
FinalActionAsync,
|
||||
};
|
||||
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), steps));
|
||||
|
||||
// The initial child Dialog to run.
|
||||
InitialDialogId = nameof(WaterfallDialog);
|
||||
}
|
||||
|
||||
private static bool IsAmbiguous(string timex)
|
||||
{
|
||||
var timexProperty = new TimexProperty(timex);
|
||||
return !timexProperty.Types.Contains(Constants.TimexTypes.Definite);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> DestinationActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var bookingDetails = (BookingDetails)stepContext.Options ?? new BookingDetails();
|
||||
|
||||
if (bookingDetails.Destination == null)
|
||||
{
|
||||
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Where would you like to travel to?") }, cancellationToken);
|
||||
}
|
||||
|
||||
return await stepContext.NextAsync(bookingDetails.Destination, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> OriginActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var bookingDetails = (BookingDetails)stepContext.Options;
|
||||
bookingDetails.Destination = (string)stepContext.Result;
|
||||
|
||||
if (bookingDetails.Origin == null)
|
||||
{
|
||||
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Where are you traveling from?") }, cancellationToken);
|
||||
}
|
||||
|
||||
return await stepContext.NextAsync(bookingDetails.Origin, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> TravelDateActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var bookingDetails = (BookingDetails)stepContext.Options;
|
||||
bookingDetails.Origin = (string)stepContext.Result;
|
||||
|
||||
if (bookingDetails.TravelDate == null || IsAmbiguous(bookingDetails.TravelDate))
|
||||
{
|
||||
// Run the DateResolverDialog giving it whatever details we have from the LUIS call, it will fill out the remainder.
|
||||
return await stepContext.BeginDialogAsync(nameof(DateResolverDialog), bookingDetails.TravelDate, cancellationToken);
|
||||
}
|
||||
|
||||
return await stepContext.NextAsync(bookingDetails.TravelDate, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> FinalActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var bookingDetails = (BookingDetails)stepContext.Options;
|
||||
bookingDetails.TravelDate = (string)stepContext.Result;
|
||||
|
||||
// We are done collection booking details, return the data to the caller.
|
||||
return await stepContext.EndDialogAsync(bookingDetails, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Choices;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public class UserProfileDialog : ComponentDialog
|
||||
{
|
||||
private IStatePropertyAccessor<UserProfile> _userProfileAccessor;
|
||||
|
||||
public UserProfileDialog(UserState userState)
|
||||
: base("root")
|
||||
{
|
||||
_userProfileAccessor = userState.CreateProperty<UserProfile>("UserProfile");
|
||||
|
||||
// This array defines how the Waterfall will execute.
|
||||
var waterfallActions = new WaterfallStep[]
|
||||
{
|
||||
TransportActionAsync,
|
||||
NameActionAsync,
|
||||
NameConfirmActionAsync,
|
||||
AgeActionAsync,
|
||||
ConfirmActionAsync,
|
||||
SummaryActionAsync,
|
||||
};
|
||||
|
||||
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
|
||||
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallActions));
|
||||
AddDialog(new TextPrompt(nameof(TextPrompt)));
|
||||
AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
|
||||
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
|
||||
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
|
||||
|
||||
// The initial child Dialog to run.
|
||||
InitialDialogId = nameof(WaterfallDialog);
|
||||
}
|
||||
|
||||
private static async Task<DialogTurnResult> TransportActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
// WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
|
||||
// Running a prompt here means the next WaterfallStep will be run when the users response is received.
|
||||
return await stepContext.PromptAsync(
|
||||
nameof(ChoicePrompt),
|
||||
new PromptOptions
|
||||
{
|
||||
Prompt = MessageFactory.Text("Please enter your mode of transport."),
|
||||
Choices = ChoiceFactory.ToChoices(new List<string> { "Car", "Bus", "Bicycle" }),
|
||||
}, cancellationToken);
|
||||
}
|
||||
|
||||
private static async Task<DialogTurnResult> NameActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
stepContext.Values["transport"] = ((FoundChoice)stepContext.Result).Value;
|
||||
|
||||
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") }, cancellationToken);
|
||||
}
|
||||
|
||||
private static Task<bool> AgePromptValidatorAsync(PromptValidatorContext<int> promptContext, CancellationToken cancellationToken)
|
||||
{
|
||||
// This condition is our validation rule. You can also change the value at this point.
|
||||
return Task.FromResult(promptContext.Recognized.Value >= 0 && promptContext.Recognized.Value < 150);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> NameConfirmActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
stepContext.Values["name"] = (string)stepContext.Result;
|
||||
|
||||
// We can send messages to the user at any point in the WaterfallStep.
|
||||
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Thanks {stepContext.Result}."), cancellationToken);
|
||||
|
||||
// WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
|
||||
return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Would you like to give your age?") }, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> AgeActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
if ((bool)stepContext.Result)
|
||||
{
|
||||
// User said "yes" so we will be prompting for the age.
|
||||
// WaterfallStep always finishes with the end of the Waterfall or with another dialog, here it is a Prompt Dialog.
|
||||
var promptOptions = new PromptOptions
|
||||
{
|
||||
Prompt = MessageFactory.Text("Please enter your age."),
|
||||
RetryPrompt = MessageFactory.Text("The value entered must be greater than 0 and less than 150."),
|
||||
};
|
||||
|
||||
return await stepContext.PromptAsync(nameof(NumberPrompt<int>), promptOptions, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
// User said "no" so we will skip the next step. Give -1 as the age.
|
||||
return await stepContext.NextAsync(-1, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> ConfirmActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
stepContext.Values["age"] = (int)stepContext.Result;
|
||||
|
||||
// We can send messages to the user at any point in the WaterfallStep.
|
||||
// var msg = userProfile.Age == -1 ? "No age given." : $"I have your age as {userProfile.Age}.";
|
||||
var msg = (int)stepContext.Values["age"] == -1 ? "No age given." : $"I have your age as {stepContext.Values["age"]}.";
|
||||
|
||||
// We can send messages to the user at any point in the WaterfallStep.
|
||||
await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);
|
||||
|
||||
// WaterfallStep always finishes with the end of the Waterfall or with another dialog, here it is a Prompt Dialog.
|
||||
return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Is this ok?") }, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> SummaryActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
if ((bool)stepContext.Result)
|
||||
{
|
||||
// Get the current profile object from user state.
|
||||
var userProfile = await _userProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile(), cancellationToken);
|
||||
|
||||
userProfile.Transport = (string)stepContext.Values["transport"];
|
||||
userProfile.Name = (string)stepContext.Values["name"];
|
||||
userProfile.Age = (int)stepContext.Values["age"];
|
||||
|
||||
var msg = $"I have your mode of transport as {userProfile.Transport} and your name as {userProfile.Name}.";
|
||||
if (userProfile.Age != -1)
|
||||
{
|
||||
msg += $" And age as {userProfile.Age}.";
|
||||
}
|
||||
|
||||
await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Thanks. Your profile will not be kept."), cancellationToken);
|
||||
}
|
||||
|
||||
// WaterfallStep always finishes with the end of the Waterfall or with another dialog, here it is the end.
|
||||
return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Rest.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot
|
||||
{
|
||||
internal static class HttpHelper
|
||||
{
|
||||
public static readonly JsonSerializer BotMessageSerializer = JsonSerializer.Create(new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
Formatting = Formatting.Indented,
|
||||
DateFormatHandling = DateFormatHandling.IsoDateFormat,
|
||||
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
|
||||
ContractResolver = new ReadOnlyJsonContractResolver(),
|
||||
Converters = new List<JsonConverter> { new Iso8601TimeSpanConverter() },
|
||||
});
|
||||
|
||||
public static Activity ReadRequest(HttpRequest request)
|
||||
{
|
||||
if (request == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
}
|
||||
|
||||
var activity = default(Activity);
|
||||
|
||||
using (var bodyReader = new JsonTextReader(new StreamReader(request.Body, Encoding.UTF8)))
|
||||
{
|
||||
activity = BotMessageSerializer.Deserialize<Activity>(bodyReader);
|
||||
}
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
public static void WriteResponse(HttpResponse response, InvokeResponse invokeResponse)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(response));
|
||||
}
|
||||
|
||||
if (invokeResponse == null)
|
||||
{
|
||||
response.StatusCode = (int)HttpStatusCode.OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.ContentType = "application/json";
|
||||
response.StatusCode = invokeResponse.Status;
|
||||
|
||||
using (var writer = new StreamWriter(response.Body))
|
||||
{
|
||||
using (var jsonWriter = new JsonTextWriter(writer))
|
||||
{
|
||||
BotMessageSerializer.Serialize(jsonWriter, invokeResponse.Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,23 +6,15 @@
|
|||
<RootNamespace>Microsoft.BotBuilderSamples</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Cards\welcomeCard.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Cards\welcomeCard.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.DataTypes.TimexExpression" Version="1.2.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.AI.LUIS\Microsoft.Bot.Builder.AI.Luis.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs\Microsoft.Bot.Builder.Dialogs.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.TestBot.Shared\Microsoft.Bot.Builder.TestBot.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Services
|
||||
{
|
||||
public class FlightBookingService : IFlightBookingService
|
||||
{
|
||||
public Task<bool> BookFlight(BookingDetails booking, CancellationToken cancellationToken = default(CancellationToken)) => Task.FromResult(true);
|
||||
}
|
||||
}
|
|
@ -8,9 +8,10 @@ using Microsoft.AspNetCore.Mvc;
|
|||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Builder.TestBot.Bots;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Bots;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Services;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared
|
||||
{
|
||||
public class BookingDetails
|
||||
{
|
|
@ -5,13 +5,12 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Bots
|
||||
{
|
||||
public class DialogAndWelcomeBot<T> : DialogBot<T>
|
||||
where T : Dialog
|
||||
|
@ -40,7 +39,7 @@ namespace Microsoft.BotBuilderSamples
|
|||
// Load attachment from embedded resource.
|
||||
private Attachment CreateAdaptiveCardAttachment()
|
||||
{
|
||||
var rootNamespace = typeof(Startup).Namespace;
|
||||
var rootNamespace = typeof(UserProfile).Namespace;
|
||||
var cardResourcePath = $"{rootNamespace}.Cards.welcomeCard.json";
|
||||
|
||||
using (var stream = GetType().Assembly.GetManifestResourceStream(cardResourcePath))
|
|
@ -3,12 +3,11 @@
|
|||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Bots
|
||||
{
|
||||
// This IBot implementation can run any type of Dialog. The use of type parameterization is to allows multiple different bots
|
||||
// to be run at different endpoints within the same project. This can be achieved by defining distinct Controller types
|
|
@ -5,7 +5,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Bots
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Bots
|
||||
{
|
||||
public class MyBot : ActivityHandler
|
||||
{
|
|
@ -6,10 +6,9 @@
|
|||
// </auto-generated>
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.CognitiveModels
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.CognitiveModels
|
||||
{
|
||||
public class FlightBooking: IRecognizerConvert
|
||||
{
|
|
@ -4,10 +4,9 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Controllers
|
||||
{
|
||||
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot
|
||||
// implementation at runtime. Multiple different IBot implementations running at different endpoints can be
|
|
@ -1,6 +1,6 @@
|
|||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Debugging
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Debugging
|
||||
{
|
||||
public class DebugAdapter : BotFrameworkHttpAdapter
|
||||
{
|
|
@ -5,7 +5,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Debugging
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Debugging
|
||||
{
|
||||
public class DebugBot : ActivityHandler
|
||||
{
|
|
@ -1,8 +1,7 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder.TestBot.Debugging;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Controllers
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Debugging
|
||||
{
|
||||
[Route("api/debug")]
|
||||
[ApiController]
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared
|
||||
{
|
||||
public static class DialogExtensions
|
||||
{
|
|
@ -4,12 +4,11 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Services;
|
||||
using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Dialogs
|
||||
{
|
||||
public class BookingDialog : CancelAndHelpDialog
|
||||
{
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Dialogs
|
||||
{
|
||||
public abstract class CancelAndHelpDialog : ComponentDialog
|
||||
{
|
|
@ -8,7 +8,7 @@ using Microsoft.Bot.Builder;
|
|||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Dialogs
|
||||
{
|
||||
public class DateResolverDialog : CancelAndHelpDialog
|
||||
{
|
|
@ -7,7 +7,7 @@ using Microsoft.Bot.Builder;
|
|||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Recognizers.Text.DataTypes.TimexExpression;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Dialogs
|
||||
{
|
||||
public class GetBookingDetailsDialog : CancelAndHelpDialog
|
||||
{
|
|
@ -4,13 +4,12 @@
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.CognitiveModels;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.CognitiveModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Dialogs
|
||||
{
|
||||
// A root dialog responsible of understanding user intents and dispatching them sub tasks.
|
||||
public class MainDialog : ComponentDialog
|
|
@ -4,11 +4,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.Dialogs.Choices;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Dialogs
|
||||
{
|
||||
public class UserProfileDialog : ComponentDialog
|
||||
{
|
|
@ -11,7 +11,7 @@ using Microsoft.Bot.Schema;
|
|||
using Microsoft.Rest.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared
|
||||
{
|
||||
internal static class HttpHelper
|
||||
{
|
|
@ -0,0 +1,25 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Cards\welcomeCard.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Cards\welcomeCard.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.DataTypes.TimexExpression" Version="1.2.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.AI.LUIS\Microsoft.Bot.Builder.AI.Luis.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs\Microsoft.Bot.Builder.Dialogs.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -4,7 +4,7 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Services
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Services
|
||||
{
|
||||
public class FlightBookingService : IFlightBookingService
|
||||
{
|
|
@ -4,7 +4,7 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Services
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared.Services
|
||||
{
|
||||
public interface IFlightBookingService
|
||||
{
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
namespace Microsoft.Bot.Builder.TestBot.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// This is our application state. Just a regular serializable .NET class.
|
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Bots;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Bots;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Mvc.Controllers;
|
|||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Controllers;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Services;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Dialogs.TestData;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Moq;
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
|
|
|
@ -6,8 +6,10 @@ using System.Threading.Tasks;
|
|||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Services;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
|
|
@ -7,12 +7,14 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.CognitiveModels;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Services;
|
||||
using Microsoft.Bot.Builder.Testing;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
using Microsoft.Bot.Connector;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.CognitiveModels;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.BotBuilderSamples.Tests.Framework;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
{
|
||||
public class GetBookingDetailsDialogTestCase
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared;
|
||||
using Microsoft.Bot.Builder.Testing.XUnit;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Tests.Dialogs.TestData
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework Condition="'$(BuildTarget)' == 'netcoreapp21'">netcoreapp2.1</TargetFramework>
|
||||
<TargetFramework Condition="'$(BuildTarget)' == 'netcoreapp31'">netcoreapp3.1</TargetFramework>
|
||||
<TargetFrameworks Condition="'$(BuildTarget)' == ''">netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AssemblyName>Microsoft.Bot.Builder.TestBot.Tests</AssemblyName>
|
||||
<RootNamespace>Microsoft.BotBuilderSamples.Tests</RootNamespace>
|
||||
<GenerateDocumentationFile>false</GenerateDocumentationFile>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -17,8 +21,15 @@
|
|||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
|
||||
|
@ -29,7 +40,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Testing\Microsoft.Bot.Builder.Testing.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.TestBot\Microsoft.Bot.Builder.TestBot.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.TestBot.Shared\Microsoft.Bot.Builder.TestBot.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Bots
|
||||
{
|
||||
public class MyBot : ActivityHandler
|
||||
{
|
||||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.0",
|
||||
"body": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
|
||||
"size": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"spacing": "medium",
|
||||
"size": "default",
|
||||
"weight": "bolder",
|
||||
"text": "Welcome to Bot Framework!",
|
||||
"wrap": true,
|
||||
"maxLines": 0
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"size": "default",
|
||||
"isSubtle": "yes",
|
||||
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
|
||||
"wrap": true,
|
||||
"maxLines": 0
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Get an overview",
|
||||
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
|
||||
},
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Ask a question",
|
||||
"url": "https://stackoverflow.com/questions/tagged/botframework"
|
||||
},
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Learn how to deploy",
|
||||
"url": "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,334 +0,0 @@
|
|||
{
|
||||
"luis_schema_version": "3.2.0",
|
||||
"versionId": "0.1",
|
||||
"name": "FlightBooking",
|
||||
"desc": "Luis Model for CoreBot",
|
||||
"culture": "en-us",
|
||||
"tokenizerVersion": "1.0.0",
|
||||
"intents": [
|
||||
{
|
||||
"name": "BookFlight"
|
||||
},
|
||||
{
|
||||
"name": "Cancel"
|
||||
},
|
||||
{
|
||||
"name": "GetWeather"
|
||||
},
|
||||
{
|
||||
"name": "None"
|
||||
}
|
||||
],
|
||||
"entities": [],
|
||||
"composites": [
|
||||
{
|
||||
"name": "From",
|
||||
"children": [
|
||||
"Airport"
|
||||
],
|
||||
"roles": []
|
||||
},
|
||||
{
|
||||
"name": "To",
|
||||
"children": [
|
||||
"Airport"
|
||||
],
|
||||
"roles": []
|
||||
}
|
||||
],
|
||||
"closedLists": [
|
||||
{
|
||||
"name": "Airport",
|
||||
"subLists": [
|
||||
{
|
||||
"canonicalForm": "Paris",
|
||||
"list": [
|
||||
"paris"
|
||||
]
|
||||
},
|
||||
{
|
||||
"canonicalForm": "London",
|
||||
"list": [
|
||||
"london"
|
||||
]
|
||||
},
|
||||
{
|
||||
"canonicalForm": "Berlin",
|
||||
"list": [
|
||||
"berlin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"canonicalForm": "New York",
|
||||
"list": [
|
||||
"new york"
|
||||
]
|
||||
},
|
||||
{
|
||||
"canonicalForm": "Seattle",
|
||||
"list": [
|
||||
"seattle"
|
||||
]
|
||||
}
|
||||
],
|
||||
"roles": []
|
||||
}
|
||||
],
|
||||
"patternAnyEntities": [],
|
||||
"regex_entities": [],
|
||||
"prebuiltEntities": [
|
||||
{
|
||||
"name": "datetimeV2",
|
||||
"roles": []
|
||||
}
|
||||
],
|
||||
"model_features": [],
|
||||
"regex_features": [],
|
||||
"patterns": [],
|
||||
"utterances": [
|
||||
{
|
||||
"text": "book a flight",
|
||||
"intent": "BookFlight",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "book a flight from new york",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 19,
|
||||
"endPos": 26
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "book a flight from seattle",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 19,
|
||||
"endPos": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "book a hotel in new york",
|
||||
"intent": "None",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "book a restaurant",
|
||||
"intent": "None",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "book flight from london to paris on feb 14th",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 17,
|
||||
"endPos": 22
|
||||
},
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 27,
|
||||
"endPos": 31
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "book flight to berlin on feb 14th",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 15,
|
||||
"endPos": 20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "book me a flight from london to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 22,
|
||||
"endPos": 27
|
||||
},
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 32,
|
||||
"endPos": 36
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "bye",
|
||||
"intent": "Cancel",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "cancel booking",
|
||||
"intent": "Cancel",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "exit",
|
||||
"intent": "Cancel",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "find an airport near me",
|
||||
"intent": "None",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "flight to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 10,
|
||||
"endPos": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "flight to paris from london on feb 14th",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 10,
|
||||
"endPos": 14
|
||||
},
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 21,
|
||||
"endPos": 26
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "fly from berlin to paris on may 5th",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 9,
|
||||
"endPos": 14
|
||||
},
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 19,
|
||||
"endPos": 23
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "go to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 6,
|
||||
"endPos": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "going from paris to berlin",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 11,
|
||||
"endPos": 15
|
||||
},
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 20,
|
||||
"endPos": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "i'd like to rent a car",
|
||||
"intent": "None",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "ignore",
|
||||
"intent": "Cancel",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "travel from new york to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "From",
|
||||
"startPos": 12,
|
||||
"endPos": 19
|
||||
},
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 24,
|
||||
"endPos": 28
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "travel to new york",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 10,
|
||||
"endPos": 17
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "travel to paris",
|
||||
"intent": "BookFlight",
|
||||
"entities": [
|
||||
{
|
||||
"entity": "To",
|
||||
"startPos": 10,
|
||||
"endPos": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "what's the forecast for this friday?",
|
||||
"intent": "GetWeather",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "what's the weather like for tomorrow",
|
||||
"intent": "GetWeather",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "what's the weather like in new york",
|
||||
"intent": "GetWeather",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "what's the weather like?",
|
||||
"intent": "GetWeather",
|
||||
"entities": []
|
||||
},
|
||||
{
|
||||
"text": "winter is coming",
|
||||
"intent": "None",
|
||||
"entities": []
|
||||
}
|
||||
],
|
||||
"settings": []
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
// This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot
|
||||
// implementation at runtime. Multiple different IBot implementations running at different endpoints can be
|
||||
// achieved by specifying a more specific type for the bot constructor argument.
|
||||
[Route("api")]
|
||||
[ApiController]
|
||||
public class BotController : ControllerBase
|
||||
{
|
||||
private readonly IBotFrameworkHttpAdapter _adapter;
|
||||
private IBot _bot;
|
||||
private readonly Func<string, IBot> _service;
|
||||
|
||||
public BotController(IBotFrameworkHttpAdapter adapter, Func<string, IBot> service)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_service = service;
|
||||
}
|
||||
|
||||
[Route("{*botname}")]
|
||||
[HttpPost]
|
||||
[HttpGet]
|
||||
public async Task PostAsync(string botname)
|
||||
{
|
||||
// Delegate the processing of the HTTP POST to the adapter.
|
||||
// The adapter will invoke the bot.
|
||||
_bot = _service(botname) ?? throw new Exception($"The endpoint '{botname}' is not associated with a bot.");
|
||||
|
||||
await _adapter.ProcessAsync(Request, Response, _bot);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Debugging
|
||||
{
|
||||
public class DebugBot : ActivityHandler
|
||||
{
|
||||
private InspectionMiddleware _inspectionMiddleware;
|
||||
|
||||
public DebugBot(InspectionMiddleware inspectionMiddleware)
|
||||
{
|
||||
_inspectionMiddleware = inspectionMiddleware;
|
||||
}
|
||||
|
||||
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
|
||||
{
|
||||
await _inspectionMiddleware.ProcessCommandAsync(turnContext);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Bot.Builder.TestBot.Debugging;
|
||||
|
||||
namespace Microsoft.Bot.Builder.TestBot.Controllers
|
||||
{
|
||||
[Route("api/debug")]
|
||||
[ApiController]
|
||||
public class DebugController : ControllerBase
|
||||
{
|
||||
private DebugAdapter _adapter;
|
||||
private DebugBot _bot;
|
||||
|
||||
public DebugController(DebugAdapter adapter, DebugBot bot)
|
||||
{
|
||||
_adapter = adapter;
|
||||
_bot = bot;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task PostAsync()
|
||||
{
|
||||
await _adapter.ProcessAsync(Request, Response, _bot);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
public static class DialogExtensions
|
||||
{
|
||||
public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken)
|
||||
{
|
||||
var dialogSet = new DialogSet(accessor);
|
||||
dialogSet.Add(dialog);
|
||||
|
||||
var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
|
||||
var results = await dialogContext.ContinueDialogAsync(cancellationToken);
|
||||
if (results.Status == DialogTurnStatus.Empty)
|
||||
{
|
||||
await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.Dialogs;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.BotBuilderSamples.CognitiveModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
// A root dialog responsible of understanding user intents and dispatching them sub tasks.
|
||||
public class MainDialog : ComponentDialog
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IRecognizer _luisRecognizer;
|
||||
|
||||
public MainDialog(ILogger<MainDialog> logger, BookingDialog bookingDialog)
|
||||
: this(logger, null, bookingDialog)
|
||||
{
|
||||
}
|
||||
|
||||
public MainDialog(ILogger<MainDialog> logger, IRecognizer luisRecognizer, BookingDialog bookingDialog)
|
||||
: base(nameof(MainDialog))
|
||||
{
|
||||
_logger = logger;
|
||||
_luisRecognizer = luisRecognizer;
|
||||
|
||||
AddDialog(new TextPrompt(nameof(TextPrompt)));
|
||||
|
||||
// Add bookingDialog intents
|
||||
AddDialog(bookingDialog);
|
||||
|
||||
// Create and add waterfall for main conversation loop
|
||||
// NOTE: we use a different task step if LUIS is not configured.
|
||||
WaterfallStep[] steps;
|
||||
if (luisRecognizer == null)
|
||||
{
|
||||
steps = new WaterfallStep[]
|
||||
{
|
||||
PromptForTaskActionAsync,
|
||||
InvokeTaskActionAsyncNoLuis,
|
||||
ResumeMainLoopActionAsync,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// LUIS is configured
|
||||
steps = new WaterfallStep[]
|
||||
{
|
||||
PromptForTaskActionAsync,
|
||||
InvokeTaskActionAsync,
|
||||
ResumeMainLoopActionAsync,
|
||||
};
|
||||
}
|
||||
|
||||
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), steps));
|
||||
|
||||
// The initial child Dialog to run.
|
||||
InitialDialogId = nameof(WaterfallDialog);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> PromptForTaskActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_luisRecognizer == null)
|
||||
{
|
||||
var activity = MessageFactory.Text("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.");
|
||||
activity.InputHint = InputHints.IgnoringInput;
|
||||
await stepContext.Context.SendActivityAsync(activity, cancellationToken);
|
||||
}
|
||||
|
||||
// Use the text provided in ResumeMainLoopActionAsync or the default if it is the first time.
|
||||
var promptText = stepContext.Options?.ToString() ?? "What can I help you with today?";
|
||||
|
||||
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text(promptText) }, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> InvokeTaskActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);
|
||||
|
||||
switch (luisResult.TopIntent().intent)
|
||||
{
|
||||
case FlightBooking.Intent.BookFlight:
|
||||
// Initialize BookingDetails with any entities we may have found in the response.
|
||||
var bookingDetails = new BookingDetails()
|
||||
{
|
||||
// Get destination and origin from the composite entities arrays.
|
||||
Destination = luisResult.Entities.To?.FirstOrDefault()?.Airport?.FirstOrDefault()?.FirstOrDefault(),
|
||||
Origin = luisResult.Entities.From?.FirstOrDefault()?.Airport?.FirstOrDefault()?.FirstOrDefault(),
|
||||
|
||||
// This value will be a TIMEX. And we are only interested in a Date so grab the first result and drop the Time part.
|
||||
// TIMEX is a format that represents DateTime expressions that include some ambiguity. e.g. missing a Year.
|
||||
TravelDate = luisResult.Entities.datetime?.FirstOrDefault()?.Expressions.FirstOrDefault()?.Split('T')[0],
|
||||
};
|
||||
|
||||
// Run the BookingDialog giving it whatever details we have from the LUIS call, it will fill out the remainder.
|
||||
return await stepContext.BeginDialogAsync(nameof(BookingDialog), bookingDetails, cancellationToken);
|
||||
|
||||
case FlightBooking.Intent.GetWeather:
|
||||
// We haven't implemented the GetWeatherDialog so we just display a TODO message.
|
||||
await stepContext.Context.SendActivityAsync("TODO: get weather flow here", cancellationToken: cancellationToken);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Catch all for unhandled intents
|
||||
await stepContext.Context.SendActivityAsync($"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})", cancellationToken: cancellationToken);
|
||||
break;
|
||||
}
|
||||
|
||||
return await stepContext.NextAsync(null, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> InvokeTaskActionAsyncNoLuis(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
// We only handle book a flight if LUIS is not configured
|
||||
return await stepContext.BeginDialogAsync(nameof(BookingDialog), new BookingDetails(), cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<DialogTurnResult> ResumeMainLoopActionAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
|
||||
{
|
||||
// We have completed the task (or the user cancelled), we restart main dialog with a different prompt text.
|
||||
var promptMessage = "What else can I do for you?";
|
||||
return await stepContext.ReplaceDialogAsync(Id, promptMessage, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,14 +6,6 @@
|
|||
<RootNamespace>Microsoft.BotBuilderSamples</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Cards\welcomeCard.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Cards\welcomeCard.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.DataTypes.TimexExpression" Version="1.2.9" />
|
||||
|
@ -23,6 +15,7 @@
|
|||
<ProjectReference Include="..\..\libraries\integration\Microsoft.Bot.Builder.Integration.AspNet.Core\Microsoft.Bot.Builder.Integration.AspNet.Core.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.AI.LUIS\Microsoft.Bot.Builder.AI.Luis.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Dialogs\Microsoft.Bot.Builder.Dialogs.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.TestBot.Shared\Microsoft.Bot.Builder.TestBot.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.BotBuilderSamples.Services
|
||||
{
|
||||
public interface IFlightBookingService
|
||||
{
|
||||
Task<bool> BookFlight(BookingDetails booking, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
|
@ -7,9 +7,10 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Builder.TestBot.Bots;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Bots;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Dialogs;
|
||||
using Microsoft.Bot.Builder.TestBot.Shared.Services;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
using Microsoft.BotBuilderSamples.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace Microsoft.BotBuilderSamples
|
||||
{
|
||||
/// <summary>
|
||||
/// This is our application state. Just a regular serializable .NET class.
|
||||
/// </summary>
|
||||
public class UserProfile
|
||||
{
|
||||
public string Transport { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public int Age { get; set; }
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче