From b86381ab1360a9d94ab1a0fe870c9c5a4e029fb4 Mon Sep 17 00:00:00 2001 From: carlosscastro Date: Mon, 3 May 2021 13:33:28 -0700 Subject: [PATCH 1/2] Telephony: integration tests and CommandDialog interruption model first pass --- .gitignore | 1 + packages/Telephony/Actions/PauseRecording.cs | 2 +- packages/Telephony/Actions/ResumeRecording.cs | 2 +- packages/Telephony/Actions/StartRecording.cs | 2 +- packages/Telephony/Common/CommandDialog{T}.cs | 49 ++++++++-- tests/Microsoft.Bot.Components.Tests.sln | 23 +++-- .../Recording_BaseScenario.test.dialog | 39 ++++++++ ...cording_CommandResultWrongName.test.dialog | 27 +++++ .../StartRecording_HappyPath.test.dialog | 28 ++++++ ...g_IgnoredInNonTelephonyChannel.test.dialog | 15 +++ ...thTangent_InterruptionDisabled.test.dialog | 32 ++++++ ...ithTangent_InterruptionEnabled.test.dialog | 36 +++++++ .../IntegrationTestsBase.cs | 30 ++++++ ...soft.Bot.Components.Telephony.Tests.csproj | 57 +++++++++++ .../NuGet.Config | 7 ++ .../RecordingTests.cs | 54 ++++++++++ .../ResourceExplorerFixture.cs | 38 +++++++ .../TestUtils.cs | 98 +++++++++++++++++++ 18 files changed, 522 insertions(+), 18 deletions(-) create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/Recording_BaseScenario.test.dialog create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_CommandResultWrongName.test.dialog create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_HappyPath.test.dialog create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_IgnoredInNonTelephonyChannel.test.dialog create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionDisabled.test.dialog create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionEnabled.test.dialog create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/IntegrationTestsBase.cs create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/Microsoft.Bot.Components.Telephony.Tests.csproj create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/NuGet.Config create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/RecordingTests.cs create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/ResourceExplorerFixture.cs create mode 100644 tests/packages/Microsoft.Bot.Components.Telephony.Tests/TestUtils.cs diff --git a/.gitignore b/.gitignore index 7f2ab38b1a..cf918b024c 100644 --- a/.gitignore +++ b/.gitignore @@ -383,6 +383,7 @@ experimental/generator-dotnet-yeoman/node_modules # Allow the root-level /packages/ directory or it gets confused with NuGet directories !/[Pp]ackages/* +!/tests/[Pp]ackages/* # Ignore correct yarn files (no zero install support) .yarn/* diff --git a/packages/Telephony/Actions/PauseRecording.cs b/packages/Telephony/Actions/PauseRecording.cs index 6ee21f9264..76e71b4338 100644 --- a/packages/Telephony/Actions/PauseRecording.cs +++ b/packages/Telephony/Actions/PauseRecording.cs @@ -41,7 +41,7 @@ public PauseRecording([CallerFilePath] string sourceFilePath = "", [CallerLineNu // enable instances of this command as debug break point this.RegisterSourceLocation(sourceFilePath, sourceLineNumber); - this.Name = RecordingPause; + this.CommandName = RecordingPause; } public async override Task BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default) diff --git a/packages/Telephony/Actions/ResumeRecording.cs b/packages/Telephony/Actions/ResumeRecording.cs index c95d3a2688..0621bd3776 100644 --- a/packages/Telephony/Actions/ResumeRecording.cs +++ b/packages/Telephony/Actions/ResumeRecording.cs @@ -41,7 +41,7 @@ public ResumeRecording([CallerFilePath] string sourceFilePath = "", [CallerLineN // enable instances of this command as debug break point this.RegisterSourceLocation(sourceFilePath, sourceLineNumber); - this.Name = RecordingResume; + this.CommandName = RecordingResume; } public async override Task BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default) diff --git a/packages/Telephony/Actions/StartRecording.cs b/packages/Telephony/Actions/StartRecording.cs index 53f374d055..35f656f403 100644 --- a/packages/Telephony/Actions/StartRecording.cs +++ b/packages/Telephony/Actions/StartRecording.cs @@ -41,7 +41,7 @@ public StartRecording([CallerFilePath] string sourceFilePath = "", [CallerLineNu // enable instances of this command as debug break point this.RegisterSourceLocation(sourceFilePath, sourceLineNumber); - this.Name = RecordingStart; + this.CommandName = RecordingStart; this.Data = new RecordingStartSettings() { diff --git a/packages/Telephony/Common/CommandDialog{T}.cs b/packages/Telephony/Common/CommandDialog{T}.cs index 7723ba62ac..8455130fc3 100644 --- a/packages/Telephony/Common/CommandDialog{T}.cs +++ b/packages/Telephony/Common/CommandDialog{T}.cs @@ -9,7 +9,9 @@ using AdaptiveExpressions.Properties; using Microsoft.Bot.Builder; using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Builder.Dialogs.Adaptive; using Microsoft.Bot.Schema; +using Newtonsoft.Json; namespace Microsoft.Bot.Components.Telephony.Common { @@ -23,13 +25,22 @@ namespace Microsoft.Bot.Components.Telephony.Common /// Type of data stored in the . public class CommandDialog : Dialog { + /// + /// Gets or sets intteruption policy. + /// + /// + /// Bool or expression which evalutes to bool. + /// + [JsonProperty("allowInterruptions")] + public BoolExpression AllowInterruptions { get; set; } = true; + /// /// Gets or sets the name of the command. /// /// /// . /// - protected StringExpression Name { get; set; } + protected StringExpression CommandName { get; set; } /// /// Gets or sets the data payload of the command. @@ -42,8 +53,7 @@ public class CommandDialog : Dialog public override async Task BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default) { // TODO: check name not null / expression has value - - var startRecordingActivity = CreateCommandActivity(dc.Context, this.Data, this.Name.GetValue(dc.State)); + var startRecordingActivity = CreateCommandActivity(dc.Context, this.Data, this.CommandName.GetValue(dc.State)); var response = await dc.Context.SendActivityAsync(startRecordingActivity, cancellationToken).ConfigureAwait(false); @@ -54,18 +64,17 @@ public override async Task BeginDialogAsync(DialogContext dc, public override async Task ContinueDialogAsync(DialogContext dc, CancellationToken cancellationToken = default) { - // check activity var activity = dc.Context.Activity; - // If command result, handle it + // We are expecting a command result with the same name as our current CommandName. if (activity.Type == ActivityTypes.CommandResult - && activity.Name == this.Name.GetValue(dc.State)) + && activity.Name == this.CommandName.GetValue(dc.State)) { // TODO: correlate command id before handling it. var commandResult = TelephonyExtensions.GetCommandResultValue(activity); - if (commandResult.Error != null) + if (commandResult?.Error != null) { throw new ErrorResponseException($"{commandResult.Error.Code}: {commandResult.Error.Message}"); } @@ -73,11 +82,33 @@ public override async Task ContinueDialogAsync(DialogContext d return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false); } - // for now, end turn and keep waiting - // TODO: Carlos add interruption model + // This activity was not the command result we were expecting. Mark as waiting and end the turn. return new DialogTurnResult(DialogTurnStatus.Waiting); } + /// + protected override async Task OnPreBubbleEventAsync(DialogContext dc, DialogEvent e, CancellationToken cancellationToken) + { + if (e.Name == DialogEvents.ActivityReceived && dc.Context.Activity.Type == ActivityTypes.Message) + { + // Ask parent to perform recognition + await dc.Parent.EmitEventAsync(AdaptiveEvents.RecognizeUtterance, value: dc.Context.Activity, bubble: false, cancellationToken: cancellationToken).ConfigureAwait(false); + + // Should we allow interruptions + var canInterrupt = true; + if (this.AllowInterruptions != null) + { + var (allowInterruptions, error) = this.AllowInterruptions.TryGetValue(dc.State); + canInterrupt = error == null && allowInterruptions; + } + + // Stop bubbling if interruptions ar NOT allowed + return !canInterrupt; + } + + return false; + } + private static Activity CreateCommandActivity(ITurnContext turnContext, T data, string name) { if (turnContext == null) diff --git a/tests/Microsoft.Bot.Components.Tests.sln b/tests/Microsoft.Bot.Components.Tests.sln index 526ce29afe..245e5fd261 100644 --- a/tests/Microsoft.Bot.Components.Tests.sln +++ b/tests/Microsoft.Bot.Components.Tests.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31112.23 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Components.Teams", "..\packages\Teams\Microsoft.Bot.Components.Teams.csproj", "{1C09226C-3DE0-48BF-BEB7-68F0691908EA}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "skills", "skills", "{31CBAEDA-E319-49AE-A662-AA0739205C82}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Dialogs.Tests.Common", "skills\common\Microsoft.Bot.Dialogs.Tests.Common.csproj", "{94784B33-91CD-4EFE-A1DF-D0FD670A0058}" @@ -21,16 +19,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Components.Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Components.Graph", "..\packages\Graph\Microsoft.Bot.Components.Graph.csproj", "{9561BF32-D0EE-464F-981B-7E4298ACDDFB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "telephony", "telephony", "{47F3E043-D5E7-42E3-8B18-DF64A9F2FC1C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Components.Telephony.Tests", "packages\Microsoft.Bot.Components.Telephony.Tests\Microsoft.Bot.Components.Telephony.Tests.csproj", "{485E9D0F-6534-475D-8400-31BFF633EDE0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Components.Telephony", "..\packages\Telephony\Microsoft.Bot.Components.Telephony.csproj", "{BDA3A62A-8762-44EA-A417-5DC01D26AAF9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1C09226C-3DE0-48BF-BEB7-68F0691908EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1C09226C-3DE0-48BF-BEB7-68F0691908EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1C09226C-3DE0-48BF-BEB7-68F0691908EA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1C09226C-3DE0-48BF-BEB7-68F0691908EA}.Release|Any CPU.Build.0 = Release|Any CPU {94784B33-91CD-4EFE-A1DF-D0FD670A0058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {94784B33-91CD-4EFE-A1DF-D0FD670A0058}.Debug|Any CPU.Build.0 = Debug|Any CPU {94784B33-91CD-4EFE-A1DF-D0FD670A0058}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -51,6 +51,14 @@ Global {9561BF32-D0EE-464F-981B-7E4298ACDDFB}.Debug|Any CPU.Build.0 = Debug|Any CPU {9561BF32-D0EE-464F-981B-7E4298ACDDFB}.Release|Any CPU.ActiveCfg = Release|Any CPU {9561BF32-D0EE-464F-981B-7E4298ACDDFB}.Release|Any CPU.Build.0 = Release|Any CPU + {485E9D0F-6534-475D-8400-31BFF633EDE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {485E9D0F-6534-475D-8400-31BFF633EDE0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {485E9D0F-6534-475D-8400-31BFF633EDE0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {485E9D0F-6534-475D-8400-31BFF633EDE0}.Release|Any CPU.Build.0 = Release|Any CPU + {BDA3A62A-8762-44EA-A417-5DC01D26AAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDA3A62A-8762-44EA-A417-5DC01D26AAF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDA3A62A-8762-44EA-A417-5DC01D26AAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDA3A62A-8762-44EA-A417-5DC01D26AAF9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -61,6 +69,9 @@ Global {F0E73465-DB1D-4F8A-B527-88F1E2515A5C} = {31CBAEDA-E319-49AE-A662-AA0739205C82} {61708441-52A4-48F6-819A-B8D4C279C4C8} = {73825711-6685-48E2-BFA2-3FCDECE1A0FD} {F6E872DE-52B7-4372-B546-B18B5A495C73} = {61708441-52A4-48F6-819A-B8D4C279C4C8} + {47F3E043-D5E7-42E3-8B18-DF64A9F2FC1C} = {73825711-6685-48E2-BFA2-3FCDECE1A0FD} + {485E9D0F-6534-475D-8400-31BFF633EDE0} = {47F3E043-D5E7-42E3-8B18-DF64A9F2FC1C} + {BDA3A62A-8762-44EA-A417-5DC01D26AAF9} = {47F3E043-D5E7-42E3-8B18-DF64A9F2FC1C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2D0FB02B-704A-44E0-AECA-A4FDF6F805C5} diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/Recording_BaseScenario.test.dialog b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/Recording_BaseScenario.test.dialog new file mode 100644 index 0000000000..81be53b22c --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/Recording_BaseScenario.test.dialog @@ -0,0 +1,39 @@ +{ + "$schema": "../../../tests.schema", + "$kind": "Microsoft.AdaptiveDialog", + "id": "Recording_BaseScenario.test", + "triggers": [ + { + "$kind": "Microsoft.OnBeginDialog", + "actions": [ + { + "$kind": "Microsoft.Telephony.StartRecording", + "allowInterruptions": "=coalesce(settings.allowInterruptions, true)" + }, + { + "$kind": "Microsoft.SendActivity", + "activity": "Started recording!" + } + ] + }, + { + "$kind": "Microsoft.OnIntent", + "intent": "HelpIntent", + "actions": [ + { + "$kind": "Microsoft.SendActivity", + "activity": "On help intent handler" + } + ] + } + ], + "recognizer": { + "$kind": "Microsoft.RegexRecognizer", + "intents": [ + { + "intent": "HelpIntent", + "pattern": "help" + } + ] + } +} \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_CommandResultWrongName.test.dialog b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_CommandResultWrongName.test.dialog new file mode 100644 index 0000000000..d855a45db4 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_CommandResultWrongName.test.dialog @@ -0,0 +1,27 @@ +{ + "$schema": "../../../tests.schema", + "$kind": "Microsoft.Test.Script", + "dialog": "Recording_BaseScenario.test", + "script": [ + { + "$kind": "Microsoft.Test.UserSays", + "text": "Hello I'm Bender" + }, + { + "$kind": "Microsoft.Test.AssertReplyActivity", + "assertions": [ + "type == 'command'", + ] + }, + { + "$kind": "Microsoft.Test.UserActivity", + "activity": { + "type": "commandResult", + "name": "wrong name" + } + }, + { + "$kind": "Microsoft.Test.AssertNoActivity" + } + ] +} \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_HappyPath.test.dialog b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_HappyPath.test.dialog new file mode 100644 index 0000000000..a6f727ec3c --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_HappyPath.test.dialog @@ -0,0 +1,28 @@ +{ + "$schema": "../../../tests.schema", + "$kind": "Microsoft.Test.Script", + "dialog": "Recording_BaseScenario.test", + "script": [ + { + "$kind": "Microsoft.Test.UserSays", + "text": "Hello I'm Calculon" + }, + { + "$kind": "Microsoft.Test.AssertReplyActivity", + "assertions": [ + "type == 'command'", + ] + }, + { + "$kind": "Microsoft.Test.UserActivity", + "activity": { + "type": "commandResult", + "name": "channel/vnd.microsoft.telephony.recording.start" + } + }, + { + "$kind": "Microsoft.Test.AssertReply", + "text": "Started recording!" + } + ] +} \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_IgnoredInNonTelephonyChannel.test.dialog b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_IgnoredInNonTelephonyChannel.test.dialog new file mode 100644 index 0000000000..efaea32878 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_IgnoredInNonTelephonyChannel.test.dialog @@ -0,0 +1,15 @@ +{ + "$schema": "../../../tests.schema", + "$kind": "Microsoft.Test.Script", + "dialog": "Recording_BaseScenario.test", + "script": [ + { + "$kind": "Microsoft.Test.UserSays", + "text": "Hello I'm Bender" + }, + { + "$kind": "Microsoft.Test.AssertReply", + "text": "Started recording!" + } + ] +} \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionDisabled.test.dialog b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionDisabled.test.dialog new file mode 100644 index 0000000000..cca25d7426 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionDisabled.test.dialog @@ -0,0 +1,32 @@ +{ + "$schema": "../../../tests.schema", + "$kind": "Microsoft.Test.Script", + "dialog": "Recording_BaseScenario.test", + "script": [ + { + "$kind": "Microsoft.Test.UserSays", + "text": "Hello I'm Calculon" + }, + { + "$kind": "Microsoft.Test.AssertReplyActivity", + "assertions": [ + "type == 'command'", + ] + }, + { + "$kind": "Microsoft.Test.UserSays", + "text": "help" + }, + { + "$kind": "Microsoft.Test.UserActivity", + "activity": { + "type": "commandResult", + "name": "channel/vnd.microsoft.telephony.recording.start" + } + }, + { + "$kind": "Microsoft.Test.AssertReply", + "text": "Started recording!" + } + ] +} \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionEnabled.test.dialog b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionEnabled.test.dialog new file mode 100644 index 0000000000..3074f5d77e --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Integration/RecordingTests/StartRecording_WithTangent_InterruptionEnabled.test.dialog @@ -0,0 +1,36 @@ +{ + "$schema": "../../../tests.schema", + "$kind": "Microsoft.Test.Script", + "dialog": "Recording_BaseScenario.test", + "script": [ + { + "$kind": "Microsoft.Test.UserSays", + "text": "Hello I'm Calculon" + }, + { + "$kind": "Microsoft.Test.AssertReplyActivity", + "assertions": [ + "type == 'command'", + ] + }, + { + "$kind": "Microsoft.Test.UserSays", + "text": "help" + }, + { + "$kind": "Microsoft.Test.AssertReply", + "text": "On help intent handler" + }, + { + "$kind": "Microsoft.Test.UserActivity", + "activity": { + "type": "commandResult", + "name": "channel/vnd.microsoft.telephony.recording.start" + } + }, + { + "$kind": "Microsoft.Test.AssertReply", + "text": "Started recording!" + } + ] +} \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/IntegrationTestsBase.cs b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/IntegrationTestsBase.cs new file mode 100644 index 0000000000..9f1af39abe --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/IntegrationTestsBase.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Builder.Dialogs.Adaptive; +using Microsoft.Bot.Builder.Dialogs.Adaptive.Testing; +using Microsoft.Bot.Builder.Dialogs.Declarative; +using Microsoft.Bot.Builder.Dialogs.Declarative.Obsolete; +using Xunit; + +namespace Microsoft.Bot.Components.Telephony.Tests +{ + public class IntegrationTestsBase : IClassFixture + { + protected readonly ResourceExplorerFixture _resourceExplorerFixture; + + public IntegrationTestsBase(ResourceExplorerFixture resourceExplorerFixture) + { + ComponentRegistration.Add(new DeclarativeComponentRegistration()); + ComponentRegistration.Add(new DialogsComponentRegistration()); + ComponentRegistration.Add(new AdaptiveComponentRegistration()); + ComponentRegistration.Add(new LanguageGenerationComponentRegistration()); + ComponentRegistration.Add(new AdaptiveTestingComponentRegistration()); + ComponentRegistration.Add(new DeclarativeComponentRegistrationBridge()); + + _resourceExplorerFixture = resourceExplorerFixture.Initialize(this.GetType().Name); + } + } +} diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Microsoft.Bot.Components.Telephony.Tests.csproj b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Microsoft.Bot.Components.Telephony.Tests.csproj new file mode 100644 index 0000000000..e50fc72b24 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/Microsoft.Bot.Components.Telephony.Tests.csproj @@ -0,0 +1,57 @@ + + + + netcoreapp2.1 + netcoreapp3.1 + netcoreapp2.1;netcoreapp3.1 + false + Debug;Release + latest + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/NuGet.Config b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/NuGet.Config new file mode 100644 index 0000000000..16e6dfff88 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/RecordingTests.cs b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/RecordingTests.cs new file mode 100644 index 0000000000..290035a0dd --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/RecordingTests.cs @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Bot.Connector; +using Microsoft.Bot.Schema; +using Microsoft.Extensions.Configuration; +using Xunit; + +namespace Microsoft.Bot.Components.Telephony.Tests +{ + public class RecordingTests : IntegrationTestsBase + { + public RecordingTests(ResourceExplorerFixture resourceExplorerFixture) : base(resourceExplorerFixture) + { + } + + [Fact] + public async Task StartRecording_HappyPath() + { + await TestUtils.RunTestScript(_resourceExplorerFixture.ResourceExplorer, adapterChannel: Channels.Telephony); + } + + [Fact] + public async Task StartRecording_WithTangent_InterruptionEnabled() + { + await TestUtils.RunTestScript(_resourceExplorerFixture.ResourceExplorer, adapterChannel: Channels.Telephony); + } + + [Fact] + public async Task StartRecording_WithTangent_InterruptionDisabled() + { + await TestUtils.RunTestScript( + _resourceExplorerFixture.ResourceExplorer, + adapterChannel: Channels.Telephony, + configuration: new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary() { { "allowInterruptions", "false" } }) + .Build()); + } + + [Fact] + public async Task StartRecording_CommandResultWrongName() + { + await TestUtils.RunTestScript(_resourceExplorerFixture.ResourceExplorer, adapterChannel: Channels.Telephony); + } + + [Fact] + public async Task StartRecording_IgnoredInNonTelephonyChannel() + { + await TestUtils.RunTestScript(_resourceExplorerFixture.ResourceExplorer, adapterChannel: Channels.Msteams); + } + } +} diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/ResourceExplorerFixture.cs b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/ResourceExplorerFixture.cs new file mode 100644 index 0000000000..48a56815e3 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/ResourceExplorerFixture.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Microsoft.Bot.Builder.Dialogs.Declarative.Resources; + +namespace Microsoft.Bot.Components.Telephony.Tests +{ + public class ResourceExplorerFixture : IDisposable + { + private string _folderPath = string.Empty; + + public ResourceExplorerFixture() + { + ResourceExplorer = new ResourceExplorer(); + } + + public ResourceExplorer ResourceExplorer { get; private set; } + + public ResourceExplorerFixture Initialize(string resourceFolder) + { + if (_folderPath.Length == 0) + { + _folderPath = Path.Combine(TestUtils.GetProjectPath(), "Integration", resourceFolder); + ResourceExplorer = ResourceExplorer.AddFolder(_folderPath, monitorChanges: false); + } + + return this; + } + + public void Dispose() + { + _folderPath = string.Empty; + ResourceExplorer.Dispose(); + } + } +} diff --git a/tests/packages/Microsoft.Bot.Components.Telephony.Tests/TestUtils.cs b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/TestUtils.cs new file mode 100644 index 0000000000..e6d2b11a50 --- /dev/null +++ b/tests/packages/Microsoft.Bot.Components.Telephony.Tests/TestUtils.cs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Adapters; +using Microsoft.Bot.Builder.Dialogs.Adaptive.Testing; +using Microsoft.Bot.Builder.Dialogs.Declarative.Resources; +using Microsoft.Bot.Connector; +using Microsoft.Bot.Schema; +using Microsoft.Extensions.Configuration; + +namespace Microsoft.Bot.Components.Telephony.Tests +{ + public class TestUtils + { + public static IConfiguration DefaultConfiguration { get; set; } = new ConfigurationBuilder().AddInMemoryCollection().Build(); + + public static string RootFolder { get; set; } = GetProjectPath(); + + public static IEnumerable GetTestScripts(string relativeFolder) + { + var testFolder = Path.GetFullPath(Path.Combine(RootFolder, PathUtils.NormalizePath(relativeFolder))); + return Directory.EnumerateFiles(testFolder, "*.test.dialog", SearchOption.AllDirectories).Select(s => new object[] { Path.GetFileName(s) }).ToArray(); + } + + public static async Task RunTestScript(ResourceExplorer resourceExplorer, string resourceId = null, IConfiguration configuration = null, [CallerMemberName] string testName = null, IEnumerable middleware = null, string adapterChannel = Channels.Msteams) + { + var storage = new MemoryStorage(); + var convoState = new ConversationState(storage); + var userState = new UserState(storage); + + var adapter = (TestAdapter)new TestAdapter(CreateConversation(adapterChannel, testName)); + + if (middleware != null) + { + foreach (var m in middleware) + { + adapter.Use(m); + } + } + + adapter.Use(new RegisterClassMiddleware(configuration ?? DefaultConfiguration)) + .UseStorage(storage) + .UseBotState(userState, convoState) + .Use(new TranscriptLoggerMiddleware(new TraceTranscriptLogger(traceActivity: false))); + + adapter.OnTurnError += async (context, err) => + { + if (err.Message.EndsWith("MemoryAssertion failed")) + { + throw err; + } + + await context.SendActivityAsync(err.Message); + }; + + var script = resourceExplorer.LoadType(resourceId ?? $"{testName}.test.dialog"); + script.Configuration = configuration ?? new ConfigurationBuilder().AddInMemoryCollection().Build(); + script.Description ??= resourceId; + await script.ExecuteAsync(adapter: adapter, testName: testName, resourceExplorer: resourceExplorer).ConfigureAwait(false); + } + + public static string GetProjectPath() + { + var parent = Environment.CurrentDirectory; + while (!string.IsNullOrEmpty(parent)) + { + if (Directory.EnumerateFiles(parent, "*proj").Any()) + { + break; + } + + parent = Path.GetDirectoryName(parent); + } + + return parent; + } + + public static ConversationReference CreateConversation(string channel, string conversationName) + { + return new ConversationReference + { + ChannelId = channel ?? Channels.Test, + ServiceUrl = "https://test.com", + User = new ChannelAccount("user1", "User1"), + Bot = new ChannelAccount("bot", "Bot"), + Conversation = new ConversationAccount(false, "personal", conversationName), + Locale = "en-US", + }; + } + } +} From e485b9f05eef0e5ea2c92424bf06d6242dabe852 Mon Sep 17 00:00:00 2001 From: carlosscastro Date: Mon, 3 May 2021 13:58:18 -0700 Subject: [PATCH 2/2] Telephony: adjust usings position and remove unnecesary ones --- packages/Telephony/Actions/CallTransfer.cs | 16 +++++++------- packages/Telephony/Actions/PauseRecording.cs | 21 +++++++----------- packages/Telephony/Actions/ResumeRecording.cs | 21 +++++++----------- packages/Telephony/Actions/StartRecording.cs | 22 ++++++++----------- packages/Telephony/Common/CommandDialog{T}.cs | 2 -- .../Common/RecordingStartSettings.cs | 4 ---- .../Telephony/Common/TelephonyExtensions.cs | 4 ---- 7 files changed, 33 insertions(+), 57 deletions(-) diff --git a/packages/Telephony/Actions/CallTransfer.cs b/packages/Telephony/Actions/CallTransfer.cs index 2551644ea9..f0e7dee426 100644 --- a/packages/Telephony/Actions/CallTransfer.cs +++ b/packages/Telephony/Actions/CallTransfer.cs @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using AdaptiveExpressions.Properties; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Dialogs; +using Newtonsoft.Json; + namespace Microsoft.Bot.Components.Telephony.Actions { - using System.Runtime.CompilerServices; - using System.Threading; - using System.Threading.Tasks; - using AdaptiveExpressions.Properties; - using Microsoft.Bot.Builder; - using Microsoft.Bot.Builder.Dialogs; - using Newtonsoft.Json; - /// /// Transfers call to given phone number. /// diff --git a/packages/Telephony/Actions/PauseRecording.cs b/packages/Telephony/Actions/PauseRecording.cs index 76e71b4338..b80b5f81bf 100644 --- a/packages/Telephony/Actions/PauseRecording.cs +++ b/packages/Telephony/Actions/PauseRecording.cs @@ -1,21 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Components.Telephony.Common; +using Microsoft.Bot.Connector; +using Newtonsoft.Json; + namespace Microsoft.Bot.Components.Telephony.Actions { - using System; - using System.Runtime.CompilerServices; - using System.Threading; - using System.Threading.Tasks; - using AdaptiveExpressions.Properties; - using Microsoft.Bot.Builder; - using Microsoft.Bot.Builder.Dialogs; - using Microsoft.Bot.Components.Telephony.Common; - using Microsoft.Bot.Connector; - using Microsoft.Bot.Schema; - using Microsoft.Bot.Schema.Telephony; - using Newtonsoft.Json; - /// /// Pauses recording the current conversation. /// diff --git a/packages/Telephony/Actions/ResumeRecording.cs b/packages/Telephony/Actions/ResumeRecording.cs index 0621bd3776..c089f20ae3 100644 --- a/packages/Telephony/Actions/ResumeRecording.cs +++ b/packages/Telephony/Actions/ResumeRecording.cs @@ -1,21 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Components.Telephony.Common; +using Microsoft.Bot.Connector; +using Newtonsoft.Json; + namespace Microsoft.Bot.Components.Telephony.Actions { - using System; - using System.Runtime.CompilerServices; - using System.Threading; - using System.Threading.Tasks; - using AdaptiveExpressions.Properties; - using Microsoft.Bot.Builder; - using Microsoft.Bot.Builder.Dialogs; - using Microsoft.Bot.Components.Telephony.Common; - using Microsoft.Bot.Connector; - using Microsoft.Bot.Schema; - using Microsoft.Bot.Schema.Telephony; - using Newtonsoft.Json; - /// /// Resume recording the current conversation. /// diff --git a/packages/Telephony/Actions/StartRecording.cs b/packages/Telephony/Actions/StartRecording.cs index 35f656f403..366e204148 100644 --- a/packages/Telephony/Actions/StartRecording.cs +++ b/packages/Telephony/Actions/StartRecording.cs @@ -1,21 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Components.Telephony.Common; +using Microsoft.Bot.Connector; +using Microsoft.Bot.Schema.Telephony; +using Newtonsoft.Json; + namespace Microsoft.Bot.Components.Telephony.Actions { - using System; - using System.Runtime.CompilerServices; - using System.Threading; - using System.Threading.Tasks; - using AdaptiveExpressions.Properties; - using Microsoft.Bot.Builder; - using Microsoft.Bot.Builder.Dialogs; - using Microsoft.Bot.Components.Telephony.Common; - using Microsoft.Bot.Connector; - using Microsoft.Bot.Schema; - using Microsoft.Bot.Schema.Telephony; - using Newtonsoft.Json; - /// /// Starts recording the current conversation. /// diff --git a/packages/Telephony/Common/CommandDialog{T}.cs b/packages/Telephony/Common/CommandDialog{T}.cs index 8455130fc3..9ab7721d4b 100644 --- a/packages/Telephony/Common/CommandDialog{T}.cs +++ b/packages/Telephony/Common/CommandDialog{T}.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; using AdaptiveExpressions.Properties; diff --git a/packages/Telephony/Common/RecordingStartSettings.cs b/packages/Telephony/Common/RecordingStartSettings.cs index c7074c348e..8c64845714 100644 --- a/packages/Telephony/Common/RecordingStartSettings.cs +++ b/packages/Telephony/Common/RecordingStartSettings.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.Collections.Generic; -using System.Text; - namespace Microsoft.Bot.Schema.Telephony { public enum RecordingContentType diff --git a/packages/Telephony/Common/TelephonyExtensions.cs b/packages/Telephony/Common/TelephonyExtensions.cs index 64bf07ed82..e4c0967889 100644 --- a/packages/Telephony/Common/TelephonyExtensions.cs +++ b/packages/Telephony/Common/TelephonyExtensions.cs @@ -1,10 +1,6 @@ // 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.Schema; using Newtonsoft.Json.Linq;