Merge pull request #188 from Microsoft/CLM/Prompts
Clm/prompts - authored by Tom in an amazing fit of coding frenzy!!
This commit is contained in:
Коммит
d28d218f78
|
@ -40,6 +40,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Connector.Tes
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bot.Samples.Ai.QnA", "samples\Microsoft.Bot.Samples.Ai.QnA\Microsoft.Bot.Samples.Ai.QnA.csproj", "{A8CE6B0F-E054-45F7-B4D7-23D2C65D2D26}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.Prompts", "libraries\Microsoft.Bot.Builder.Prompts\Microsoft.Bot.Builder.Prompts.csproj", "{7A197F41-3411-47BF-87A6-5BC8A44CDB74}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Bot.Builder.Prompts.Tests", "tests\Microsoft.Bot.Builder.Prompts.Tests\Microsoft.Bot.Builder.Prompts.Tests.csproj", "{5D145BFC-1C30-4FC5-989A-82260F8225BE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -110,6 +114,14 @@ Global
|
|||
{A8CE6B0F-E054-45F7-B4D7-23D2C65D2D26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A8CE6B0F-E054-45F7-B4D7-23D2C65D2D26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A8CE6B0F-E054-45F7-B4D7-23D2C65D2D26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7A197F41-3411-47BF-87A6-5BC8A44CDB74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7A197F41-3411-47BF-87A6-5BC8A44CDB74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7A197F41-3411-47BF-87A6-5BC8A44CDB74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7A197F41-3411-47BF-87A6-5BC8A44CDB74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5D145BFC-1C30-4FC5-989A-82260F8225BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -131,6 +143,8 @@ Global
|
|||
{C8DF8AE3-0A4D-445D-993E-F7A1784BFDD4} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
|
||||
{BF414C86-DB3B-4022-9B29-DCE8AA954C12} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
{A8CE6B0F-E054-45F7-B4D7-23D2C65D2D26} = {3ADFB27A-95FA-4330-B211-1D66A29A17AB}
|
||||
{7A197F41-3411-47BF-87A6-5BC8A44CDB74} = {4269F3C3-6B42-419B-B64A-3E6DC0F1574A}
|
||||
{5D145BFC-1C30-4FC5-989A-82260F8225BE} = {AD743B78-D61F-4FBF-B620-FA83CE599A50}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7173C9F3-A7F9-496E-9078-9156E35D6E16}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Microsoft.Bot.Builder.Adapters
|
|||
public class TestAdapter : BotAdapter
|
||||
{
|
||||
private int _nextId = 0;
|
||||
private readonly List<Activity> botReplies = new List<Activity>();
|
||||
private readonly List<Activity> botReplies = new List<Activity>();
|
||||
|
||||
public TestAdapter(ConversationReference reference = null)
|
||||
{
|
||||
|
@ -290,7 +290,12 @@ namespace Microsoft.Bot.Builder.Adapters
|
|||
if (expected.Type != reply.Type)
|
||||
throw new Exception($"{description}: Type should match");
|
||||
if (expected.AsMessageActivity().Text != reply.AsMessageActivity().Text)
|
||||
throw new Exception($"{description}: Text should match");
|
||||
{
|
||||
if (description == null)
|
||||
throw new Exception($"Expected:{expected.AsMessageActivity().Text}\nReceived:{reply.AsMessageActivity().Text}");
|
||||
else
|
||||
throw new Exception($"{description}: Text should match");
|
||||
}
|
||||
// TODO, expand this to do all properties set on expected
|
||||
}, description, timeout);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// AgePrompt recognizes age expressions like "95 years"
|
||||
/// </summary>
|
||||
public class AgePrompt : NumberWithUnitPrompt
|
||||
{
|
||||
public AgePrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(NumberWithUnitRecognizer.Instance.GetAgeModel(culture), validator)
|
||||
{
|
||||
}
|
||||
|
||||
protected AgePrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(model, validator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
using Microsoft.Bot.Schema;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
public abstract class BasePrompt<T>
|
||||
{
|
||||
private readonly PromptValidator<T> _customValidator = null;
|
||||
|
||||
public BasePrompt(PromptValidator<T> validator = null)
|
||||
{
|
||||
_customValidator = validator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Message, and queues it for sending to the user.
|
||||
/// </summary>
|
||||
public Task Prompt(IBotContext context, string text, string speak = null)
|
||||
{
|
||||
IMessageActivity activity = MessageFactory.Text(text, speak);
|
||||
activity.InputHint = InputHints.ExpectingInput;
|
||||
return Prompt(context, activity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Message Activity, and queues it for sending to the user.
|
||||
/// </summary>
|
||||
public Task Prompt(IBotContext context, IMessageActivity activity)
|
||||
{
|
||||
context.Reply(activity);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// implement to recognize the basic type
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns>null if not recognized</returns>
|
||||
public abstract Task<T> Recognize(IBotContext context);
|
||||
|
||||
|
||||
protected virtual Task<bool> Validate(IBotContext context, T value)
|
||||
{
|
||||
// Validation passed. Return the validated text.
|
||||
if (_customValidator != null)
|
||||
{
|
||||
return _customValidator(context, value);
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// CurrencyPrompt recognizes currency expressions as float type
|
||||
/// </summary>
|
||||
public class CurrencyPrompt : NumberWithUnitPrompt
|
||||
{
|
||||
public CurrencyPrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(NumberWithUnitRecognizer.Instance.GetCurrencyModel(culture), validator)
|
||||
{
|
||||
}
|
||||
|
||||
protected CurrencyPrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(model, validator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
//using System;
|
||||
//using System.Linq;
|
||||
//using System.Threading.Tasks;
|
||||
//using Microsoft.Bot.Schema;
|
||||
//using Microsoft.Recognizers.Text;
|
||||
//using Microsoft.Recognizers.Text.Number;
|
||||
//using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
//using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
//namespace Microsoft.Bot.Builder.Prompts
|
||||
//{
|
||||
// public class NumberWithUnit
|
||||
// {
|
||||
// public NumberWithUnit() { }
|
||||
|
||||
// public string Unit { get; set; }
|
||||
|
||||
// public float Amount { get; set; }
|
||||
|
||||
// public string Text { get; set; }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// CurrencyPrompt recognizes currency expressions as float type
|
||||
// /// </summary>
|
||||
// public class NumberWithUnitPrompt : BasePrompt<NumberWithUnit>
|
||||
// {
|
||||
// private readonly PromptValidator<NumberWithUnit, bool> _customValidator = null;
|
||||
// private IModel _model;
|
||||
|
||||
|
||||
// protected NumberWithUnitPrompt(IModel model, PromptValidator<NumberWithUnit, bool> validator = null)
|
||||
// {
|
||||
// _model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
// _customValidator = validator;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Used to validate the incoming text, expected on context.Request, is
|
||||
// /// valid according to the rules defined in the validation steps.
|
||||
// /// </summary>
|
||||
// public override async Task<NumberWithUnit> Recognize(IBotContext context)
|
||||
// {
|
||||
// BotAssert.ContextNotNull(context);
|
||||
// BotAssert.ActivityNotNull(context.Request);
|
||||
// if (context.Request.Type != ActivityTypes.Message)
|
||||
// throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
// IMessageActivity message = context.Request.AsMessageActivity();
|
||||
// var results = _model.Parse(message.Text);
|
||||
// if (results.Any())
|
||||
// {
|
||||
// var result = results.First();
|
||||
// NumberWithUnit value = new NumberWithUnit()
|
||||
// {
|
||||
// Text = result.Text,
|
||||
// Unit = (string)result.Resolution["unit"],
|
||||
// Amount = float.NaN
|
||||
// };
|
||||
// if (float.TryParse(result.Resolution["amount"]?.ToString() ?? String.Empty, out float val))
|
||||
// value.Amount = val;
|
||||
|
||||
// if (await Validate(context, value))
|
||||
// return value;
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
// protected Task<bool> Validate(IBotContext context, NumberWithUnit value)
|
||||
// {
|
||||
// // Validation passed. Return the validated text.
|
||||
// if (_customValidator != null)
|
||||
// {
|
||||
// return _customValidator(context, value);
|
||||
// }
|
||||
// return Task.FromResult(true);
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
//}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// DimensionPrompt recognizes dimension expressions like "4 feet" or "6 miles"
|
||||
/// </summary>
|
||||
public class DimensionPrompt : NumberWithUnitPrompt
|
||||
{
|
||||
public DimensionPrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(NumberWithUnitRecognizer.Instance.GetDimensionModel(culture), validator)
|
||||
{
|
||||
}
|
||||
|
||||
protected DimensionPrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(model, validator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.Number" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.NumberWithUnit" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.Sequence" Version="1.0.0.36" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
public class NumberResult<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NumberPrompt recognizes floats or ints
|
||||
/// </summary>
|
||||
public class NumberPrompt<T> : BasePrompt<NumberResult<T>>
|
||||
{
|
||||
private IModel _model;
|
||||
|
||||
public NumberPrompt(string culture, PromptValidator<NumberResult<T>> validator = null)
|
||||
: base(validator)
|
||||
{
|
||||
_model = NumberRecognizer.Instance.GetNumberModel(culture);
|
||||
}
|
||||
|
||||
protected NumberPrompt(IModel model, PromptValidator<NumberResult<T>> validator = null)
|
||||
: base(validator)
|
||||
{
|
||||
_model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to validate the incoming text, expected on context.Request, is
|
||||
/// valid according to the rules defined in the validation steps.
|
||||
/// </summary>
|
||||
public override async Task<NumberResult<T>> Recognize(IBotContext context)
|
||||
{
|
||||
BotAssert.ContextNotNull(context);
|
||||
BotAssert.ActivityNotNull(context.Request);
|
||||
if (context.Request.Type != ActivityTypes.Message)
|
||||
throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
IMessageActivity message = context.Request.AsMessageActivity();
|
||||
var results = _model.Parse(message.Text);
|
||||
if (results.Any())
|
||||
{
|
||||
var result = results.First();
|
||||
if (typeof(T) == typeof(float))
|
||||
{
|
||||
if (float.TryParse(result.Resolution["value"].ToString(), out float value))
|
||||
{
|
||||
NumberResult<T> numberResult = new NumberResult<T>()
|
||||
{
|
||||
Value = (T)(object)value,
|
||||
Text = result.Text
|
||||
};
|
||||
if (await Validate(context, numberResult))
|
||||
return numberResult;
|
||||
}
|
||||
}
|
||||
else if (typeof(T) == typeof(int))
|
||||
{
|
||||
if (int.TryParse(result.Resolution["value"].ToString(), out int value))
|
||||
{
|
||||
NumberResult<T> numberResult = new NumberResult<T>()
|
||||
{
|
||||
Value = (T)(object)value,
|
||||
Text = result.Text
|
||||
};
|
||||
if (await Validate(context, numberResult))
|
||||
return numberResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
public class NumberWithUnit
|
||||
{
|
||||
public NumberWithUnit() { }
|
||||
|
||||
public string Unit { get; set; }
|
||||
|
||||
public float Value { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CurrencyPrompt recognizes currency expressions as float type
|
||||
/// </summary>
|
||||
public class NumberWithUnitPrompt : BasePrompt<NumberWithUnit>
|
||||
{
|
||||
private IModel _model;
|
||||
|
||||
|
||||
protected NumberWithUnitPrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)
|
||||
:base(validator)
|
||||
{
|
||||
_model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to validate the incoming text, expected on context.Request, is
|
||||
/// valid according to the rules defined in the validation steps.
|
||||
/// </summary>
|
||||
public override async Task<NumberWithUnit> Recognize(IBotContext context)
|
||||
{
|
||||
BotAssert.ContextNotNull(context);
|
||||
BotAssert.ActivityNotNull(context.Request);
|
||||
if (context.Request.Type != ActivityTypes.Message)
|
||||
throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
IMessageActivity message = context.Request.AsMessageActivity();
|
||||
var results = _model.Parse(message.Text);
|
||||
if (results.Any())
|
||||
{
|
||||
var result = results.First();
|
||||
NumberWithUnit value = new NumberWithUnit()
|
||||
{
|
||||
Text = result.Text,
|
||||
Unit = (string)result.Resolution["unit"],
|
||||
Value = float.NaN
|
||||
};
|
||||
if (float.TryParse(result.Resolution["value"]?.ToString() ?? String.Empty, out float val))
|
||||
value.Value = val;
|
||||
|
||||
if (await Validate(context, value))
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// OrdinalPrompt recognizes pharses like First, 2nd, third, etc.
|
||||
/// </summary>
|
||||
public class OrdinalPrompt : NumberPrompt<int>
|
||||
{
|
||||
|
||||
public OrdinalPrompt(string culture, PromptValidator<NumberResult<int>> validator = null)
|
||||
: base(NumberRecognizer.Instance.GetOrdinalModel(culture), validator)
|
||||
{
|
||||
}
|
||||
|
||||
protected OrdinalPrompt(IModel model, PromptValidator<NumberResult<int>> validator = null)
|
||||
: base(model, validator)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// PercentagePrompt recognizes percentage expressions as float type
|
||||
/// </summary>
|
||||
public class PercentagePrompt : BasePrompt<NumberResult<float>>
|
||||
{
|
||||
private IModel _model;
|
||||
|
||||
public PercentagePrompt(string culture, PromptValidator<NumberResult<float>> validator = null)
|
||||
: base( validator)
|
||||
{
|
||||
_model = NumberRecognizer.Instance.GetPercentageModel(culture);
|
||||
}
|
||||
|
||||
|
||||
protected PercentagePrompt(IModel model, PromptValidator<NumberResult<float>> validator = null)
|
||||
: base(validator)
|
||||
{
|
||||
_model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to validate the incoming text, expected on context.Request, is
|
||||
/// valid according to the rules defined in the validation steps.
|
||||
/// </summary>
|
||||
public override async Task<NumberResult<float>> Recognize(IBotContext context)
|
||||
{
|
||||
BotAssert.ContextNotNull(context);
|
||||
BotAssert.ActivityNotNull(context.Request);
|
||||
if (context.Request.Type != ActivityTypes.Message)
|
||||
throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
IMessageActivity message = context.Request.AsMessageActivity();
|
||||
var results = _model.Parse(message.Text);
|
||||
if (results.Any())
|
||||
{
|
||||
var result = results.First();
|
||||
if (float.TryParse(result.Resolution["value"].ToString().TrimEnd('%'), out float value))
|
||||
{
|
||||
NumberResult<float> numberResult = new NumberResult<float>()
|
||||
{
|
||||
Value = value,
|
||||
Text = result.Text
|
||||
};
|
||||
if (await Validate(context, numberResult))
|
||||
return numberResult;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using Microsoft.Recognizers.Text.Sequence;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
/// <summary>
|
||||
/// PhoneNumberPrompt recognizes phone numbers
|
||||
/// </summary>
|
||||
public class PhoneNumberPrompt : ValuePrompt
|
||||
{
|
||||
public PhoneNumberPrompt(string culture, PromptValidator<ValueResult> validator = null) :
|
||||
base(SequenceRecognizer.Instance.GetPhoneNumberModel(culture), validator)
|
||||
{
|
||||
}
|
||||
|
||||
protected PhoneNumberPrompt(IModel model, PromptValidator<ValueResult> validator = null) :
|
||||
base(model, validator)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
public static class PromptValidatorEx
|
||||
{
|
||||
/// <summary>
|
||||
/// Signature of a handler that can be passed to a prompt to provide additional validation logic
|
||||
/// or to customize the reply sent to the user when their response is invalid.
|
||||
/// </summary>
|
||||
/// <typeparam name="InT">Type of value that will recognized and passed to the validator as input</typeparam>
|
||||
/// <param name="context">Context for the current turn of conversation.</param>
|
||||
/// <param name="toValidate"></param>
|
||||
/// <returns>true or false task</returns>
|
||||
public delegate Task<bool> PromptValidator<InT>(IBotContext context, InT toValidate);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
public class RangeResult
|
||||
{
|
||||
public float Start { get; set; }
|
||||
|
||||
public float End { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RangeResult recognizes range expressions like "between 2 and 4" -> Start =2 End =4
|
||||
/// </summary>
|
||||
public class RangePrompt<T> : BasePrompt<RangeResult>
|
||||
{
|
||||
private IModel _model;
|
||||
|
||||
public RangePrompt(string culture, PromptValidator<RangeResult> validator = null)
|
||||
:base(validator)
|
||||
{
|
||||
_model = NumberRecognizer.Instance.GetNumberRangeModel(culture);
|
||||
}
|
||||
|
||||
protected RangePrompt(IModel model, PromptValidator<RangeResult> validator = null)
|
||||
:base(validator)
|
||||
{
|
||||
_model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
public override async Task<RangeResult> Recognize(IBotContext context)
|
||||
{
|
||||
BotAssert.ContextNotNull(context);
|
||||
BotAssert.ActivityNotNull(context.Request);
|
||||
if (context.Request.Type != ActivityTypes.Message)
|
||||
throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
IMessageActivity message = context.Request.AsMessageActivity();
|
||||
var results = _model.Parse(message.Text);
|
||||
if (results.Any())
|
||||
{
|
||||
var result = results.First();
|
||||
if (result.TypeName == "numberrange")
|
||||
{
|
||||
string[] values = result.Resolution["value"].ToString().Trim('(', ')').Split(',');
|
||||
RangeResult rangeResult = new RangeResult()
|
||||
{
|
||||
Text = result.Text
|
||||
};
|
||||
if (float.TryParse(values[0], out float startValue) && float.TryParse(values[1], out float endValue))
|
||||
{
|
||||
rangeResult.Start = startValue;
|
||||
rangeResult.End = endValue;
|
||||
}
|
||||
if (await Validate(context, rangeResult))
|
||||
return rangeResult;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// TemperaturePrompt recognizes temperature expressions
|
||||
/// </summary>
|
||||
public class TemperaturePrompt : NumberWithUnitPrompt
|
||||
{
|
||||
public TemperaturePrompt(string culture, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(NumberWithUnitRecognizer.Instance.GetTemperatureModel(culture), validator)
|
||||
{
|
||||
}
|
||||
|
||||
protected TemperaturePrompt(IModel model, PromptValidator<NumberWithUnit> validator = null)
|
||||
: base(model, validator)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
/// <summary>
|
||||
/// Text Prompt provides a simple mechanism to send text to a user
|
||||
/// and validate a response. The default validator passes on any
|
||||
/// non-whitespace string. That behavior is easily changed by deriving
|
||||
/// from this class and authoring custom validation behavior.
|
||||
///
|
||||
/// For simple validation changes, a PromptValidator may be passed in to the
|
||||
/// constructor. If the standard validation passes, the custom PromptValidator
|
||||
/// will be called.
|
||||
/// </summary>
|
||||
public class TextPrompt : BasePrompt<string>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a TextPrompt allowing a custom validator
|
||||
/// to be specified. The custom validator will ONLY be called if the
|
||||
/// Validate method on the class first passes.
|
||||
/// </summary>
|
||||
public TextPrompt(PromptValidator<string> validator = null)
|
||||
:base(validator)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to validate the incoming text, expected on context.Request, is
|
||||
/// valid according to the rules defined in the validation steps.
|
||||
/// </summary>
|
||||
public override async Task<string> Recognize(IBotContext context)
|
||||
{
|
||||
BotAssert.ContextNotNull(context);
|
||||
BotAssert.ActivityNotNull(context.Request);
|
||||
if (context.Request.Type != ActivityTypes.Message)
|
||||
throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
IMessageActivity message = context.Request.AsMessageActivity();
|
||||
if (await Validate(context, message.Text))
|
||||
return message.Text;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.Recognizers.Text.Number;
|
||||
using Microsoft.Recognizers.Text.NumberWithUnit;
|
||||
using static Microsoft.Bot.Builder.Prompts.PromptValidatorEx;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts
|
||||
{
|
||||
public class ValueResult
|
||||
{
|
||||
public ValueResult() { }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CurrencyPrompt recognizes currency expressions as float type
|
||||
/// </summary>
|
||||
public class ValuePrompt : BasePrompt<ValueResult>
|
||||
{
|
||||
private IModel _model;
|
||||
|
||||
|
||||
protected ValuePrompt(IModel model, PromptValidator<ValueResult> validator = null) : base(validator)
|
||||
{
|
||||
_model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to validate the incoming text, expected on context.Request, is
|
||||
/// valid according to the rules defined in the validation steps.
|
||||
/// </summary>
|
||||
public override async Task<ValueResult> Recognize(IBotContext context)
|
||||
{
|
||||
BotAssert.ContextNotNull(context);
|
||||
BotAssert.ActivityNotNull(context.Request);
|
||||
if (context.Request.Type != ActivityTypes.Message)
|
||||
throw new InvalidOperationException("No Message to Recognize");
|
||||
|
||||
IMessageActivity message = context.Request.AsMessageActivity();
|
||||
var results = _model.Parse(message.Text);
|
||||
if (results.Any())
|
||||
{
|
||||
var result = results.First();
|
||||
ValueResult value = new ValueResult()
|
||||
{
|
||||
Text = result.Text,
|
||||
Value = (string)result.Resolution["value"]
|
||||
};
|
||||
|
||||
if (await Validate(context, value))
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Ai\Microsoft.Bot.Builder.Ai.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Connector\Microsoft.Bot.Connector.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Age Prompts")]
|
||||
public class AgePromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task AgePrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new AgePrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsNotNull(result.Unit);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(float));
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("I am 30 years old")
|
||||
.AssertReply("30 Year")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AgePrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new AgePrompt(Culture.English, async (ctx, result) => result.Value > 10);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send(" it is 1 year old")
|
||||
.AssertReply("null")
|
||||
.Send(" it is 15 year old")
|
||||
.AssertReply("15 Year")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Currency Prompts")]
|
||||
public class CurrencyPromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task CurrencyPrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new CurrencyPrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsNotNull(result.Unit);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(float));
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send(" I would like $45.50")
|
||||
.AssertReply("45.5 Dollar")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CurrencyPrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new CurrencyPrompt(Culture.English, async (ctx, result) => result.Value > 10);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send(" I would like $1.00")
|
||||
.AssertReply("null")
|
||||
.Send(" I would like $45.50")
|
||||
.AssertReply("45.5 Dollar")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Dimension Prompts")]
|
||||
public class DimensionPromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task DimensionPrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new DimensionPrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsNotNull(result.Unit);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(float));
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("I am 4 feet wide")
|
||||
.AssertReply("4 Foot")
|
||||
.Send(" it is 1 foot wide")
|
||||
.AssertReply("1 Foot")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task DimensionPrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new DimensionPrompt(Culture.English, async (ctx, result) => result.Value > 10);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send(" it is 1 foot wide")
|
||||
.AssertReply("null")
|
||||
.Send(" it is 40 feet wide")
|
||||
.AssertReply("40 Foot")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<NoWarn>1701;1702;1705;1998</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.DateTime" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.Number" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.NumberWithUnit" Version="1.0.0.36" />
|
||||
<PackageReference Include="Microsoft.Recognizers.Text.Sequence" Version="1.0.0.36" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Prompts\Microsoft.Bot.Builder.Prompts.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
public class TestState : StoreItem
|
||||
{
|
||||
public bool InPrompt { get; set; } = false;
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Number Prompts")]
|
||||
public class NumberPromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task NumberPrompt_Float()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new NumberPrompt<float>(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(float));
|
||||
context.Reply(result.Value.ToString());
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("asdf df 123")
|
||||
.AssertReply("123")
|
||||
.Send(" asdf asd 123.43 adsfsdf ")
|
||||
.AssertReply("123.43")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task NumberPrompt_Int()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new NumberPrompt<int>(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsInstanceOfType(result.Value, typeof(int));
|
||||
Assert.IsNotNull(result.Text);
|
||||
context.Reply(result.Value.ToString());
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("asdf df 123")
|
||||
.AssertReply("123")
|
||||
.Send(" asdf asd 123.43 adsfsdf ")
|
||||
.AssertReply("null")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task NumberPrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new NumberPrompt<int>(Culture.English, async (ctx, result) => result.Value < 100);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsInstanceOfType(result.Value, typeof(int));
|
||||
Assert.IsTrue(result.Value < 100);
|
||||
Assert.IsNotNull(result.Text);
|
||||
context.Reply(result.Value.ToString());
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("asdf df 123")
|
||||
.AssertReply("null")
|
||||
.Send(" asdf asd 12 adsfsdf ")
|
||||
.AssertReply("12")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Ordinal Prompts")]
|
||||
public class OrdinalPromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task OrdinalPrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new OrdinalPrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(int));
|
||||
context.Reply(result.Value.ToString());
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send(" the second one please ")
|
||||
.AssertReply("2")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task OrdinalPrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new OrdinalPrompt(Culture.English, async (ctx, result) => result.Value > 2);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsInstanceOfType(result.Value, typeof(int));
|
||||
Assert.IsTrue(result.Value < 100);
|
||||
Assert.IsNotNull(result.Text);
|
||||
context.Reply(result.Value.ToString());
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("the first one")
|
||||
.AssertReply("null")
|
||||
.Send("the third one")
|
||||
.AssertReply("3")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Percentage Prompts")]
|
||||
public class PercentagePromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task PercentagePrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new PercentagePrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(float));
|
||||
context.Reply($"{result.Value}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("give me 5")
|
||||
.AssertReply("null")
|
||||
.Send(" I would like forty five percent")
|
||||
.AssertReply("45")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task PercentagePrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new PercentagePrompt(Culture.English, async (ctx, result) => result.Value > 10);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
context.Reply($"{result.Value}");
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send(" I would like 5%")
|
||||
.AssertReply("null")
|
||||
.Send(" I would like 30%")
|
||||
.AssertReply("30")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("PhoneNumber Prompts")]
|
||||
public class PhoneNumberPromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task PhoneNumberPrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new PhoneNumberPrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsNotNull(result.Value);
|
||||
context.Reply($"{result.Value}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("123 123123sdfsdf 123 1asdf23123 123 ")
|
||||
.AssertReply("null")
|
||||
.Send("123-456-7890")
|
||||
.AssertReply("123-456-7890")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task PhoneNumberPrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new PhoneNumberPrompt(Culture.English, async (ctx, result) => result.Value.StartsWith("123"));
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
context.Reply($"{result.Value}");
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("888-123-4567")
|
||||
.AssertReply("null")
|
||||
.Send("123-123-4567")
|
||||
.AssertReply("123-123-4567")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Range Prompts")]
|
||||
public class RangePromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task RangePrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new RangePrompt<int>(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Start > 0);
|
||||
Assert.IsTrue(result.End > result.Start);
|
||||
Assert.IsNotNull(result.Text);
|
||||
context.Reply($"{result.Start}-{result.End}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send("give me 5 10")
|
||||
.AssertReply("null")
|
||||
.Send(" give me between 5 and 10")
|
||||
.AssertReply("5-10")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task RangePrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new RangePrompt<int>(Culture.English, async (c, result) => result.End - result.Start > 5);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Start > 0);
|
||||
Assert.IsTrue(result.End > result.Start);
|
||||
Assert.IsNotNull(result.Text);
|
||||
context.Reply($"{result.Start}-{result.End}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("give me between 1 and 4")
|
||||
.AssertReply("null")
|
||||
.Send(" give me between 1 and 10")
|
||||
.AssertReply("1-10")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.Recognizers.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Temperature Prompts")]
|
||||
public class TemperaturePromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task TemperaturePrompt_Test()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var testPrompt = new TemperaturePrompt(Culture.English);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await testPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await testPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
{
|
||||
Assert.IsTrue(result.Value != float.NaN);
|
||||
Assert.IsNotNull(result.Text);
|
||||
Assert.IsNotNull(result.Unit);
|
||||
Assert.IsInstanceOfType(result.Value, typeof(float));
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send("test test test")
|
||||
.AssertReply("null")
|
||||
.Send(" it is 43 degrees")
|
||||
.AssertReply("43 Degree")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task TemperaturePrompt_Validator()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<TestState>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, async (context) =>
|
||||
{
|
||||
var state = ConversationState<TestState>.Get(context);
|
||||
var numberPrompt = new TemperaturePrompt(Culture.English, async (ctx, result) => result.Value > 10);
|
||||
if (!state.InPrompt)
|
||||
{
|
||||
state.InPrompt = true;
|
||||
await numberPrompt.Prompt(context, "Gimme:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await numberPrompt.Recognize(context);
|
||||
if (result == null)
|
||||
context.Reply("null");
|
||||
else
|
||||
context.Reply($"{result.Value} {result.Unit}");
|
||||
}
|
||||
})
|
||||
.Send("hello")
|
||||
.AssertReply("Gimme:")
|
||||
.Send(" it is 10 degrees")
|
||||
.AssertReply("null")
|
||||
.Send(" it is 43 degrees")
|
||||
.AssertReply("43 Degree")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Bot.Builder.Adapters;
|
||||
using Microsoft.Bot.Builder.Middleware;
|
||||
using Microsoft.Bot.Builder.Storage;
|
||||
using Microsoft.Bot.Schema;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Microsoft.Bot.Builder.Prompts.Tests
|
||||
{
|
||||
[TestClass]
|
||||
[TestCategory("Prompts")]
|
||||
[TestCategory("Text Prompts")]
|
||||
public class TextPromptTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task SimpleRecognize()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<StoreItem>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, MyTestPrompt)
|
||||
.Send("hello")
|
||||
.AssertReply("Your Name:")
|
||||
.Send("test test test")
|
||||
.AssertReply("Passed")
|
||||
.AssertReply("test test test")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MinLenghtViaCustomValidator_Fail()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<StoreItem>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, LengthCheckPromptTest)
|
||||
.Send("hello")
|
||||
.AssertReply("Your Name:")
|
||||
.Send("1")
|
||||
.AssertReply("Failed")
|
||||
.StartTest();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task MinLenghtViaCustomValidator_Pass()
|
||||
{
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new ConversationState<StoreItem>(new MemoryStorage()));
|
||||
|
||||
await new TestFlow(adapter, LengthCheckPromptTest)
|
||||
.Send("hello")
|
||||
.AssertReply("Your Name:")
|
||||
.Send("123456")
|
||||
.AssertReply("Passed")
|
||||
.AssertReply("123456")
|
||||
.StartTest();
|
||||
}
|
||||
|
||||
|
||||
public async Task MyTestPrompt(IBotContext context)
|
||||
{
|
||||
dynamic conversationState = ConversationState<StoreItem>.Get(context);
|
||||
TextPrompt askForName = new TextPrompt();
|
||||
if (conversationState["topic"] != "textPromptTest")
|
||||
{
|
||||
conversationState["topic"] = "textPromptTest";
|
||||
await askForName.Prompt(context, "Your Name:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var text = await askForName.Recognize(context);
|
||||
if (text != null)
|
||||
{
|
||||
context.Reply("Passed");
|
||||
context.Reply(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Reply("Failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LengthCheckPromptTest(IBotContext context)
|
||||
{
|
||||
dynamic conversationState = ConversationState<StoreItem>.Get(context);
|
||||
TextPrompt askForName = new TextPrompt(MinLengthValidator);
|
||||
if (conversationState["topic"] != "textPromptTest")
|
||||
{
|
||||
conversationState["topic"] = "textPromptTest";
|
||||
await askForName.Prompt(context, "Your Name:");
|
||||
}
|
||||
else
|
||||
{
|
||||
var text = await askForName.Recognize(context);
|
||||
if (text != null)
|
||||
{
|
||||
context.Reply("Passed");
|
||||
context.Reply(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Reply("Failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> MinLengthValidator(IBotContext context, string toValidate)
|
||||
{
|
||||
return toValidate.Length > 5;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -19,6 +18,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder.Core\Microsoft.Bot.Builder.Core.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Builder\Microsoft.Bot.Builder.csproj" />
|
||||
<ProjectReference Include="..\..\libraries\Microsoft.Bot.Schema\Microsoft.Bot.Schema.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче