Skip to content

Commit

Permalink
Merge pull request #654 from Microsoft/johtaylo/confirm-fix
Browse files Browse the repository at this point in the history
fix confirm prompt when invalid locale used with number selection
  • Loading branch information
johnataylor authored Nov 21, 2018
2 parents b126cea + b7d6bde commit ce72c8e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 11 deletions.
26 changes: 15 additions & 11 deletions libraries/botbuilder-dialogs/src/prompts/confirmPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,13 @@ export class ConfirmPrompt extends Prompt<boolean> {
}

protected async onPrompt(context: TurnContext, state: any, options: PromptOptions, isRetry: boolean): Promise<void> {
// Determine locale
let locale: string = context.activity.locale || this.defaultLocale;
if (!locale || !ConfirmPrompt.defaultChoiceOptions.hasOwnProperty(locale)) {
locale = 'en-us';
}

// Format prompt to send
let prompt: Partial<Activity>;
const channelId: string = context.activity.channelId;
const choiceOptions: ChoiceFactoryOptions = this.choiceOptions || ConfirmPrompt.defaultChoiceOptions[locale];
const choices: any[] = this.confirmChoices || ConfirmPrompt.defaultConfirmChoices[locale];
const culture: string = this.determineCulture(context.activity);
const choiceOptions: ChoiceFactoryOptions = this.choiceOptions || ConfirmPrompt.defaultChoiceOptions[culture];
const choices: any[] = this.confirmChoices || ConfirmPrompt.defaultConfirmChoices[culture];
if (isRetry && options.retryPrompt) {
prompt = this.appendChoices(options.retryPrompt, channelId, choices, this.style, choiceOptions);
} else {
Expand All @@ -108,17 +104,17 @@ export class ConfirmPrompt extends Prompt<boolean> {
const result: PromptRecognizerResult<boolean> = { succeeded: false };
const activity: Activity = context.activity;
const utterance: string = activity.text;
const locale: string = activity.locale || this.defaultLocale || 'en-us';
const results: any = Recognizers.recognizeBoolean(utterance, locale);
const culture: string = this.determineCulture(context.activity);
const results: any = Recognizers.recognizeBoolean(utterance, culture);
if (results.length > 0 && results[0].resolution) {
result.succeeded = true;
result.value = results[0].resolution.value;
} else {
// If the prompt text was sent to the user with numbers, the prompt should recognize number choices.
const choiceOptions = this.choiceOptions || ConfirmPrompt.defaultChoiceOptions[locale];
const choiceOptions = this.choiceOptions || ConfirmPrompt.defaultChoiceOptions[culture];

if (typeof choiceOptions.includeNumbers !== 'boolean' || choiceOptions.includeNumbers) {
const confirmChoices = this.confirmChoices || ConfirmPrompt.defaultConfirmChoices[locale];
const confirmChoices = this.confirmChoices || ConfirmPrompt.defaultConfirmChoices[culture];
const choices = [confirmChoices[0], confirmChoices[1]];
const secondOrMoreAttemptResults = recognizeChoices(utterance, choices);
if (secondOrMoreAttemptResults.length > 0) {
Expand All @@ -130,4 +126,12 @@ export class ConfirmPrompt extends Prompt<boolean> {

return result;
}

private determineCulture(activity: Activity): string {
let culture: string = activity.locale || this.defaultLocale;
if (!culture || !ConfirmPrompt.defaultChoiceOptions.hasOwnProperty(culture)) {
culture = 'en-us';
}
return culture;
}
}
68 changes: 68 additions & 0 deletions libraries/botbuilder-dialogs/tests/confirmPrompt.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,74 @@ describe('ConfirmPrompt', function () {
.assertReply(`The result found is 'true'.`);
});

it('should recogize valid number and default to en if locale invalid string.', async function () {
const adapter = new TestAdapter(async (turnContext) => {

turnContext.activity.locale = 'invalid-locale';

const dc = await dialogs.createContext(turnContext);

const results = await dc.continueDialog();
if (results.status === DialogTurnStatus.empty) {
await dc.prompt('prompt', {
prompt: { text: 'Please confirm.', type: ActivityTypes.Message },
retryPrompt: { text: 'Please confirm, say "yes" or "no" or something like that.', type: ActivityTypes.Message }
});
} else if (results.status === DialogTurnStatus.complete) {
await turnContext.sendActivity(`The result found is '${ results.result }'.`);
}
await convoState.saveChanges(turnContext);
});

const convoState = new ConversationState(new MemoryStorage());

const dialogState = convoState.createProperty('dialogState');
const dialogs = new DialogSet(dialogState);
const prompt = new ConfirmPrompt('prompt');
prompt.choiceOptions = { includeNumbers: true };
dialogs.add(prompt);

await adapter.send('Hello')
.assertReply('Please confirm. (1) Yes or (2) No')
.send('lala')
.assertReply('Please confirm, say "yes" or "no" or something like that. (1) Yes or (2) No')
.send('1')
.assertReply(`The result found is 'true'.`);
});

it('should recogize valid number and default to en if defaultLocale invalid string.', 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: { text: 'Please confirm.', type: ActivityTypes.Message },
retryPrompt: { text: 'Please confirm, say "yes" or "no" or something like that.', type: ActivityTypes.Message }
});
} else if (results.status === DialogTurnStatus.complete) {
await turnContext.sendActivity(`The result found is '${ results.result }'.`);
}
await convoState.saveChanges(turnContext);
});

const convoState = new ConversationState(new MemoryStorage());

const dialogState = convoState.createProperty('dialogState');
const dialogs = new DialogSet(dialogState);
const prompt = new ConfirmPrompt('prompt', undefined, 'invalid-locale');
prompt.choiceOptions = { includeNumbers: true };
dialogs.add(prompt);

await adapter.send('Hello')
.assertReply('Please confirm. (1) Yes or (2) No')
.send('lala')
.assertReply('Please confirm, say "yes" or "no" or something like that. (1) Yes or (2) No')
.send('1')
.assertReply(`The result found is 'true'.`);
});

it('should not recognize invalid number when choiceOptions.includeNumbers is true.', async function () {
const adapter = new TestAdapter(async (turnContext) => {
const dc = await dialogs.createContext(turnContext);
Expand Down

0 comments on commit ce72c8e

Please sign in to comment.