From 989aca53514d376fdd373ba85044cad2f6d89a7a Mon Sep 17 00:00:00 2001 From: Michael Richardson <40401643+mdrichardson@users.noreply.github.com> Date: Wed, 24 Mar 2021 11:01:06 -0700 Subject: [PATCH] Replace done w/ async part 4 (#3427) * convert done to async tests * no-op formatting fixes * use assert.rejects Co-authored-by: Michael Richardson Co-authored-by: Josh Gummersall <1235378+joshgummersall@users.noreply.github.com> --- .../tests/attachmentPrompt.test.js | 131 ++--- .../tests/choicePrompt.test.js | 377 +++++++------ .../tests/choices_recognizers.test.js | 80 ++- .../tests/choices_tokenizer.test.js | 30 +- .../tests/componentDialog.test.js | 256 ++++----- .../tests/dialogContext.test.js | 495 +++++++++--------- .../tests/dialogHelper.test.js | 76 ++- .../tests/dialogSet.test.js | 33 +- .../tests/memory_pathResolvers.test.js | 38 +- 9 files changed, 779 insertions(+), 737 deletions(-) diff --git a/libraries/botbuilder-dialogs/tests/attachmentPrompt.test.js b/libraries/botbuilder-dialogs/tests/attachmentPrompt.test.js index a67952e7ff..34bb89dcc1 100644 --- a/libraries/botbuilder-dialogs/tests/attachmentPrompt.test.js +++ b/libraries/botbuilder-dialogs/tests/attachmentPrompt.test.js @@ -1,11 +1,15 @@ const { ConversationState, MemoryStorage, TestAdapter } = require('botbuilder-core'); -const { AttachmentPrompt, DialogSet, DialogTurnStatus } = require('../'); +const { AttachmentPrompt, DialogSet, DialogTurnStatus } = require('../'); const assert = require('assert'); -const answerMessage = { text: `here you go`, type: 'message', attachments: [{ contentType: 'test', content: 'test1' }] }; +const answerMessage = { + text: `here you go`, + type: 'message', + attachments: [{ contentType: 'test', content: 'test1' }], +}; const invalidMessage = { text: `what?`, type: 'message' }; -describe('AttachmentPrompt', function() { +describe('AttachmentPrompt', function () { this.timeout(5000); it('should call AttachmentPrompt using dc.prompt().', async function () { @@ -24,7 +28,7 @@ describe('AttachmentPrompt', function() { await convoState.saveChanges(turnContext); }); - // Create new ConversationState with MemoryStorage + // Create new ConversationState with MemoryStorage const convoState = new ConversationState(new MemoryStorage()); // adapter.use(convoState); @@ -32,15 +36,16 @@ describe('AttachmentPrompt', function() { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); dialogs.add(new AttachmentPrompt('prompt')); - - await adapter.send('Hello') - .assertReply('Please send an attachment.') - .send(answerMessage) - .assertReply('test1') - .startTest(); + + await adapter + .send('Hello') + .assertReply('Please send an attachment.') + .send(answerMessage) + .assertReply('test1') + .startTest(); }); - it('should call AttachmentPrompt with custom validator.', function (done) { + it('should call AttachmentPrompt with custom validator.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -59,20 +64,22 @@ describe('AttachmentPrompt', function() { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new AttachmentPrompt('prompt', async (prompt) => { - assert(prompt); - return prompt.recognized.succeeded; - })); - - adapter.send('Hello') - .assertReply('Please send an attachment.') - .send(answerMessage) - .assertReply('test1') - .startTest(); - done(); + dialogs.add( + new AttachmentPrompt('prompt', async (prompt) => { + assert(prompt); + return prompt.recognized.succeeded; + }) + ); + + await adapter + .send('Hello') + .assertReply('Please send an attachment.') + .send(answerMessage) + .assertReply('test1') + .startTest(); }); - it('should send custom retryPrompt.', function (done) { + it('should send custom retryPrompt.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -91,22 +98,24 @@ describe('AttachmentPrompt', function() { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new AttachmentPrompt('prompt', async (prompt) => { - assert(prompt); - return prompt.recognized.succeeded; - })); - - adapter.send('Hello') - .assertReply('Please send an attachment.') - .send(invalidMessage) - .assertReply('Please try again.') - .send(answerMessage) - .assertReply('test1') - .startTest(); - done(); + dialogs.add( + new AttachmentPrompt('prompt', async (prompt) => { + assert(prompt); + return prompt.recognized.succeeded; + }) + ); + + await adapter + .send('Hello') + .assertReply('Please send an attachment.') + .send(invalidMessage) + .assertReply('Please try again.') + .send(answerMessage) + .assertReply('test1') + .startTest(); }); - it('should send ignore retryPrompt if validator replies.', function (done) { + it('should send ignore retryPrompt if validator replies.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -125,26 +134,28 @@ describe('AttachmentPrompt', function() { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new AttachmentPrompt('prompt', async (prompt) => { - assert(prompt); - - if (!prompt.recognized.succeeded) { - await prompt.context.sendActivity('Bad input.'); - } - return prompt.recognized.succeeded; - })); - - adapter.send('Hello') - .assertReply('Please send an attachment.') - .send(invalidMessage) - .assertReply('Bad input.') - .send(answerMessage) - .assertReply('test1') - .startTest(); - done(); + dialogs.add( + new AttachmentPrompt('prompt', async (prompt) => { + assert(prompt); + + if (!prompt.recognized.succeeded) { + await prompt.context.sendActivity('Bad input.'); + } + return prompt.recognized.succeeded; + }) + ); + + await adapter + .send('Hello') + .assertReply('Please send an attachment.') + .send(invalidMessage) + .assertReply('Bad input.') + .send(answerMessage) + .assertReply('test1') + .startTest(); }); - it('should not send any retryPrompt if no prompt is specified.', function (done) { + it('should not send any retryPrompt if no prompt is specified.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -164,13 +175,7 @@ describe('AttachmentPrompt', function() { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); dialogs.add(new AttachmentPrompt('prompt')); - - adapter.send('Hello') - .send('what?') - .send(answerMessage) - .assertReply('test1') - .startTest(); - done(); - }); + await adapter.send('Hello').send('what?').send(answerMessage).assertReply('test1').startTest(); + }); }); diff --git a/libraries/botbuilder-dialogs/tests/choicePrompt.test.js b/libraries/botbuilder-dialogs/tests/choicePrompt.test.js index ad8ad2df8f..208fa43e66 100644 --- a/libraries/botbuilder-dialogs/tests/choicePrompt.test.js +++ b/libraries/botbuilder-dialogs/tests/choicePrompt.test.js @@ -37,7 +37,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(answerMessage) .assertReply('red') @@ -66,7 +67,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(answerMessage) .assertReply('red') @@ -97,7 +99,8 @@ describe('ChoicePrompt', function () { choicePrompt.style = ListStyle.none; dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(invalidMessage) .assertReply('Please choose a color.') @@ -112,9 +115,13 @@ describe('ChoicePrompt', function () { const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { - await dc.prompt('prompt', 'Please choose a color.', stringChoices.map(choice => { - return { value: choice, action: {} } - })); + await dc.prompt( + 'prompt', + 'Please choose a color.', + stringChoices.map((choice) => { + return { value: choice, action: {} }; + }) + ); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; await turnContext.sendActivity(selectedChoice.value); @@ -132,7 +139,8 @@ describe('ChoicePrompt', function () { choicePrompt.style = ListStyle.suggestedAction; dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(invalidMessage) .assertReply('Please choose a color.') @@ -150,7 +158,7 @@ describe('ChoicePrompt', function () { await dc.prompt('prompt', { prompt: 'Please choose a color.', choices: stringChoices, - style: ListStyle.none + style: ListStyle.none, }); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; @@ -168,7 +176,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(answerMessage) .assertReply('red') @@ -181,7 +190,11 @@ describe('ChoicePrompt', function () { const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { - await dc.prompt('prompt', { prompt: 'Please choose a color.', retryPrompt: 'Please choose red, blue, or green.', choices: stringChoices }); + await dc.prompt('prompt', { + prompt: 'Please choose a color.', + retryPrompt: 'Please choose red, blue, or green.', + choices: stringChoices, + }); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; await turnContext.sendActivity(selectedChoice.value); @@ -196,7 +209,8 @@ describe('ChoicePrompt', function () { choicePrompt.style = ListStyle.none; dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(invalidMessage) .assertReply('Please choose red, blue, or green.') @@ -211,7 +225,11 @@ describe('ChoicePrompt', function () { const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { - await dc.prompt('prompt', { prompt: 'Please choose a color.', retryPrompt: 'Please choose red, blue, or green.', choices: stringChoices }); + await dc.prompt('prompt', { + prompt: 'Please choose a color.', + retryPrompt: 'Please choose red, blue, or green.', + choices: stringChoices, + }); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; await turnContext.sendActivity(selectedChoice.value); @@ -232,7 +250,8 @@ describe('ChoicePrompt', function () { choicePrompt.style = ListStyle.none; dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(invalidMessage) .assertReply('bad input.') @@ -258,16 +277,21 @@ describe('ChoicePrompt', function () { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - const choicePrompt = new ChoicePrompt('prompt', async (prompt) => { - assert(prompt); - if (!prompt.recognized.succeeded) { - await prompt.context.sendActivity('bad input.'); - } - return prompt.recognized.succeeded; - }, 'es-es'); + const choicePrompt = new ChoicePrompt( + 'prompt', + async (prompt) => { + assert(prompt); + if (!prompt.recognized.succeeded) { + await prompt.context.sendActivity('bad input.'); + } + return prompt.recognized.succeeded; + }, + 'es-es' + ); dialogs.add(choicePrompt); - await adapter.send({ text: 'Hello', type: ActivityTypes.Message, locale: undefined }) + await adapter + .send({ text: 'Hello', type: ActivityTypes.Message, locale: undefined }) .assertReply((activity) => { assert('Please choose a color. (1) red, (2) green, o (3) blue'); }) @@ -304,7 +328,8 @@ describe('ChoicePrompt', function () { }); dialogs.add(choicePrompt); - await adapter.send({ text: 'Hello', type: ActivityTypes.Message, locale: 'es-es' }) + await adapter + .send({ text: 'Hello', type: ActivityTypes.Message, locale: 'es-es' }) .assertReply('Please choose a color. (1) red, (2) green, o (3) blue') .send(answerMessage) .assertReply('red') @@ -328,16 +353,21 @@ describe('ChoicePrompt', function () { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - const choicePrompt = new ChoicePrompt('prompt', async (prompt) => { - assert(prompt); - if (!prompt.recognized.succeeded) { - await prompt.context.sendActivity('bad input.'); - } - return prompt.recognized.succeeded; - }, 'es-es'); + const choicePrompt = new ChoicePrompt( + 'prompt', + async (prompt) => { + assert(prompt); + if (!prompt.recognized.succeeded) { + await prompt.context.sendActivity('bad input.'); + } + return prompt.recognized.succeeded; + }, + 'es-es' + ); dialogs.add(choicePrompt); - await adapter.send({ text: 'Hello', type: ActivityTypes.Message, locale: 'en-us' }) + await adapter + .send({ text: 'Hello', type: ActivityTypes.Message, locale: 'en-us' }) .assertReply('Please choose a color. (1) red, (2) green, or (3) blue') .send(answerMessage) .assertReply('red') @@ -345,20 +375,10 @@ describe('ChoicePrompt', function () { }); it('should recognize locale variations of correct locales', async function () { - const locales = [ - 'es-es', - 'nl-nl', - 'en-us', - 'fr-fr', - 'de-de', - 'it-it', - 'ja-jp', - 'pt-br', - 'zh-cn' - ]; + const locales = ['es-es', 'nl-nl', 'en-us', 'fr-fr', 'de-de', 'it-it', 'ja-jp', 'pt-br', 'zh-cn']; // es-ES const capEnding = (locale) => { - return `${ locale.split('-')[0] }-${ locale.split('-')[1].toUpperCase() }`; + return `${locale.split('-')[0]}-${locale.split('-')[1].toUpperCase()}`; }; // es-Es const titleEnding = (locale) => { @@ -381,20 +401,72 @@ describe('ChoicePrompt', function () { capEnding(locale), titleEnding(locale), capTwoLetter(locale), - lowerTwoLetter(locale) + lowerTwoLetter(locale), ]; return obj; }, {}); // Test each valid locale - await Promise.all(Object.keys(localeTests).map(async (validLocale) => { - // Hold the correct answer from when a valid locale is used - let expectedAnswer; - // Test each of the test locales - await Promise.all(localeTests[validLocale].map(async (testLocale) => { + await Promise.all( + Object.keys(localeTests).map(async (validLocale) => { + // Hold the correct answer from when a valid locale is used + let expectedAnswer; + // Test each of the test locales + await Promise.all( + localeTests[validLocale].map(async (testLocale) => { + 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 choose a color.', choices: stringChoices }); + } else if (results.status === DialogTurnStatus.complete) { + const selectedChoice = results.result; + await turnContext.sendActivity(selectedChoice.value); + } + await convoState.saveChanges(turnContext); + }); + const convoState = new ConversationState(new MemoryStorage()); + + const dialogState = convoState.createProperty('dialogState'); + const dialogs = new DialogSet(dialogState); + const choicePrompt = new ChoicePrompt( + 'prompt', + async (prompt) => { + assert(prompt); + if (!prompt.recognized.succeeded) { + await prompt.context.sendActivity('bad input.'); + } + return prompt.recognized.succeeded; + }, + 'es-es' + ); + dialogs.add(choicePrompt); + + await adapter + .send({ text: 'Hello', type: ActivityTypes.Message, locale: testLocale }) + .assertReply((activity) => { + // if the valid locale is tested, save the answer because then we can test to see + // if the test locales produce the same answer + if (validLocale === testLocale) { + expectedAnswer = activity.text; + } + assert.strictEqual(activity.text, expectedAnswer); + }) + .startTest(); + }) + ); + }) + ); + }); + + it('should default to english locale', async function () { + const locales = [null, '', 'not-supported']; + await Promise.all( + locales.map(async (testLocale) => { 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 choose a color.', choices: stringChoices }); @@ -405,78 +477,38 @@ describe('ChoicePrompt', function () { await convoState.saveChanges(turnContext); }); const convoState = new ConversationState(new MemoryStorage()); - + const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - const choicePrompt = new ChoicePrompt('prompt', async (prompt) => { - assert(prompt); - if (!prompt.recognized.succeeded) { - await prompt.context.sendActivity('bad input.'); - } - return prompt.recognized.succeeded; - }, 'es-es'); + const choicePrompt = new ChoicePrompt( + 'prompt', + async (prompt) => { + assert(prompt); + if (!prompt.recognized.succeeded) { + await prompt.context.sendActivity('bad input.'); + } + return prompt.recognized.succeeded; + }, + null + ); dialogs.add(choicePrompt); - - await adapter.send({ text: 'Hello', type: ActivityTypes.Message, locale: testLocale }) + + await adapter + .send({ text: 'Hello', type: ActivityTypes.Message, locale: testLocale }) .assertReply((activity) => { - // if the valid locale is tested, save the answer because then we can test to see - // if the test locales produce the same answer - if (validLocale === testLocale) { - expectedAnswer = activity.text; - } - assert.strictEqual(activity.text, expectedAnswer); + const expectedChoices = ChoiceFactory.inline(stringChoices, null, null, { + inlineOr: PromptCultureModels.English.inlineOr, + inlineOrMore: PromptCultureModels.English.inlineOrMore, + inlineSeparator: PromptCultureModels.English.separator, + }).text; + assert.strictEqual(activity.text, `Please choose a color.${expectedChoices}`); }) .startTest(); - })); - })); - }); - - it('should default to english locale', async function () { - const locales = [ - null, - '', - 'not-supported' - ]; - await Promise.all(locales.map(async (testLocale) => { - 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 choose a color.', choices: stringChoices }); - } else if (results.status === DialogTurnStatus.complete) { - const selectedChoice = results.result; - await turnContext.sendActivity(selectedChoice.value); - } - await convoState.saveChanges(turnContext); - }); - const convoState = new ConversationState(new MemoryStorage()); - - const dialogState = convoState.createProperty('dialogState'); - const dialogs = new DialogSet(dialogState); - const choicePrompt = new ChoicePrompt('prompt', async (prompt) => { - assert(prompt); - if (!prompt.recognized.succeeded) { - await prompt.context.sendActivity('bad input.'); - } - return prompt.recognized.succeeded; - }, null); - dialogs.add(choicePrompt); - - await adapter.send({ text: 'Hello', type: ActivityTypes.Message, locale: testLocale }) - .assertReply((activity) => { - const expectedChoices = ChoiceFactory.inline(stringChoices, null, null, { - inlineOr: PromptCultureModels.English.inlineOr, - inlineOrMore: PromptCultureModels.English.inlineOrMore, - inlineSeparator: PromptCultureModels.English.separator, - }).text; - assert.strictEqual(activity.text, `Please choose a color.${ expectedChoices }`); - }) - .startTest(); - })); + }) + ); }); - it('should accept and recognize custom locale dict', async function() { + it('should accept and recognize custom locale dict', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -497,7 +529,7 @@ describe('ChoicePrompt', function () { locale: 'custom-custom', separator: 'customSeparator', noInLanguage: 'customNo', - yesInLanguage: 'customYes' + yesInLanguage: 'customYes', }; const customDict = { @@ -506,33 +538,39 @@ describe('ChoicePrompt', function () { inlineOrMore: culture.inlineOrMore, inlineSeparator: culture.separator, includeNumbers: true, - } + }, }; const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - const choicePrompt = new ChoicePrompt('prompt', async (prompt) => { - assert(prompt); - if (!prompt.recognized.succeeded) { - await prompt.context.sendActivity('bad input.'); - } - return prompt.recognized.succeeded; - }, culture.locale, customDict); + const choicePrompt = new ChoicePrompt( + 'prompt', + async (prompt) => { + assert(prompt); + if (!prompt.recognized.succeeded) { + await prompt.context.sendActivity('bad input.'); + } + return prompt.recognized.succeeded; + }, + culture.locale, + customDict + ); dialogs.add(choicePrompt); - await adapter.send({ text: 'Hello', type: ActivityTypes.Message, locale: culture.locale }) + await adapter + .send({ text: 'Hello', type: ActivityTypes.Message, locale: culture.locale }) .assertReply((activity) => { const expectedChoices = ChoiceFactory.inline(stringChoices, undefined, undefined, { inlineOr: culture.inlineOr, inlineOrMore: culture.inlineOrMore, - inlineSeparator: culture.separator + inlineSeparator: culture.separator, }).text; - assert.strictEqual(activity.text, `Please choose a color.${ expectedChoices }`); + assert.strictEqual(activity.text, `Please choose a color.${expectedChoices}`); }) .startTest(); }); - it('should not render choices and not blow up if choices aren\'t passed in', async function () { + it("should not render choices and not blow up if choices aren't passed in", async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -554,12 +592,10 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') - .assertReply('Please choose a color.') - .startTest(); + await adapter.send('Hello').assertReply('Please choose a color.').startTest(); }); - it('should render choices if PromptOptions & choices are passed into DialogContext.prompt()', async function() { + it('should render choices if PromptOptions & choices are passed into DialogContext.prompt()', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -581,7 +617,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color. (1) red, (2) green, or (3) blue') .send(answerMessage) .assertReply('red') @@ -610,7 +647,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(answerMessage) .assertReply('red') @@ -639,7 +677,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send('hello') .assertReply('Please choose a color.') @@ -652,11 +691,10 @@ describe('ChoicePrompt', function () { const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { - await dc.prompt('prompt', - { - prompt: { text: 'Please choose a color.', type: ActivityTypes.Message }, - choices: stringChoices - }); + await dc.prompt('prompt', { + prompt: { text: 'Please choose a color.', type: ActivityTypes.Message }, + choices: stringChoices, + }); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; await turnContext.sendActivity(selectedChoice.value); @@ -672,7 +710,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send(answerMessage) .assertReply('red') @@ -685,11 +724,10 @@ describe('ChoicePrompt', function () { const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { - await dc.prompt('prompt', - { - prompt: { text: 'Please choose a color.', type: ActivityTypes.Message }, - choices: stringChoices - }); + await dc.prompt('prompt', { + prompt: { text: 'Please choose a color.', type: ActivityTypes.Message }, + choices: stringChoices, + }); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; await turnContext.sendActivity(selectedChoice.value); @@ -705,7 +743,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color. (1) red, (2) green, or (3) blue') .send(answerMessage) .assertReply('red') @@ -718,11 +757,10 @@ describe('ChoicePrompt', function () { const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { - await dc.prompt('prompt', - { - prompt: { text: 'Please choose a color.', type: ActivityTypes.Message }, - choices: stringChoices - }); + await dc.prompt('prompt', { + prompt: { text: 'Please choose a color.', type: ActivityTypes.Message }, + choices: stringChoices, + }); } else if (results.status === DialogTurnStatus.complete) { const selectedChoice = results.result; await turnContext.sendActivity(selectedChoice.value); @@ -738,7 +776,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.\n\n 1. red\n 2. green\n 3. blue') .send(answerMessage) .assertReply('red') @@ -770,11 +809,7 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') - .assertReply('Please choose a color.') - .send('1') - .assertReply('red') - .startTest(); + await adapter.send('Hello').assertReply('Please choose a color.').send('1').assertReply('red').startTest(); }); it('should not recognize, then re-prompt without error for falsy input.', async function () { @@ -802,7 +837,8 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') + await adapter + .send('Hello') .assertReply('Please choose a color.') .send('') .assertReply('Please choose a color.') @@ -839,8 +875,9 @@ describe('ChoicePrompt', function () { dialogs.add(choicePrompt); - await adapter.send('Hello') - .assertReply(activity => { + await adapter + .send('Hello') + .assertReply((activity) => { assert(activity.attachments.length === 1); assert(activity.attachments[0].contentType === CardFactory.contentTypes.heroCard); assert(activity.attachments[0].content.text === 'Please choose a size.'); @@ -849,8 +886,8 @@ describe('ChoicePrompt', function () { .assertReply('large') .startTest(); }); - - it('should display choices on a hero card with an additional attachment', async function (done) { + + it('should display choices on a hero card with an additional attachment', async function () { const sizeChoices = ['large', 'medium', 'small']; const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); @@ -875,24 +912,22 @@ describe('ChoicePrompt', function () { choicePrompt.style = ListStyle.heroCard; const card = CardFactory.adaptiveCard({ - "type": "AdaptiveCard", - "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", - "version": "1.2", - "body": [] + type: 'AdaptiveCard', + $schema: 'http://adaptivecards.io/schemas/adaptive-card.json', + version: '1.2', + body: [], }); - const activity ={ attachments: [card], type: ActivityTypes.Message }; + const activity = { attachments: [card], type: ActivityTypes.Message }; dialogs.add(choicePrompt); - adapter.send('Hello') - .assertReply(response => { + await adapter + .send('Hello') + .assertReply((response) => { assert(response.attachments.length === 2); assert(response.attachments[0].contentType === CardFactory.contentTypes.adaptiveCard); assert(response.attachments[1].contentType === CardFactory.contentTypes.heroCard); }) .startTest(); - done(); }); - - }); diff --git a/libraries/botbuilder-dialogs/tests/choices_recognizers.test.js b/libraries/botbuilder-dialogs/tests/choices_recognizers.test.js index 528f8d5b57..a118430c2d 100644 --- a/libraries/botbuilder-dialogs/tests/choices_recognizers.test.js +++ b/libraries/botbuilder-dialogs/tests/choices_recognizers.test.js @@ -24,7 +24,10 @@ function assertChoice(result, value, index, score, synonym) { assert(resolution.index === index, `Invalid resolution.index of '${resolution.index}' for '${value}' choice.`); assert(resolution.score === score, `Invalid resolution.score of '${resolution.score}' for '${value}' choice.`); if (synonym) { - assert(resolution.synonym === synonym, `Invalid resolution.synonym of '${resolution.synonym}' for '${value}' choice.`); + assert( + resolution.synonym === synonym, + `Invalid resolution.synonym of '${resolution.synonym}' for '${value}' choice.` + ); } } @@ -35,64 +38,58 @@ function assertChoice(result, value, index, score, synonym) { const colorValues = [ { value: 'red', index: 0 }, { value: 'green', index: 1 }, - { value: 'blue', index: 2 } + { value: 'blue', index: 2 }, ]; const overlappingValues = [ { value: 'bread', index: 0 }, { value: 'bread pudding', index: 1 }, - { value: 'pudding', index: 2 } + { value: 'pudding', index: 2 }, ]; const similarValues = [ { value: 'option A', index: 0 }, { value: 'option B', index: 1 }, - { value: 'option C', index: 2 } + { value: 'option C', index: 2 }, ]; - -describe('findValues()', function() { +describe('findValues()', function () { this.timeout(5000); - - it('should find a simple value in an single word utterance.', function (done) { + + it('should find a simple value in an single word utterance.', function () { const found = findValues(`red`, colorValues); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 0, 2, 'red'); assertValue(found[0], 'red', 0, 1.0); - done(); }); - it('should find a simple value in an utterance.', function (done) { + it('should find a simple value in an utterance.', function () { const found = findValues(`the red one please.`, colorValues); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 6, 'red'); assertValue(found[0], 'red', 0, 1.0); - done(); }); - it('should find multiple values within an utterance.', function (done) { + it('should find multiple values within an utterance.', function () { const found = findValues(`the red and blue ones please.`, colorValues); assert(found.length === 2, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 6, 'red'); assertValue(found[0], 'red', 0, 1.0); assertValue(found[1], 'blue', 2, 1.0); - done(); }); - it('should find multiple values that overlap.', function (done) { + it('should find multiple values that overlap.', function () { const found = findValues(`the bread pudding and bread please.`, overlappingValues); assert(found.length === 2, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 16, 'bread pudding'); assertValue(found[0], 'bread pudding', 1, 1.0); assertValue(found[1], 'bread', 0, 1.0); - done(); }); - it('should correctly disambiguate between very similar values.', function (done) { + it('should correctly disambiguate between very similar values.', function () { const found = findValues(`option B`, similarValues, { allowPartialMatches: true }); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertValue(found[0], 'option B', 1, 1.0); - done(); }); }); @@ -103,33 +100,30 @@ describe('findValues()', function() { const colorChoices = ['red', 'green', 'blue']; const overlappingChoices = ['bread', 'bread pudding', 'pudding']; -describe('findChoices()', function() { +describe('findChoices()', function () { this.timeout(5000); - - it('should find a single choice in an utterance.', function (done) { + + it('should find a single choice in an utterance.', function () { const found = findChoices(`the red one please.`, colorChoices); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 6, 'red'); assertChoice(found[0], 'red', 0, 1.0, 'red'); - done(); }); - it('should find multiple choices within an utterance.', function (done) { + it('should find multiple choices within an utterance.', function () { const found = findChoices(`the red and blue ones please.`, colorChoices); assert(found.length === 2, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 6, 'red'); assertChoice(found[0], 'red', 0, 1.0); assertChoice(found[1], 'blue', 2, 1.0); - done(); }); - it('should find multiple choices that overlap.', function (done) { + it('should find multiple choices that overlap.', function () { const found = findChoices(`the bread pudding and bread please.`, overlappingChoices); assert(found.length === 2, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 16, 'bread pudding'); assertChoice(found[0], 'bread pudding', 1, 1.0); assertChoice(found[1], 'bread', 0, 1.0); - done(); }); }); @@ -137,72 +131,66 @@ describe('findChoices()', function() { // recognizeChoices() tests //============================================================================= -describe('recognizeChoices()', function() { +describe('recognizeChoices()', function () { this.timeout(5000); - - it('should find a choice in an utterance by name.', function (done) { + + it('should find a choice in an utterance by name.', function () { const found = recognizeChoices(`the red one please.`, colorChoices); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 6, 'red'); assertChoice(found[0], 'red', 0, 1.0, 'red'); - done(); }); - it('should find a choice in an utterance by ordinal position.', function (done) { + it('should find a choice in an utterance by ordinal position.', function () { const found = recognizeChoices(`the first one please.`, colorChoices); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 4, 8, 'first'); assertChoice(found[0], 'red', 0, 1.0); - done(); }); - it('should find multiple choices in an utterance by ordinal position.', function (done) { + it('should find multiple choices in an utterance by ordinal position.', function () { const found = recognizeChoices(`the first and third one please.`, colorChoices); assert(found.length === 2, `Invalid token count of '${found.length}' returned.`); assertChoice(found[0], 'red', 0, 1.0); assertChoice(found[1], 'blue', 2, 1.0); - done(); }); - it('should find a choice in an utterance by numerical index (as digit.)', function (done) { + it('should find a choice in an utterance by numerical index (as digit.)', function () { const found = recognizeChoices(`1`, colorChoices); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 0, 0, '1'); assertChoice(found[0], 'red', 0, 1.0); - done(); }); - it('should find a choice in an utterance by numerical index (as text.)', function (done) { + it('should find a choice in an utterance by numerical index (as text.)', function () { const found = recognizeChoices(`one`, colorChoices); assert(found.length === 1, `Invalid token count of '${found.length}' returned.`); assertResult(found[0], 0, 2, 'one'); assertChoice(found[0], 'red', 0, 1.0); - done(); }); - it('should find multiple choices in an utterance by numerical index.', function (done) { + it('should find multiple choices in an utterance by numerical index.', function () { const found = recognizeChoices(`option one and 3.`, colorChoices); assert(found.length === 2, `Invalid token count of '${found.length}' returned.`); assertChoice(found[0], 'red', 0, 1.0); assertChoice(found[1], 'blue', 2, 1.0); - done(); }); - it('should not find a choice if recognizeOrdinals option disabled.', function (done) { + it('should not find a choice if recognizeOrdinals option disabled.', function () { const found = recognizeChoices(`first`, colorChoices, { recognizeOrdinals: false }); assert(found.length === 0, `Invalid token count of '${found.length}' returned.`); - done(); }); - it('should not find a choice if recognizeNumbers option disabled.', function (done) { + it('should not find a choice if recognizeNumbers option disabled.', function () { const found = recognizeChoices(`1`, colorChoices, { recognizeNumbers: false }); assert(found.length === 0, `Invalid token count of '${found.length}' returned.`); - done(); }); - it('should not find a choice if both recognizeOrdinals and recognizeNumbers options are disabled.', function (done) { - const found = recognizeChoices(`the first and third one please.`, colorChoices, { recognizeOrdinals: false, recognizeNumbers: false }); + it('should not find a choice if both recognizeOrdinals and recognizeNumbers options are disabled.', function () { + const found = recognizeChoices(`the first and third one please.`, colorChoices, { + recognizeOrdinals: false, + recognizeNumbers: false, + }); assert(found.length === 0, `Invalid token count of '${found.length}' returned.`); - done(); }); }); diff --git a/libraries/botbuilder-dialogs/tests/choices_tokenizer.test.js b/libraries/botbuilder-dialogs/tests/choices_tokenizer.test.js index 395a14b6fd..4206829f7b 100644 --- a/libraries/botbuilder-dialogs/tests/choices_tokenizer.test.js +++ b/libraries/botbuilder-dialogs/tests/choices_tokenizer.test.js @@ -5,69 +5,65 @@ function assertToken(token, start, end, text, normalized) { assert(token.start === start, `Invalid token.start of '${token.start}' for '${text}' token.`); assert(token.end === end, `Invalid token.end of '${token.end}' for '${text}' token.`); assert(token.text === text, `Invalid token.text of '${token.text}' for '${text}' token.`); - assert(token.normalized === normalized || text, `Invalid token.normalized of '${token.normalized}' for '${text}' token.`); + assert( + token.normalized === normalized || text, + `Invalid token.normalized of '${token.normalized}' for '${text}' token.` + ); } -describe('defaultTokenizer()', function() { +describe('defaultTokenizer()', function () { this.timeout(5000); - - it('should break on spaces.', function (done) { + + it('should break on spaces.', function () { const tokens = defaultTokenizer(`how now brown cow`); assert(tokens.length === 4); assertToken(tokens[0], 0, 2, 'how'); assertToken(tokens[1], 4, 6, 'now'); assertToken(tokens[2], 8, 12, 'brown'); assertToken(tokens[3], 14, 16, 'cow'); - done(); }); - it('should break on punctuation.', function (done) { + it('should break on punctuation.', function () { const tokens = defaultTokenizer(`how-now.brown:cow?`); assert(tokens.length === 4); assertToken(tokens[0], 0, 2, 'how'); assertToken(tokens[1], 4, 6, 'now'); assertToken(tokens[2], 8, 12, 'brown'); assertToken(tokens[3], 14, 16, 'cow'); - done(); }); - it('should tokenize single character tokens.', function (done) { + it('should tokenize single character tokens.', function () { const tokens = defaultTokenizer(`a b c d`); assert(tokens.length === 4); assertToken(tokens[0], 0, 0, 'a'); assertToken(tokens[1], 2, 2, 'b'); assertToken(tokens[2], 4, 4, 'c'); assertToken(tokens[3], 6, 6, 'd'); - done(); }); - it('should return a single token.', function (done) { + it('should return a single token.', function () { const tokens = defaultTokenizer(`food`); assert(tokens.length === 1); assertToken(tokens[0], 0, 3, 'food'); - done(); }); - it('should return no tokens.', function (done) { + it('should return no tokens.', function () { const tokens = defaultTokenizer(`.?;-()`); assert(tokens.length === 0); - done(); }); - it('should return a the normalized and original text for a token.', function (done) { + it('should return a the normalized and original text for a token.', function () { const tokens = defaultTokenizer(`fOoD`); assert(tokens.length === 1); assertToken(tokens[0], 0, 3, 'fOoD', 'food'); - done(); }); - it('should break on emojis.', function (done) { + it('should break on emojis.', function () { const tokens = defaultTokenizer(`food 💥👍😀`); assert(tokens.length === 4); assertToken(tokens[0], 0, 3, 'food'); assertToken(tokens[1], 5, 6, '💥'); assertToken(tokens[2], 7, 8, '👍'); assertToken(tokens[3], 9, 10, '😀'); - done(); }); }); diff --git a/libraries/botbuilder-dialogs/tests/componentDialog.test.js b/libraries/botbuilder-dialogs/tests/componentDialog.test.js index 107482a65a..5033c5da00 100644 --- a/libraries/botbuilder-dialogs/tests/componentDialog.test.js +++ b/libraries/botbuilder-dialogs/tests/componentDialog.test.js @@ -10,24 +10,22 @@ function simpleStepContextCheck(step) { describe('ComponentDialog', function () { this.timeout(5000); - it('should set initial dialog to be first dialog added via addDialog()', (done) => { - const simpleWaterfall = new WaterfallDialog('simpleWaterfall', [ - async (step) => { } - ]); + it('should set initial dialog to be first dialog added via addDialog()', function () { + const simpleWaterfall = new WaterfallDialog('simpleWaterfall', [async (step) => {}]); - const simpleH2ofall = new WaterfallDialog('simpleH2ofall', [ - async (step) => { } - ]); + const simpleH2ofall = new WaterfallDialog('simpleH2ofall', [async (step) => {}]); const component = new ComponentDialog('component'); component.addDialog(simpleWaterfall); assert(component.initialDialogId === 'simpleWaterfall', `unexpected initialDialogId`); component.addDialog(simpleH2ofall); - assert(component.initialDialogId === 'simpleWaterfall', `unexpected change in initialDialogId, it is now ${ component.initialDialogId }`); - done(); + assert( + component.initialDialogId === 'simpleWaterfall', + `unexpected change in initialDialogId, it is now ${component.initialDialogId}` + ); }); - it('should call ComponentDialog from another DialogSet.', (done) => { + it('should call ComponentDialog from another DialogSet.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); @@ -36,7 +34,7 @@ describe('ComponentDialog', function () { simpleStepContextCheck(step); assert(step.options.foo === 'bar'); return await step.endDialog(); - } + }, ]); const component = new ComponentDialog('composite'); component.addDialog(startDialog); @@ -44,23 +42,22 @@ describe('ComponentDialog', function () { const dialogs = new DialogSet(dialogState); dialogs.add(component); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - const results = await dc.beginDialog('composite', { foo: 'bar' }); + await dc.beginDialog('composite', { foo: 'bar' }); }); - adapter.send('Hi').startTest(); - done(); + await adapter.send('Hi').startTest(); }); - it('should throw an error up if child dialog does not return DialogTurnResult on beginDialog.', (done) => { + it('should throw an error up if child dialog does not return DialogTurnResult on beginDialog.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); const startDialog = new WaterfallDialog('start', [ async (step) => { simpleStepContextCheck(step); - } + }, ]); const component = new ComponentDialog('composite'); component.addDialog(startDialog); @@ -68,19 +65,16 @@ describe('ComponentDialog', function () { const dialogs = new DialogSet(dialogState); dialogs.add(component); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - const results = await dc.beginDialog('composite') - .catch(err => { - assert(err.message === `Cannot read property 'status' of undefined`, - `unexpected Error thrown.`); - done(); - }); + await assert.rejects(async () => await dc.beginDialog('composite'), { + message: `Cannot read property 'status' of undefined`, + }); }); - adapter.send('Hi').startTest(); + await adapter.send('Hi').startTest(); }); - it('should have DialogTurnResult.status equal DialogTurnStatus.complete when endComponent() is called.', (done) => { + it('should have DialogTurnResult.status equal DialogTurnStatus.complete when endComponent() is called.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); @@ -88,7 +82,7 @@ describe('ComponentDialog', function () { async (step) => { simpleStepContextCheck(step); return { status: DialogTurnStatus.complete, result: undefined }; - } + }, ]); const component = new ComponentDialog('composite'); component.addDialog(startDialog); @@ -96,18 +90,20 @@ describe('ComponentDialog', function () { const dialogs = new DialogSet(dialogState); dialogs.add(component); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.beginDialog('composite'); - assert(results.status === DialogTurnStatus.complete, `unexpected DialogTurnStatus received: ${ results.status }`); - assert(results.result === undefined, `unexpected results.result received: ${ results.result }`); - done(); + assert( + results.status === DialogTurnStatus.complete, + `unexpected DialogTurnStatus received: ${results.status}` + ); + assert(results.result === undefined, `unexpected results.result received: ${results.result}`); }); - adapter.send('Hi').startTest(); + await adapter.send('Hi').startTest(); }); - it(`should return Dialog.EndOfTurn if the dialog's turnResult.status === 'waiting'.`, (done) => { + it(`should return Dialog.EndOfTurn if the dialog's turnResult.status === 'waiting'.`, async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); @@ -119,7 +115,7 @@ describe('ComponentDialog', function () { async (step) => { simpleStepContextCheck(step); return await step.endDialog(); - } + }, ]); const component = new ComponentDialog('composite'); component.addDialog(startDialog); @@ -127,50 +123,48 @@ describe('ComponentDialog', function () { const dialogs = new DialogSet(dialogState); dialogs.add(component); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.beginDialog('composite'); - assert(results.status === DialogTurnStatus.waiting, `unexpected DialogTurnStatus received: ${ results.status }`); - assert(results.result === undefined, `unexpected results.result received: ${ results.result }`); - done(); + assert( + results.status === DialogTurnStatus.waiting, + `unexpected DialogTurnStatus received: ${results.status}` + ); + assert(results.result === undefined, `unexpected results.result received: ${results.result}`); }); - adapter.send('Hi').startTest(); + await adapter.send('Hi').startTest(); }); - it('should return any found dialogs.', (done) => { - const simpleWaterfall = new WaterfallDialog('simpleWaterfall', [ - async (step) => { } - ]); + it('should return any found dialogs.', function () { + const simpleWaterfall = new WaterfallDialog('simpleWaterfall', [async (step) => {}]); const component = new ComponentDialog('component'); component.addDialog(simpleWaterfall); const dialog = component.findDialog('simpleWaterfall'); assert(dialog === simpleWaterfall, `unexpected dialog returned`); - done(); }); - it('should return undefined for not found dialogs.', (done) => { + it('should return undefined for not found dialogs.', function () { const component = new ComponentDialog('component'); const notADialog = component.findDialog('notADialog'); - assert(notADialog === undefined, `unexpected value returned: ${ typeof notADialog }`); - done(); + assert(notADialog === undefined, `unexpected value returned: ${typeof notADialog}`); }); - it('should continue from dc.continueDialog() and call onContinueDialog().', (done) => { + it('should continue from dc.continueDialog() and call onContinueDialog().', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); const startDialog = new WaterfallDialog('start', [ - async step => { + async (step) => { simpleStepContextCheck(step); await step.context.sendActivity('First step.'); return Dialog.EndOfTurn; }, - async step => { + async (step) => { simpleStepContextCheck(step); return await step.endDialog(); - } + }, ]); const component = new ContinueDialog('composite'); component.addDialog(startDialog); @@ -178,22 +172,25 @@ describe('ComponentDialog', function () { const dialogs = new DialogSet(dialogState); dialogs.add(component); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { await dc.beginDialog('composite'); } else { - assert(results.status === DialogTurnStatus.complete, `results.status should be 'complete' not ${ results.status }`); - assert(results.result === undefined, `results.result should be undefined, not ${ results.result }`); + assert( + results.status === DialogTurnStatus.complete, + `results.status should be 'complete' not ${results.status}` + ); + assert(results.result === undefined, `results.result should be undefined, not ${results.result}`); await turnContext.sendActivity('Done.'); - done(); } await conversationState.saveChanges(turnContext); }); - adapter.send('Hi') + await adapter + .send('Hi') .assertReply('First step.') .send('Hi again') .assertReply('Called onContinueDialog.') @@ -201,30 +198,30 @@ describe('ComponentDialog', function () { .startTest(); }); - it('should cancel all Dialogs inside of ComponentDialog namespace.', () => { + it('should cancel all Dialogs inside of ComponentDialog namespace.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); const firstChildDialog = new WaterfallDialog('first', [ - async step => { + async (step) => { simpleStepContextCheck(step); - assert(step.stack.length === 1, `dialogStack should only have one dialog, not ${ step.stack.length }`); + assert(step.stack.length === 1, `dialogStack should only have one dialog, not ${step.stack.length}`); await step.context.sendActivity('Reached first component dialog child.'); return await step.beginDialog('second'); }, - async step => { + async (step) => { simpleStepContextCheck(step); await step.context.sendActivity('Should not have sent this message.'); return await step.endDialog(); - } + }, ]); const secondChildDialog = new WaterfallDialog('second', [ - async step => { + async (step) => { simpleStepContextCheck(step); - assert(step.stack.length === 2, `dialog stack should have two dialogs, not ${ step.stack.length }`); + assert(step.stack.length === 2, `dialog stack should have two dialogs, not ${step.stack.length}`); await step.context.sendActivity('Cancelling all component dialog dialogs.'); return await step.cancelAllDialogs(); - } + }, ]); const component = new ComponentDialog('component'); @@ -232,50 +229,60 @@ describe('ComponentDialog', function () { component.addDialog(secondChildDialog); const dialogs = new DialogSet(dialogState); - dialogs.add(component) + dialogs.add(component); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.beginDialog('component'); - assert(results.status === DialogTurnStatus.cancelled, `should have returned ${ DialogTurnStatus.cancelled } not ${ results.status }`); - assert(dc.stack.length === 0, `should have a dialogStack without 0 dialogs, not ${ dc.stack.length } dialogs`); + assert( + results.status === DialogTurnStatus.cancelled, + `should have returned ${DialogTurnStatus.cancelled} not ${results.status}` + ); + assert( + dc.stack.length === 0, + `should have a dialogStack without 0 dialogs, not ${dc.stack.length} dialogs` + ); }); - adapter.send('Hi') + await adapter + .send('Hi') .assertReply('Reached first component dialog child.') .assertReply('Cancelling all component dialog dialogs.') .startTest(); }); - it('should not cancel any Dialogs outside of ComponentDialog namespace.', () => { + it('should not cancel any Dialogs outside of ComponentDialog namespace.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); const outerDialog = new WaterfallDialog('outerDialog', [ - async step => { + async (step) => { simpleStepContextCheck(step); return await step.beginDialog('component'); }, - async step => { + async (step) => { simpleStepContextCheck(step); - assert(step.reason === DialogReason.endCalled, `called ComponentDialog should have bubbled up "cancelCalled" not "${ step.reason }".`); + assert( + step.reason === DialogReason.endCalled, + `called ComponentDialog should have bubbled up "cancelCalled" not "${step.reason}".` + ); await step.context.sendActivity('Cancelled successfully.'); return await step.endDialog(); - } + }, ]); const firstChildDialog = new WaterfallDialog('first', [ - async step => { + async (step) => { simpleStepContextCheck(step); await step.context.sendActivity('Reached first component dialog child.'); return await step.beginDialog('second'); - } + }, ]); const secondChildDialog = new WaterfallDialog('second', [ - async step => { + async (step) => { simpleStepContextCheck(step); await step.context.sendActivity('Cancelling all component dialog dialogs.'); return await step.cancelAllDialogs(); - } + }, ]); const component = new ComponentDialog('component'); @@ -283,89 +290,94 @@ describe('ComponentDialog', function () { component.addDialog(secondChildDialog); const dialogs = new DialogSet(dialogState); - dialogs.add(component) - .add(outerDialog); + dialogs.add(component).add(outerDialog); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); await dc.beginDialog('outerDialog'); }); - adapter.send('Hi') + await adapter + .send('Hi') .assertReply('Reached first component dialog child.') .assertReply('Cancelling all component dialog dialogs.') .assertReply('Cancelled successfully.') .startTest(); }); - it('should call a dialog defined in a parent component.', (done) => { + it('should call a dialog defined in a parent component.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); const childComponent = new ComponentDialog('childComponent'); - childComponent.addDialog(new WaterfallDialog('childDialog', [ - async step => { - await step.context.sendActivity('Child started.'); - return await step.beginDialog('parentDialog', { value: 'test' }); - }, - async step => { - assert(step.result === 'test'); - await step.context.sendActivity('Child finished.'); - return await step.endDialog(); - } - ])); + childComponent.addDialog( + new WaterfallDialog('childDialog', [ + async (step) => { + await step.context.sendActivity('Child started.'); + return await step.beginDialog('parentDialog', { value: 'test' }); + }, + async (step) => { + assert(step.result === 'test'); + await step.context.sendActivity('Child finished.'); + return await step.endDialog(); + }, + ]) + ); const parentComponent = new ComponentDialog('parentComponent'); parentComponent.addDialog(childComponent); - parentComponent.addDialog(new WaterfallDialog('parentDialog', [ - async step => { - assert(step.options.value); - await step.context.sendActivity(`Parent called with: ${step.options.value}`); - return await step.endDialog(step.options.value); - } - ])); - + parentComponent.addDialog( + new WaterfallDialog('parentDialog', [ + async (step) => { + assert(step.options.value); + await step.context.sendActivity(`Parent called with: ${step.options.value}`); + return await step.endDialog(step.options.value); + }, + ]) + ); const dialogs = new DialogSet(dialogState); dialogs.add(parentComponent); - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { await dc.beginDialog('parentComponent'); } else { - assert(results.status === DialogTurnStatus.complete, `results.status should be 'complete' not ${ results.status }`); - assert(results.result === undefined, `results.result should be undefined, not ${ results.result }`); + assert( + results.status === DialogTurnStatus.complete, + `results.status should be 'complete' not ${results.status}` + ); + assert(results.result === undefined, `results.result should be undefined, not ${results.result}`); await turnContext.sendActivity('Done.'); - done(); } await conversationState.saveChanges(turnContext); }); - adapter.send('Hi') + await adapter + .send('Hi') .assertReply('Child started.') .assertReply('Parent called with: test') .assertReply('Child finished.') - .then(() => done()) .startTest(); }); - it('should handle that a components children have changed.', (done) => { + it('should handle that a components children have changed.', async function () { const conversationState = new ConversationState(new MemoryStorage()); const dialogState = conversationState.createProperty('dialog'); const childDialog = new WaterfallDialog('child', [ - async step => { + async (step) => { component.addDialog(new WaterfallDialog('change')); await step.context.sendActivity('First step.'); return Dialog.EndOfTurn; }, - async step => { + async (step) => { await step.context.sendActivity('Second step.'); return await step.endDialog(); - } + }, ]); const component = new ComponentDialog('test'); component.addDialog(childDialog); @@ -373,30 +385,33 @@ describe('ComponentDialog', function () { const dialogs = new DialogSet(dialogState); dialogs.add(component); dialogs.telemetryClient = { - trackEvent: function(telemetry) {}, - trackTrace: function(telemetry) { + trackEvent: function (telemetry) {}, + trackTrace: function (telemetry) { if (telemetry.severityLevel === Severity.Warning) { assert.equal(telemetry.message, 'Unhandled dialog event: versionChanged. Active Dialog: test'); } - } + }, }; - const adapter = new TestAdapter(async turnContext => { + const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { await dc.beginDialog('test'); } else { - assert(results.status === DialogTurnStatus.complete, `results.status should be 'complete' not ${ results.status }`); - assert(results.result === undefined, `results.result should be undefined, not ${ results.result }`); + assert( + results.status === DialogTurnStatus.complete, + `results.status should be 'complete' not ${results.status}` + ); + assert(results.result === undefined, `results.result should be undefined, not ${results.result}`); await turnContext.sendActivity('Done.'); - done(); } await conversationState.saveChanges(turnContext); }); - adapter.send('Hi') + await adapter + .send('Hi') .assertReply('First step.') .send('Hi again') .assertReply('Second step.') @@ -405,7 +420,6 @@ describe('ComponentDialog', function () { }); }); - class ContinueDialog extends ComponentDialog { constructor(dialogId) { super(dialogId); diff --git a/libraries/botbuilder-dialogs/tests/dialogContext.test.js b/libraries/botbuilder-dialogs/tests/dialogContext.test.js index 2828021911..f9429f5e69 100644 --- a/libraries/botbuilder-dialogs/tests/dialogContext.test.js +++ b/libraries/botbuilder-dialogs/tests/dialogContext.test.js @@ -1,223 +1,239 @@ const { ConversationState, MemoryStorage, TestAdapter } = require('botbuilder-core'); -const { Dialog, DialogContextError, DialogSet, WaterfallDialog, DialogTurnStatus } = require('../'); +const { Dialog, DialogContextError, DialogSet, WaterfallDialog, DialogTurnStatus } = require('../'); const assert = require('assert'); const beginMessage = { text: `begin`, type: 'message' }; const continueMessage = { text: `continue`, type: 'message' }; -describe('DialogContext', function() { +describe('DialogContext', function () { this.timeout(5000); - it('should beginDialog() a new dialog.', function (done) { + it('should beginDialog() a new dialog.', async function () { // Initialize TestAdapter. const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.beginDialog('a'); if (results.status === DialogTurnStatus.complete) { assert(results.result === true, `End result from WaterfallDialog was not expected value.`); - done(); } await convoState.saveChanges(turnContext); }); // Create new ConversationState with MemoryStorage and register the state as middleware. const convoState = new ConversationState(new MemoryStorage()); - + // Create a DialogState property, DialogSet and register the WaterfallDialog. const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.endDialog(true); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.endDialog(true); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it('beginDialog() should pass in dialogOptions to a begun dialog.', function (done) { + it('beginDialog() should pass in dialogOptions to a begun dialog.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.beginDialog('a', { z: 'z' }); if (results.status === DialogTurnStatus.complete) { assert(results.result === true, `End result from WaterfallDialog was not expected value.`); - done(); } await convoState.saveChanges(turnContext); }); const convoState = new ConversationState(new MemoryStorage()); - + const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert(step.options.z === 'z', `Correct DialogOptions was not passed in to WaterfallDialog.`); - return await step.endDialog(true); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert(step.options.z === 'z', `Correct DialogOptions was not passed in to WaterfallDialog.`); + return await step.endDialog(true); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it('should return error if beginDialog() called with invalid dialogId.', function (done) { + it('should return error if beginDialog() called with invalid dialogId.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - - try { - let results = await dc.beginDialog('b'); - await convoState.saveChanges(turnContext); - } - catch (err) { - assert(err); - assert.strictEqual(err.message, `DialogContext.beginDialog(): A dialog with an id of 'b' wasn't found.`, `unexpected error message thrown: "${err.message}"`); - assert(err instanceof DialogContextError, 'err should be a DialogContextError'); - assert(err.dialogContext, 'err should include dialogContext'); - - return done(); - } - throw new Error('Should have thrown an error.'); + await assert.rejects( + async () => { + await dc.beginDialog('b'); + await convoState.saveChanges(turnContext); + }, + (err) => { + assert.strictEqual( + err.message, + `DialogContext.beginDialog(): A dialog with an id of 'b' wasn't found.`, + `unexpected error message thrown: "${err.message}"` + ); + + assert(err instanceof DialogContextError, 'err should be a DialogContextError'); + assert(err.dialogContext, 'err should include dialogContext'); + return true; + } + ); }); const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - return await step.endDialog(); - } - ])); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + return await step.endDialog(); + }, + ]) + ); - adapter.send(beginMessage).startTest(); + await adapter.send(beginMessage).startTest(); }); - it('should pass prompt() args to dialog.', function (done) { + it('should pass prompt() args to dialog.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - - const results = await dc.prompt('a', 'test'); + + await dc.prompt('a', 'test'); await convoState.saveChanges(turnContext); - done(); }); const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert.strictEqual(step.options.prompt, 'test', `promptOrOptions arg was not correctly passed through.`); - return await step.endDialog(); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert.strictEqual( + step.options.prompt, + 'test', + `promptOrOptions arg was not correctly passed through.` + ); + return await step.endDialog(); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it('should pass undefined prompt() to dialog.', function (done) { + it('should pass undefined prompt() to dialog.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - - const results = await dc.prompt('a'); + + await dc.prompt('a'); await convoState.saveChanges(turnContext); - done(); }); const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.endDialog(); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.endDialog(); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it('should pass choice array to prompt() to dialog.', function (done) { + it('should pass choice array to prompt() to dialog.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - - const results = await dc.prompt('a', 'test', ['red', 'green', 'blue']); + + await dc.prompt('a', 'test', ['red', 'green', 'blue']); await convoState.saveChanges(turnContext); - done(); }); const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert(Array.isArray(step.options.choices), `choices received in step is not an array.`); - assert.strictEqual(step.options.choices.length, 3, `not all choices were passed in.`); - return await step.endDialog(); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert(Array.isArray(step.options.choices), `choices received in step is not an array.`); + assert.strictEqual(step.options.choices.length, 3, `not all choices were passed in.`); + return await step.endDialog(); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it('should return a value to parent when endDialog() called with a value.', function (done) { + it('should return a value to parent when endDialog() called with a value.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.beginDialog('a'); await convoState.saveChanges(turnContext); assert.strictEqual(results.result, 119, `unexpected results.result value received from 'a' dialog.`); - done(); }); const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.beginDialog('b'); - }, - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert.strictEqual(step.result, 120, `incorrect step.result value received from 'b' dialog.`); - return await step.endDialog(119); - } - ])); - - dialogs.add(new WaterfallDialog('b', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.endDialog(120); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.beginDialog('b'); + }, + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert.strictEqual(step.result, 120, `incorrect step.result value received from 'b' dialog.`); + return await step.endDialog(119); + }, + ]) + ); + + dialogs.add( + new WaterfallDialog('b', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.endDialog(120); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it('should continue() execution of a dialog.', function (done) { + it('should continue() execution of a dialog.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.continueDialog(); switch (results.status) { case DialogTurnStatus.empty: await dc.beginDialog('a'); break; - + case DialogTurnStatus.complete: assert.strictEqual(results.result, true, `received unexpected final result from dialog.`); - done(); break; } await convoState.saveChanges(turnContext); @@ -227,203 +243,216 @@ describe('DialogContext', function() { const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - await step.context.sendActivity(`foo`); - return Dialog.EndOfTurn; - }, - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.endDialog(true); - } - ])); - - adapter.send(beginMessage) - .send(continueMessage) - .startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + await step.context.sendActivity(`foo`); + return Dialog.EndOfTurn; + }, + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.endDialog(true); + }, + ]) + ); + + await adapter.send(beginMessage).send(continueMessage).startTest(); }); - it('should return an error if dialog not found when continue() called.', function (done) { + it('should return an error if dialog not found when continue() called.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - let results; - try { - results = await dc.continueDialog(); - } - catch (err) { - assert(err, `Error not found.`); - assert.strictEqual(err.message, `DialogContext.continueDialog(): Can't continue dialog. A dialog with an id of 'b' wasn't found.`, `unexpected error message thrown: "${err.message}"`); - - assert(err instanceof DialogContextError, 'err should be a DialogContextError'); - assert(err.dialogContext, 'err should include dialogContext'); - - return done(); - } + const results = await dc.continueDialog(); if (results.status === DialogTurnStatus.empty) { await dc.beginDialog('a'); } await convoState.saveChanges(turnContext); }); - + const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert.strictEqual(step.activeDialog.id, 'a', `incorrect value for step.activeDialog.id`); - step.activeDialog.id = 'b'; - return Dialog.EndOfTurn; - }, - async function (step) { - assert(false, `shouldn't continue`); - } - ])); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert.strictEqual(step.activeDialog.id, 'a', `incorrect value for step.activeDialog.id`); + step.activeDialog.id = 'b'; + return Dialog.EndOfTurn; + }, + async function (step) { + assert(false, `shouldn't continue`); + }, + ]) + ); + + await assert.rejects( + async () => await adapter.send(beginMessage).send(continueMessage).startTest(), + (err) => { + assert(err, `Error not found.`); + assert.strictEqual( + err.message, + `DialogContext.continueDialog(): Can't continue dialog. A dialog with an id of 'b' wasn't found.`, + `unexpected error message thrown: "${err.message}"` + ); - adapter.send(beginMessage) - .send(continueMessage) - .startTest(); + assert(err instanceof DialogContextError, 'err should be a DialogContextError'); + assert(err.dialogContext, 'err should include dialogContext'); + return true; + } + ); }); - it(`should return a DialogTurnResult if continue() is called without an activeDialog.`, function (done) { + it(`should return a DialogTurnResult if continue() is called without an activeDialog.`, async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); const results = await dc.continueDialog(); assert.strictEqual(typeof results, 'object', `results is not the expected object`); assert.strictEqual(results.status, DialogTurnStatus.empty, `results.status is not 'empty'.`); await convoState.saveChanges(turnContext); - done(); }); const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); - const dialogs = new DialogSet(dialogState); + const dialogs = new DialogSet(dialogState); - adapter.send(beginMessage).startTest(); + await adapter.send(beginMessage).startTest(); }); - it('should return to parent dialog when endDialog() called.', function (done) { + it('should return to parent dialog when endDialog() called.', async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.beginDialog('a'); assert.strictEqual(results.result, true, `received unexpected final result from dialog.`); await convoState.saveChanges(turnContext); - done(); }); const convoState = new ConversationState(new MemoryStorage()); - + const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.beginDialog('b'); - }, - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert(step.context.activity.text, 'begin', `unexpected message received.`); - assert(step.result, `ended dialog.`, `unexpected step.result received.`); - return await step.endDialog(true); - } - ])); - - dialogs.add(new WaterfallDialog('b', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.endDialog('ended dialog.'); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.beginDialog('b'); + }, + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert(step.context.activity.text, 'begin', `unexpected message received.`); + assert(step.result, `ended dialog.`, `unexpected step.result received.`); + return await step.endDialog(true); + }, + ]) + ); + + dialogs.add( + new WaterfallDialog('b', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.endDialog('ended dialog.'); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it(`should accept calls to end when no activeDialogs or parent dialogs exist.`, function (done) { + it(`should accept calls to end when no activeDialogs or parent dialogs exist.`, async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.endDialog(); await convoState.saveChanges(turnContext); assert.strictEqual(results.status, DialogTurnStatus.complete, `results.status not equal 'complete'.`); - assert.strictEqual(results.result, undefined, `received unexpected value for results.result (expected undefined).`); - done(); + assert.strictEqual( + results.result, + undefined, + `received unexpected value for results.result (expected undefined).` + ); }); const convoState = new ConversationState(new MemoryStorage()); - + const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.replaceDialog('b', { z: step.options.z }); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.replaceDialog('b', { z: step.options.z }); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it(`should replace() dialog.`, function (done) { + it(`should replace() dialog.`, async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - + const results = await dc.beginDialog('a', { z: 'z' }); await convoState.saveChanges(turnContext); assert.strictEqual(results.result, 'z', `received unexpected final result from dialog.`); - done(); }); const convoState = new ConversationState(new MemoryStorage()); - + const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('a', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.replaceDialog('b', { z: step.options.z }); - } - ])); - - dialogs.add(new WaterfallDialog('b', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - assert.strictEqual(step.stack.length, 1, `current DialogContext.stack.length should be 1.`); - assert.strictEqual(step.options.z, 'z', `incorrect step.options received.`); - return await step.endDialog(step.options.z); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('a', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.replaceDialog('b', { z: step.options.z }); + }, + ]) + ); + + dialogs.add( + new WaterfallDialog('b', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + assert.strictEqual(step.stack.length, 1, `current DialogContext.stack.length should be 1.`); + assert.strictEqual(step.options.z, 'z', `incorrect step.options received.`); + return await step.endDialog(step.options.z); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); - it(`should begin dialog if stack empty when replaceDialog() called with valid dialogId.`, function (done) { + it(`should begin dialog if stack empty when replaceDialog() called with valid dialogId.`, async function () { const adapter = new TestAdapter(async (turnContext) => { const dc = await dialogs.createContext(turnContext); - const results = await dc.replaceDialog('b'); + await dc.replaceDialog('b'); await convoState.saveChanges(turnContext); - done(); }); const convoState = new ConversationState(new MemoryStorage()); - + const dialogState = convoState.createProperty('dialogState'); const dialogs = new DialogSet(dialogState); - dialogs.add(new WaterfallDialog('b', [ - async function (step) { - assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); - return await step.endDialog(); - } - ])); - - adapter.send(beginMessage).startTest(); + dialogs.add( + new WaterfallDialog('b', [ + async function (step) { + assert(step, `WaterfallStepContext not passed in to WaterfallStep.`); + return await step.endDialog(); + }, + ]) + ); + + await adapter.send(beginMessage).startTest(); }); }); diff --git a/libraries/botbuilder-dialogs/tests/dialogHelper.test.js b/libraries/botbuilder-dialogs/tests/dialogHelper.test.js index 7523ab3d49..6fdf611e94 100644 --- a/libraries/botbuilder-dialogs/tests/dialogHelper.test.js +++ b/libraries/botbuilder-dialogs/tests/dialogHelper.test.js @@ -1,4 +1,4 @@ -const { ok, strictEqual } = require('assert'); +const assert = require('assert'); const { ActivityTypes, AutoSaveStateMiddleware, @@ -89,7 +89,7 @@ function createTestFlow(dialog, testCase) { } // Interceptor to capture the EoC activity if it was sent so we can assert it in the tests. - context.onSendActivities(async (tc, activities, next) => { + context.onSendActivities(async (_tc, activities, next) => { for (let idx = 0; idx < activities.length; idx++) { if (activities[idx].type === ActivityTypes.EndOfConversation) { _eocSent = activities[idx]; @@ -180,40 +180,28 @@ describe('runDialog()', function () { this.timeout(300); describe('parameter validation', () => { - it('should throw if missing dialog parameter', (done) => { - runDialog().then( - () => done(new Error('should have throw error')), - (err) => { - done(strictEqual(err.message, 'runDialog(): missing dialog')); - } - ); + it('should throw if missing dialog parameter', async function () { + await assert.rejects(async () => runDialog(), { + message: 'runDialog(): missing dialog', + }); }); - it('should throw if missing context parameter', (done) => { - runDialog({}).then( - () => done(new Error('should have throw error')), - (err) => { - done(strictEqual(err.message, 'runDialog(): missing context')); - } - ); + it('should throw if missing context parameter', async function () { + await assert.rejects(async () => runDialog({}), { + message: 'runDialog(): missing context', + }); }); - it('should throw if missing context.activity', (done) => { - runDialog({}, {}).then( - () => done(new Error('should have throw error')), - (err) => { - done(strictEqual(err.message, 'runDialog(): missing context.activity')); - } - ); + it('should throw if missing context.activity', async function () { + await assert.rejects(async () => runDialog({}, {}), { + message: 'runDialog(): missing context.activity', + }); }); - it('should throw if missing accessor parameter', (done) => { - runDialog({}, { activity: {} }).then( - () => done(new Error('should have throw error')), - (err) => { - done(strictEqual(err.message, 'runDialog(): missing accessor')); - } - ); + it('should throw if missing accessor parameter', async function () { + await assert.rejects(async () => runDialog({}, { activity: {} }), { + message: 'runDialog(): missing accessor', + }); }); }); @@ -232,14 +220,14 @@ describe('runDialog()', function () { .assertReply('Hello SomeName, nice to meet you!') .startTest(); - strictEqual(dialog.endReason, DialogReason.endCalled); + assert.strictEqual(dialog.endReason, DialogReason.endCalled); if (shouldSendEoc) { - ok(_eocSent, 'Skills should send EndConversation to channel'); - strictEqual(_eocSent.type, ActivityTypes.EndOfConversation); - strictEqual(_eocSent.value, 'SomeName'); - strictEqual(_eocSent.code, EndOfConversationCodes.CompletedSuccessfully); + assert.ok(_eocSent, 'Skills should send EndConversation to channel'); + assert.strictEqual(_eocSent.type, ActivityTypes.EndOfConversation); + assert.strictEqual(_eocSent.value, 'SomeName'); + assert.strictEqual(_eocSent.code, EndOfConversationCodes.CompletedSuccessfully); } else { - strictEqual(undefined, _eocSent, 'Root bot should not send EndConversation to channel'); + assert.strictEqual(undefined, _eocSent, 'Root bot should not send EndConversation to channel'); } } @@ -266,20 +254,20 @@ describe('runDialog()', function () { const testFlow = createTestFlow(dialog, FlowTestCase.MiddleSkill); await testFlow.send('Hi').startTest(); - strictEqual(dialog.endReason, DialogReason.endCalled); - ok(_eocSent, 'Skills should send EndConversation to channel'); - strictEqual(_eocSent.type, ActivityTypes.EndOfConversation); - strictEqual(_eocSent.code, EndOfConversationCodes.CompletedSuccessfully); + assert.strictEqual(dialog.endReason, DialogReason.endCalled); + assert.ok(_eocSent, 'Skills should send EndConversation to channel'); + assert.strictEqual(_eocSent.type, ActivityTypes.EndOfConversation); + assert.strictEqual(_eocSent.code, EndOfConversationCodes.CompletedSuccessfully); }); it('handles premature dialog cancellation', async () => { const dialog = new ComponentDialogWithCancellation(); const testFlow = createTestFlow(dialog, FlowTestCase.MiddleSkill); await testFlow.send('Hi').startTest(); - strictEqual(dialog.endReason, DialogReason.cancelCalled); - ok(_eocSent, 'Skills should send EndConversation to channel'); - strictEqual(_eocSent.type, ActivityTypes.EndOfConversation); - strictEqual(_eocSent.code, EndOfConversationCodes.UserCancelled); + assert.strictEqual(dialog.endReason, DialogReason.cancelCalled); + assert.ok(_eocSent, 'Skills should send EndConversation to channel'); + assert.strictEqual(_eocSent.type, ActivityTypes.EndOfConversation); + assert.strictEqual(_eocSent.code, EndOfConversationCodes.UserCancelled); }); }); }); diff --git a/libraries/botbuilder-dialogs/tests/dialogSet.test.js b/libraries/botbuilder-dialogs/tests/dialogSet.test.js index 570b0e10f0..3b21d2f07a 100644 --- a/libraries/botbuilder-dialogs/tests/dialogSet.test.js +++ b/libraries/botbuilder-dialogs/tests/dialogSet.test.js @@ -14,13 +14,12 @@ describe('DialogSet', function () { it('should throw on createContext(undefined)', async function () { const dialogSet = new DialogSet(dialogState); - try { - await dialogSet.createContext(undefined); - assert.fail('should have thrown error on undefined'); - } catch (err) {} + await assert.rejects(async () => await dialogSet.createContext(undefined), { + message: "Cannot read property 'turnState' of undefined", + }); }); - it('should add a waterfall to the dialog set.', function (done) { + it('should add a waterfall to the dialog set.', function () { const dialogs = new DialogSet(dialogState); dialogs.add( new WaterfallDialog('a', [ @@ -29,7 +28,6 @@ describe('DialogSet', function () { }, ]) ); - done(); }); it('should throw an error if DialogSet.dialogState is falsey.', async function () { @@ -45,7 +43,7 @@ describe('DialogSet', function () { } }); - it('should add fluent dialogs to the dialog set.', function (done) { + it('should add fluent dialogs to the dialog set.', function () { // Create new ConversationState with MemoryStorage and instantiate DialogSet with PropertyAccessor. const dialogs = new DialogSet(dialogState); dialogs @@ -65,11 +63,9 @@ describe('DialogSet', function () { ); assert(dialogs.find('A'), `dialog A not found.`); assert(dialogs.find('B'), `dialog B not found.`); - - done(); }); - it('should increment the dialog ID when adding the same dialog twice.', function (done) { + it('should increment the dialog ID when adding the same dialog twice.', function () { const dialogs = new DialogSet(dialogState); dialogs.add(new WaterfallDialog('a', [function () {}])); @@ -77,19 +73,17 @@ describe('DialogSet', function () { assert(dialogs.find('a')); assert(dialogs.find('a2'), `second dialog didn't have ID incremented`); - done(); }); - it('should find() a dialog that was added.', function (done) { + it('should find() a dialog that was added.', function () { const dialogs = new DialogSet(dialogState); dialogs.add(new WaterfallDialog('a', [function () {}])); assert(dialogs.find('a'), `dialog not found.`); assert(!dialogs.find('b'), `dialog found that shouldn't exist.`); - done(); }); - it('should save dialog stack state between turns.', function (done) { + it('should save dialog stack state between turns.', async function () { const convoState = new ConversationState(new MemoryStorage()); const dialogState = convoState.createProperty('dialogState'); @@ -118,25 +112,22 @@ describe('DialogSet', function () { await convoState.saveChanges(turnContext); }); - adapter + await adapter .send(beginMessage) .assertReply('Greetings') .send(continueMessage) .assertReply('Good bye!') - .then(() => done()) .startTest(); }); - it('should generate a version hash of added dialogs.', function (done) { + it('should generate a version hash of added dialogs.', function () { const dialogs = new DialogSet(dialogState); dialogs.add(new WaterfallDialog('A')).add(new WaterfallDialog('B')); const hash = dialogs.getVersion(); assert(hash && hash.length > 0, `no hash generated.`); - - done(); }); - it('Generated version hash should change when dialog set changes.', function (done) { + it('Generated version hash should change when dialog set changes.', function () { const dialogs = new DialogSet(dialogState); dialogs.add(new WaterfallDialog('A')).add(new WaterfallDialog('B')); const hash = dialogs.getVersion(); @@ -144,8 +135,6 @@ describe('DialogSet', function () { dialogs.add(new WaterfallDialog('C')); assert(hash != dialogs.getVersion(), `hash not updated.`); - - done(); }); it('Cyclical dialog structures', () => { diff --git a/libraries/botbuilder-dialogs/tests/memory_pathResolvers.test.js b/libraries/botbuilder-dialogs/tests/memory_pathResolvers.test.js index 8c2a50be7b..35b91f942a 100644 --- a/libraries/botbuilder-dialogs/tests/memory_pathResolvers.test.js +++ b/libraries/botbuilder-dialogs/tests/memory_pathResolvers.test.js @@ -1,63 +1,61 @@ -const { AliasPathResolver, AtAtPathResolver, AtPathResolver, - DollarPathResolver, HashPathResolver, PercentPathResolver } = require('../'); +const { + AliasPathResolver, + AtAtPathResolver, + AtPathResolver, + DollarPathResolver, + HashPathResolver, + PercentPathResolver, +} = require('../'); const assert = require('assert'); -describe('Memory - Path Resolvers', function() { +describe('Memory - Path Resolvers', function () { this.timeout(5000); - it('AliasPathResolver should should prefix paths.', function (done) { + it('AliasPathResolver should should prefix paths.', function () { const resolver = new AliasPathResolver('@', 'turn.recognized.entities.'); const path = resolver.transformPath('@test'); assert(path == 'turn.recognized.entities.test', `path: ${path}`); - done(); }); - it('AliasPathResolver should should prefix and postfix paths.', function (done) { + it('AliasPathResolver should should prefix and postfix paths.', function () { const resolver = new AliasPathResolver('@', 'turn.recognized.entities.', '.first()'); const path = resolver.transformPath('@test'); assert(path == 'turn.recognized.entities.test.first()', `path: ${path}`); - done(); }); - it('AliasPathResolver should ignore non-matching aliases.', function (done) { + it('AliasPathResolver should ignore non-matching aliases.', function () { const resolver = new AliasPathResolver('@', 'turn.recognized.entities.', '.first()'); const path = resolver.transformPath('$test'); assert(path == '$test', `path: ${path}`); - done(); }); - it('AtAtPathResolver should transform @@ aliases.', function (done) { + it('AtAtPathResolver should transform @@ aliases.', function () { const resolver = new AtAtPathResolver(); const path = resolver.transformPath('@@test'); assert(path == 'turn.recognized.entities.test', `path: ${path}`); - done(); }); - it('AtPathResolver should transform @ aliases.', function (done) { + it('AtPathResolver should transform @ aliases.', function () { const resolver = new AtPathResolver(); assert.equal(resolver.transformPath('@test'), 'turn.recognized.entities.test.first()'); assert.equal(resolver.transformPath('@test.bar'), 'turn.recognized.entities.test.first().bar'); - done(); }); - it('DollarPathResolver should transform $ aliases.', function (done) { + it('DollarPathResolver should transform $ aliases.', function () { const resolver = new DollarPathResolver(); const path = resolver.transformPath('$test'); assert(path == 'dialog.test', `path: ${path}`); - done(); }); - it('HashPathResolver should transform # aliases.', function (done) { + it('HashPathResolver should transform # aliases.', function () { const resolver = new HashPathResolver(); const path = resolver.transformPath('#test'); assert(path == 'turn.recognized.intents.test', `path: ${path}`); - done(); }); - it('PercentPathResolver should transform % aliases.', function (done) { + it('PercentPathResolver should transform % aliases.', function () { const resolver = new PercentPathResolver(); const path = resolver.transformPath('%test'); assert(path == 'class.test', `path: ${path}`); - done(); }); -}); \ No newline at end of file +});