diff --git a/libraries/botbuilder-dialogs/src/prompts/activityPrompt.ts b/libraries/botbuilder-dialogs/src/prompts/activityPrompt.ts index 33d3371e68..b420e0f453 100644 --- a/libraries/botbuilder-dialogs/src/prompts/activityPrompt.ts +++ b/libraries/botbuilder-dialogs/src/prompts/activityPrompt.ts @@ -5,7 +5,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ -import { Activity, InputHints, TurnContext } from 'botbuilder-core'; +import { Activity, InputHints, TurnContext, ActivityTypes } from 'botbuilder-core'; import { Dialog, DialogInstance, DialogReason, DialogTurnResult } from '../dialog'; import { DialogContext } from '../dialogContext'; import { PromptOptions, PromptRecognizerResult, PromptValidator } from './prompt'; @@ -45,7 +45,7 @@ export abstract class ActivityPrompt extends Dialog { state.state = {}; // Send initial prompt - await this.onPrompt(dc.context, state.state, state.options); + await this.onPrompt(dc.context, state.state, state.options, false); return Dialog.EndOfTurn; } @@ -69,6 +69,10 @@ export abstract class ActivityPrompt extends Dialog { if (isValid) { return await dc.endDialog(recognized.value); } else { + if (dc.context.activity.type === ActivityTypes.Message && !dc.context.responded) { + await this.onPrompt(dc.context, state.state, state.options, true); + } + return Dialog.EndOfTurn; } } @@ -86,11 +90,13 @@ export abstract class ActivityPrompt extends Dialog { public async repromptDialog(context: TurnContext, instance: DialogInstance): Promise { const state: ActivityPromptState = instance.state as ActivityPromptState; - await this.onPrompt(context, state.state, state.options); + await this.onPrompt(context, state.state, state.options, true); } - protected async onPrompt(context: TurnContext, state: object, options: PromptOptions): Promise { - if (options.prompt) { + protected async onPrompt(context: TurnContext, state: object, options: PromptOptions, isRetry: boolean): Promise { + if (isRetry && options.retryPrompt) { + await context.sendActivity(options.retryPrompt, undefined, InputHints.ExpectingInput); + } else if (options.prompt) { await context.sendActivity(options.prompt, undefined, InputHints.ExpectingInput); } } diff --git a/libraries/botbuilder-dialogs/tests/activityPrompt.test.js b/libraries/botbuilder-dialogs/tests/activityPrompt.test.js index c7bb7b6ccf..d10e3eee80 100644 --- a/libraries/botbuilder-dialogs/tests/activityPrompt.test.js +++ b/libraries/botbuilder-dialogs/tests/activityPrompt.test.js @@ -47,7 +47,7 @@ describe('ActivityPrompt', function () { .assertReply('You said test'); }); - it('should return Dialog.EndOfTurn if validator returned false.', async function () { + it('should re-prompt with original prompt if validator returned false.', async function () { const adapter = new TestAdapter(async turnContext => { const dc = await dialogs.createContext(turnContext); @@ -57,9 +57,6 @@ describe('ActivityPrompt', function () { } else if (results.status === DialogTurnStatus.complete) { const reply = results.result.text; await turnContext.sendActivity(`You said ${reply}`); - } else if (results.status === DialogTurnStatus.waiting) { - // This status is reached if the ActivityPrompt fails the validation process. - await turnContext.sendActivity('Test complete.'); } await convoState.saveChanges(turnContext); }); @@ -76,7 +73,36 @@ describe('ActivityPrompt', function () { await adapter.send('Hello') .assertReply('Please send an activity.') .send('test') - .assertReply('Test complete.'); + .assertReply('Please send an activity.'); + }); + + it('should re-prompt with custom retyrPrompt if validator returned false.', async function () { + const adapter = new TestAdapter(async turnContext => { + const dc = await dialogs.createContext(turnContext); + + const results = await dc.continueDialog(); + if (results.status === DialogTurnStatus.empty) { + await dc.prompt('prompt', { prompt: 'Please send activity.', retryPrompt: 'Activity not received.' }); + } else if (results.status === DialogTurnStatus.complete) { + const reply = results.result.text; + await turnContext.sendActivity(`You said ${reply}`); + } + await convoState.saveChanges(turnContext); + }); + const convoState = new ConversationState(new MemoryStorage()); + + const dialogState = convoState.createProperty('dialogState'); + const dialogs = new DialogSet(dialogState); + dialogs.add(new SimpleActivityPrompt('prompt', async prompt => { + assert(prompt, `validator missing PromptValidatorContext.`); + assert(typeof prompt.recognized.value === 'object', 'recognized.value was not an object.'); + return false; + })); + + await adapter.send('Hello') + .assertReply('Please send activity.') + .send('test') + .assertReply('Activity not received.'); }); it('should have resumeDialog() prompt user and return Dialog.EndOfTurn.', async function () {