From d0b78dfabc9228d94d6222d9f9f2ed610271555d Mon Sep 17 00:00:00 2001 From: Matthew Schwartz Date: Thu, 5 Oct 2017 19:03:52 -0700 Subject: [PATCH] v3.1.0 (#33) * Add message filter and in-line options update (#28) * added ability to filter messages * added in line options modifier * add builtin message filters to options/config (#30) * v3.1.0 (#32) * add builtin message filters * bump version for v3.1.0 * updated docs for publish --- README.md | 73 ++- docs/assets/js/search.js | 2 +- ...ries_chaiexpectation_.chaiexpectation.html | 19 +- docs/classes/_bottester_.bottester.html | 260 +++++---- .../_expectedmessage_.expectedmessage.html | 17 +- .../_messageservice_.messageservice.html | 17 +- ...comparator_.outgoingmessagecomparator.html | 21 +- .../_sessionservice_.sessionservice.html | 23 +- .../_testconnector_.testconnector.html | 17 +- ..._expectedmessage_.expectedmessagetype.html | 9 +- docs/index.html | 4 + ...nlibraries_iexpectation_.iexpectation.html | 13 +- docs/interfaces/_bottester_.ibottester.html | 501 ++++++++++++++++++ .../_bottester_.ioptionsmodifier.html | 370 +++++++++++++ docs/interfaces/_config_.iconfig.html | 67 ++- .../_assertionlibraries_chaiexpectation_.html | 3 + .../_assertionlibraries_iexpectation_.html | 5 +- docs/modules/_bottester_.html | 18 +- docs/modules/_builtinmessagefilters_.html | 290 ++++++++++ docs/modules/_config_.html | 55 +- docs/modules/_expectedmessage_.html | 9 +- docs/modules/_index_.html | 3 + docs/modules/_messageservice_.html | 5 +- docs/modules/_outgoingmessagecomparator_.html | 3 + docs/modules/_sessionservice_.html | 3 + docs/modules/_testconnector_.html | 3 + package.json | 2 +- src/BotTester.ts | 201 ++++--- src/ExpectedMessage.ts | 4 +- src/MessageService.ts | 14 +- src/builtInMessageFilters.ts | 13 + src/config.ts | 24 +- test/BotTester.spec.ts | 70 ++- test/BotTesterFailure.spec.ts | 51 ++ 34 files changed, 1953 insertions(+), 236 deletions(-) create mode 100644 docs/interfaces/_bottester_.ibottester.html create mode 100644 docs/interfaces/_bottester_.ioptionsmodifier.html create mode 100644 docs/modules/_builtinmessagefilters_.html create mode 100644 src/builtInMessageFilters.ts diff --git a/README.md b/README.md index d872b91..0dd3e7b 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,22 @@ config can be set one of 2 ways: 1. creating a bot-tester.json file in the root directory of your project. 2. passing in a config object into the options param, which is the last, when creating a BotTester instance + Passing in the config overrides any default values or values set by bot-tester.json. At the moment, the options are: -```javascript +```typescript { defaultAddress: botbuilder.IAddress, timeout: number // in milliseconds + // each filter returns false for messages that the BotTester should ignore + messageFilters: ((message:IMessage) => boolean)[], + ignoreTypingEvent: boolean, + ignoreEndOfConversationEvent: boolean } ``` if timeout is defined, then a particular ```runTest()``` call will fail if it does not receive each expected message within the timeout period of time set in the options. +additionally, config can be set by using the config updating options in the build chain, documented below in the example use + For a more in depth view, check out [the Bot Tester Framework Config doc](https://microsoftly.github.io/BotTester/interfaces/_config_.iconfig.html) # Example Usage ```javascript @@ -357,3 +364,67 @@ describe('BotTester', () => { .runTest(); }); ``` + +# can apply one or more message filters in the BotTester options for messages to ignore +``` javascript + it('can apply one or more message filters in the BotTester options for messages to ignore', () => { + bot.dialog('/', (session) => { + session.send('hello'); + session.send('how'); + session.send('are'); + session.send('you?'); + }); + + const ignoreHowMessage = (message) => !message.text.includes('how'); + const ignoreAreMessage = (message) => !message.text.includes('are'); + + return new BotTester(bot, { messageFilters: [ignoreHowMessage, ignoreAreMessage]}) + .sendMessageToBot('intro', 'hello', 'you?') + .runTest(); + }); +``` + +# can modify BotTester options +``` javascript + describe('can modifiy options in line in builder chain', () => { + it('add a message filter', () => { + bot.dialog('/', (session) => { + session.send('hello'); + session.send('there'); + session.send('green'); + }); + + return new BotTester(bot) + .addMessageFilter((msg) => !msg.text.includes('hello')) + .addMessageFilter((msg) => !msg.text.includes('there')) + .sendMessageToBot('hey', 'green') + .runTest(); + }); + + it('change timeout time', (done) => { + const timeout = 750; + bot.dialog('/', (session) => { + setTimeout(() => session.send('hi there'), timeout * 2 ); + }); + + expect(new BotTester(bot) + .setTimeout(timeout) + .sendMessageToBot('hey', 'hi there') + .runTest() + ).to.be.rejected.notify(done); + }); + + it('can ignore typing events', () => { + bot.dialog('/', (session) => { + session.send('hello'); + session.sendTyping(); + session.send('goodbye'); + }); + + return new BotTester(bot) + .ignoreTypingEvent() + .sendMessageToBot('hey', 'hello', 'goodbye') + .runTest(); + }); + }); +``` diff --git a/docs/assets/js/search.js b/docs/assets/js/search.js index 636b530..f8620f9 100644 --- a/docs/assets/js/search.js +++ b/docs/assets/js/search.js @@ -1,3 +1,3 @@ var typedoc = typedoc || {}; typedoc.search = typedoc.search || {}; - typedoc.search.data = {"kinds":{"1":"External module","65536":"Type literal"},"rows":[{"id":0,"kind":65536,"name":"__type","url":"classes/_testconnector_.testconnector.html#oneventhandler.__type","classes":"tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported","parent":"\"TestConnector\".TestConnector.onEventHandler"},{"id":1,"kind":65536,"name":"__type","url":"classes/_testconnector_.testconnector.html#oninvokehandler.__type-1","classes":"tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported","parent":"\"TestConnector\".TestConnector.onInvokeHandler"},{"id":2,"kind":65536,"name":"__type","url":"modules/_messageservice_.html#bottousermessagecheckerfunction.__type","classes":"tsd-kind-type-literal tsd-parent-kind-type-alias tsd-is-not-exported","parent":"\"MessageService\".botToUserMessageCheckerFunction"},{"id":3,"kind":65536,"name":"__type","url":"classes/_sessionservice_.sessionservice.html#currentsessionloadresolver.__type","classes":"tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported","parent":"\"SessionService\".SessionService.currentSessionLoadResolver"},{"id":4,"kind":65536,"name":"__type","url":"modules/_bottester_.html#checksessionfunction.__type","classes":"tsd-kind-type-literal tsd-parent-kind-type-alias tsd-is-not-exported","parent":"\"BotTester\".checkSessionFunction"},{"id":5,"kind":1,"name":"\"index\"","url":"modules/_index_.html","classes":"tsd-kind-external-module"}]}; \ No newline at end of file + typedoc.search.data = {"kinds":{"1":"External module","65536":"Type literal"},"rows":[{"id":0,"kind":65536,"name":"__type","url":"classes/_testconnector_.testconnector.html#oneventhandler.__type","classes":"tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported","parent":"\"TestConnector\".TestConnector.onEventHandler"},{"id":1,"kind":65536,"name":"__type","url":"classes/_testconnector_.testconnector.html#oninvokehandler.__type-1","classes":"tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported","parent":"\"TestConnector\".TestConnector.onInvokeHandler"},{"id":2,"kind":65536,"name":"__type","url":"modules/_config_.html#messagefilter.__type","classes":"tsd-kind-type-literal tsd-parent-kind-type-alias tsd-is-not-exported","parent":"\"config\".MessageFilter"},{"id":3,"kind":65536,"name":"__type","url":"modules/_messageservice_.html#bottousermessagecheckerfunction.__type","classes":"tsd-kind-type-literal tsd-parent-kind-type-alias tsd-is-not-exported","parent":"\"MessageService\".botToUserMessageCheckerFunction"},{"id":4,"kind":65536,"name":"__type","url":"classes/_sessionservice_.sessionservice.html#currentsessionloadresolver.__type","classes":"tsd-kind-type-literal tsd-parent-kind-property tsd-is-not-exported","parent":"\"SessionService\".SessionService.currentSessionLoadResolver"},{"id":5,"kind":65536,"name":"__type","url":"modules/_bottester_.html#checksessionfunction.__type","classes":"tsd-kind-type-literal tsd-parent-kind-type-alias tsd-is-not-exported","parent":"\"BotTester\".checkSessionFunction"},{"id":6,"kind":1,"name":"\"index\"","url":"modules/_index_.html","classes":"tsd-kind-external-module"}]}; \ No newline at end of file diff --git a/docs/classes/_assertionlibraries_chaiexpectation_.chaiexpectation.html b/docs/classes/_assertionlibraries_chaiexpectation_.chaiexpectation.html index fb1c32e..cbb5966 100644 --- a/docs/classes/_assertionlibraries_chaiexpectation_.chaiexpectation.html +++ b/docs/classes/_assertionlibraries_chaiexpectation_.chaiexpectation.html @@ -130,7 +130,7 @@

constructor

  • Parameters

    @@ -155,7 +155,7 @@

    Private message

    message: string
    @@ -165,7 +165,7 @@

    Private subject

    subject: __type
    @@ -183,7 +183,7 @@

    notToBeEmpty

    Returns void

    @@ -201,7 +201,7 @@

    toBeTrue

    Returns void

    @@ -219,7 +219,7 @@

    toDeeplyInclude

    @@ -252,7 +252,7 @@

    toEqual

    Parameters

    @@ -276,7 +276,7 @@

    toInclude

    Parameters

    @@ -330,6 +330,9 @@

    Returns void "assertionLibraries/IExpectation"

  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/classes/_bottester_.bottester.html b/docs/classes/_bottester_.bottester.html index 5f0f331..6b2c6ac 100644 --- a/docs/classes/_bottester_.bottester.html +++ b/docs/classes/_bottester_.bottester.html @@ -82,6 +82,13 @@

    Hierarchy

    +
    +

    Implements

    + +

    Index

    @@ -96,7 +103,7 @@

    Constructors

    Properties

    @@ -198,7 +197,7 @@

    Private sessionLoader

    sessionLoader: SessionService
    @@ -208,47 +207,61 @@

    Private testSteps

    testSteps: TestStep[]

    Methods

    +
    + +

    addMessageFilter

    + + +

    checkSession

    • -
      -
      -

      loads a session associated with an address and passes it to a user defined function

      -
      -

      Parameters

      • sessionCheckerFunction: checkSessionFunction
        -
        -

        function passed in to inspect message

        -
      • Optional address: IAddress
        -
        -

        (Optional) address of the session to load. Defaults to bot's default address if not defined

        -
      -

      Returns BotTester

      +

      Returns IBotTester

    @@ -262,7 +275,7 @@

    Private convertToIMessage<
  • Parameters

    @@ -275,25 +288,62 @@

    Returns IMessage<

  • +
    + +

    ignoreEndOfConversationEvent

    + + +
    +
    + +

    ignoreTypingEvent

    + + +

    runTest

    @@ -301,38 +351,26 @@

    Returns Promise

    sendMessageToBot

      -
    • sendMessageToBot(msg: IMessage | string, ...expectedResponses: (string | RegExp | IMessage | (string | RegExp | IMessage)[])[]): BotTester
    • +
    • sendMessageToBot(msg: IMessage | string, ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]): IBotTester
    • -
      -
      -

      sends a message to a bot and compares bot responses against expectedResponsess. Expected responses can be a variable number of args, - each of which can be a single expected response of any PossibleExpectedMessageType or a collection of PossibleExpectedMessageType - that mocks a randomly selected response by the bot

      -
      -

      Parameters

      • msg: IMessage | string
        -
        -

        message to send to bot

        -
      • -
        Rest ...expectedResponses: (string | RegExp | IMessage | (string | RegExp | IMessage)[])[]
        -
        -

        (Optional) responses the bot-tester framework checks against

        -
        +
        Rest ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]
      -

      Returns BotTester

      +

      Returns IBotTester

    @@ -340,31 +378,23 @@

    Returns

    sendMessageToBotAndExpectSaveWithNoResponse

      -
    • sendMessageToBotAndExpectSaveWithNoResponse(msg: IMessage | string): BotTester
    • +
    • sendMessageToBotAndExpectSaveWithNoResponse(msg: IMessage | string): IBotTester
    @@ -372,13 +402,14 @@

    Returns

    sendMessageToBotIgnoringResponseOrder

      -
    • sendMessageToBotIgnoringResponseOrder(msg: IMessage | string, ...expectedResponses: (string | RegExp | IMessage | (string | RegExp | IMessage)[])[]): BotTester
    • +
    • sendMessageToBotIgnoringResponseOrder(msg: IMessage | string, ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]): IBotTester
    • Parameters

      @@ -387,10 +418,10 @@

      Parameters

      msg: IMessage | string
    • -
      Rest ...expectedResponses: (string | RegExp | IMessage | (string | RegExp | IMessage)[])[]
      +
      Rest ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]
    -

    Returns BotTester

    +

    Returns IBotTester

    @@ -398,13 +429,13 @@

    Returns

    Private sendMessageToBotInternal

      -
    • sendMessageToBotInternal(message: IMessage, expectedResponses: (string | RegExp | IMessage | (string | RegExp | IMessage)[])[], ignoreOrder?: boolean): BotTester
    • +
    • sendMessageToBotInternal(message: IMessage, expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[], ignoreOrder?: boolean): BotTester
    • @@ -421,7 +452,7 @@
      message: IMessage
    • -
      expectedResponses: (string | RegExp | IMessage | (string | RegExp | IMessage)[])[]
      +
      expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]

      expected responses

      @@ -434,35 +465,51 @@

      Returns

    +
    + +

    setTimeout

    +
      +
    • setTimeout(milliseconds: number): BotTester
    • +
    + +

    then

    • -
      -
      -

      Works exactly like Promise's .then function, except that the return value is not passed as an arg to the next function (even if its - another .then)

      -
      -

      Parameters

      • fn: Function
        -
        -

        some function to run

        -
      -

      Returns BotTester

      +

      Returns IBotTester

    @@ -470,27 +517,23 @@

    Returns

    wait

      -
    • wait(delayInMilliseconds: number): BotTester
    • +
    • wait(delayInMilliseconds: number): IBotTester
    @@ -535,6 +578,9 @@

    Returns "assertionLibraries/IExpectation" +
  • + "builtInMessageFilters" +
  • "config"
  • @@ -554,7 +600,7 @@

    Returns bot
  • - defaultAddress + config
  • messageService @@ -565,12 +611,21 @@

    Returns testSteps

  • +
  • + addMessageFilter +
  • checkSession
  • convertToIMessage
  • +
  • + ignoreEndOfConversationEvent +
  • +
  • + ignoreTypingEvent +
  • runTest
  • @@ -586,6 +641,9 @@

    Returns sendMessageToBotInternal +
  • + setTimeout +
  • then
  • @@ -596,6 +654,12 @@

    Returns @@ -123,6 +124,9 @@

    External modules

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/interfaces/_assertionlibraries_iexpectation_.iexpectation.html b/docs/interfaces/_assertionlibraries_iexpectation_.iexpectation.html index c0846f8..d220e94 100644 --- a/docs/interfaces/_assertionlibraries_iexpectation_.iexpectation.html +++ b/docs/interfaces/_assertionlibraries_iexpectation_.iexpectation.html @@ -117,7 +117,7 @@

    notToBeEmpty

  • Returns void

    @@ -134,7 +134,7 @@

    toBeTrue

  • Returns void

    @@ -151,7 +151,7 @@

    toDeeplyInclude

  • Parameters

    @@ -174,7 +174,7 @@

    toEqual

  • Parameters

    @@ -197,7 +197,7 @@

    toInclude

  • Parameters

    @@ -251,6 +251,9 @@

    Returns void "assertionLibraries/IExpectation"

  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/interfaces/_bottester_.ibottester.html b/docs/interfaces/_bottester_.ibottester.html new file mode 100644 index 0000000..69901c1 --- /dev/null +++ b/docs/interfaces/_bottester_.ibottester.html @@ -0,0 +1,501 @@ + + + + + + IBotTester | bot-tester + + + + + +
    +
    +
    +
    + +
    +
    + Options +
    +
    + All +
      +
    • Public
    • +
    • Public/Protected
    • +
    • All
    • +
    +
    + + + + +
    +
    + Menu +
    +
    +
    +
    +
    +
    + +

    Interface IBotTester

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Test builder/runner suite. After any of these are called, no functions in IConfigModified should be accessible

    +
    +
    +
    +
    +

    Hierarchy

    +
      +
    • + IBotTester +
    • +
    +
    +
    +

    Implemented by

    + +
    +
    +

    Index

    +
    + +
    +
    +
    +

    Methods

    +
    + +

    checkSession

    + +
      +
    • + +
      +
      +

      loads a session associated with an address and passes it to a user defined function

      +
      +
      +

      Parameters

      +
        +
      • +
        sessionCheckerFunction: checkSessionFunction
        +
        +

        function passed in to inspect message

        +
        +
      • +
      • +
        Optional address: IAddress
        +
        +

        (Optional) address of the session to load. Defaults to bot's default address if not defined

        +
        +
      • +
      +

      Returns IBotTester

      +
    • +
    +
    +
    + +

    runTest

    +
      +
    • runTest(): Promise<__type>
    • +
    +
      +
    • + +
      +
      +

      executes each test step serially.

      +
      +
      +

      Returns Promise<__type>

      +
    • +
    +
    +
    + +

    sendMessageToBot

    +
      +
    • sendMessageToBot(msg: IMessage | string, ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]): IBotTester
    • +
    +
      +
    • + +
      +
      +

      sends a message to a bot and compares bot responses against expectedResponsess. Expected responses can be a variable number of args, + each of which can be a single expected response of any PossibleExpectedMessageType or a collection of PossibleExpectedMessageType + that mocks a randomly selected response by the bot

      +
      +
      +

      Parameters

      +
        +
      • +
        msg: IMessage | string
        +
        +

        message to send to bot

        +
        +
      • +
      • +
        Rest ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]
        +
        +

        (Optional) responses the bot-tester framework checks against

        +
        +
      • +
      +

      Returns IBotTester

      +
    • +
    +
    +
    + +

    sendMessageToBotAndExpectSaveWithNoResponse

    +
      +
    • sendMessageToBotAndExpectSaveWithNoResponse(msg: IMessage | string): IBotTester
    • +
    +
      +
    • + +
      +
      +

      sends a message to the bot. This should be used whenever session.save() is used without sending a reply to the user. This exists due + to a limitation in the current implementation of the botbuilder framework

      +
      +
      +

      Parameters

      +
        +
      • +
        msg: IMessage | string
        +
        +

        message to send to bot

        +
        +
      • +
      +

      Returns IBotTester

      +
    • +
    +
    +
    + +

    sendMessageToBotIgnoringResponseOrder

    +
      +
    • sendMessageToBotIgnoringResponseOrder(msg: IMessage | string, ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]): IBotTester
    • +
    +
      +
    • + +
      +
      +

      same as sendMessageToBot, but the order of responses is not checked. This will cause the test to hang until all messages it expects + are returned

      +
      +
      +

      Parameters

      +
        +
      • +
        msg: IMessage | string
        +
      • +
      • +
        Rest ...expectedResponses: (string | RegExp | IEvent | IMessage | (string | RegExp | IEvent | IMessage)[])[]
        +
      • +
      +

      Returns IBotTester

      +
    • +
    +
    +
    + +

    then

    + +
      +
    • + +
      +
      +

      Works exactly like Promise's .then function, except that the return value is not passed as an arg to the next function (even if its + another .then)

      +
      +
      +

      Parameters

      +
        +
      • +
        fn: Function
        +
        +

        some function to run

        +
        +
      • +
      +

      Returns IBotTester

      +
    • +
    +
    +
    + +

    wait

    +
      +
    • wait(delayInMilliseconds: number): IBotTester
    • +
    +
      +
    • + +
      +
      +

      Waits for the given delay between test steps.

      +
      +
      +

      Parameters

      +
        +
      • +
        delayInMilliseconds: number
        +
      • +
      +

      Returns IBotTester

      +
    • +
    +
    +
    +
    + +
    +
    +
    +
    +

    Legend

    +
    +
      +
    • Module
    • +
    • Object literal
    • +
    • Variable
    • +
    • Function
    • +
    • Function with type parameter
    • +
    • Index signature
    • +
    • Type alias
    • +
    +
      +
    • Enumeration
    • +
    • Enumeration member
    • +
    • Property
    • +
    • Method
    • +
    +
      +
    • Interface
    • +
    • Interface with type parameter
    • +
    • Constructor
    • +
    • Property
    • +
    • Method
    • +
    • Index signature
    • +
    +
      +
    • Class
    • +
    • Class with type parameter
    • +
    • Constructor
    • +
    • Property
    • +
    • Method
    • +
    • Accessor
    • +
    • Index signature
    • +
    +
      +
    • Inherited constructor
    • +
    • Inherited property
    • +
    • Inherited method
    • +
    • Inherited accessor
    • +
    +
      +
    • Protected property
    • +
    • Protected method
    • +
    • Protected accessor
    • +
    +
      +
    • Private property
    • +
    • Private method
    • +
    • Private accessor
    • +
    +
      +
    • Static property
    • +
    • Static method
    • +
    +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/docs/interfaces/_bottester_.ioptionsmodifier.html b/docs/interfaces/_bottester_.ioptionsmodifier.html new file mode 100644 index 0000000..7f52afd --- /dev/null +++ b/docs/interfaces/_bottester_.ioptionsmodifier.html @@ -0,0 +1,370 @@ + + + + + + IOptionsModifier | bot-tester + + + + + +
    +
    +
    +
    + +
    +
    + Options +
    +
    + All +
      +
    • Public
    • +
    • Public/Protected
    • +
    • All
    • +
    +
    + + + + +
    +
    + Menu +
    +
    +
    +
    +
    +
    + +

    Interface IOptionsModifier

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    methods that the Test builder can call to edit/modify the options. These can be called until any of the IBotTester method are called.

    +
    +
    +
    +
    +

    Hierarchy

    +
      +
    • + IOptionsModifier +
    • +
    +
    +
    +

    Implemented by

    + +
    +
    +

    Index

    +
    + +
    +
    +
    +

    Methods

    +
    + +

    addMessageFilter

    + +
      +
    • + +
      +
      +

      adds a message filter to the options.

      +
      +
      +

      Parameters

      + +

      Returns BotTester

      +
    • +
    +
    +
    + +

    ignoreEndOfConversationEvent

    +
      +
    • ignoreEndOfConversationEvent(): BotTester
    • +
    +
      +
    • + +
      +
      +

      adds prebuilt filter to ignore endOfConversationEvent

      +
      +
      +

      Returns BotTester

      +
    • +
    +
    +
    + +

    ignoreTypingEvent

    + + +
    +
    + +

    setTimeout

    +
      +
    • setTimeout(milliseconds: number): BotTester
    • +
    +
      +
    • + +
      +
      +

      sets the timeout time that the BotTester will wait for any particular message before failing

      +
      +
      +

      Parameters

      +
        +
      • +
        milliseconds: number
        +
      • +
      +

      Returns BotTester

      +
    • +
    +
    +
    +
    + +
    +
    +
    +
    +

    Legend

    +
    +
      +
    • Module
    • +
    • Object literal
    • +
    • Variable
    • +
    • Function
    • +
    • Function with type parameter
    • +
    • Index signature
    • +
    • Type alias
    • +
    +
      +
    • Enumeration
    • +
    • Enumeration member
    • +
    • Property
    • +
    • Method
    • +
    +
      +
    • Interface
    • +
    • Interface with type parameter
    • +
    • Constructor
    • +
    • Property
    • +
    • Method
    • +
    • Index signature
    • +
    +
      +
    • Class
    • +
    • Class with type parameter
    • +
    • Constructor
    • +
    • Property
    • +
    • Method
    • +
    • Accessor
    • +
    • Index signature
    • +
    +
      +
    • Inherited constructor
    • +
    • Inherited property
    • +
    • Inherited method
    • +
    • Inherited accessor
    • +
    +
      +
    • Protected property
    • +
    • Protected method
    • +
    • Protected accessor
    • +
    +
      +
    • Private property
    • +
    • Private method
    • +
    • Private accessor
    • +
    +
      +
    • Static property
    • +
    • Static method
    • +
    +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/docs/interfaces/_config_.iconfig.html b/docs/interfaces/_config_.iconfig.html index c314bbd..9767185 100644 --- a/docs/interfaces/_config_.iconfig.html +++ b/docs/interfaces/_config_.iconfig.html @@ -83,6 +83,9 @@

    Index

    Properties

    @@ -97,7 +100,7 @@

    Optional defaultAddressdefaultAddress: IAddress
    @@ -106,13 +109,58 @@

    Optional defaultAddress

    +
    + +

    Optional ignoreEndOfConversationEvent

    +
    ignoreEndOfConversationEvent: boolean
    + +
    +
    +

    ignores end of conversation event messages

    +
    +
    +
    +
    + +

    Optional ignoreTypingEvent

    +
    ignoreTypingEvent: boolean
    + +
    +
    +

    ignores typing event messages

    +
    +
    +
    +
    + +

    Optional messageFilters

    +
    messageFilters: MessageFilter[]
    + +
    +
    +

    filters for messages that the BotTester framework should use

    +
    +
    +

    Optional timeout

    timeout: number
    @@ -162,6 +210,9 @@

    Optional timeout

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • @@ -177,6 +228,15 @@

    Optional timeout

  • defaultAddress
  • +
  • + ignoreEndOfConversationEvent +
  • +
  • + ignoreTypingEvent +
  • +
  • + messageFilters +
  • timeout
  • @@ -184,6 +244,9 @@

    Optional timeout

    +
    +

    Interfaces

    + +

    Type aliases

      @@ -91,7 +98,7 @@

      checkSessionFunction

      checkSessionFunction: function
      @@ -157,6 +164,9 @@

      Returns void "assertionLibraries/IExpectation" +
    • + "builtInMessageFilters" +
    • "config"
    • @@ -167,6 +177,12 @@

      Returns void BotTester +
    • + IBotTester +
    • +
    • + IOptionsModifier +
    • checkSessionFunction
    • diff --git a/docs/modules/_builtinmessagefilters_.html b/docs/modules/_builtinmessagefilters_.html new file mode 100644 index 0000000..8a181ac --- /dev/null +++ b/docs/modules/_builtinmessagefilters_.html @@ -0,0 +1,290 @@ + + + + + + "builtInMessageFilters" | bot-tester + + + + + +
      +
      +
      +
      + +
      +
      + Options +
      +
      + All +
        +
      • Public
      • +
      • Public/Protected
      • +
      • All
      • +
      +
      + + + + +
      +
      + Menu +
      +
      +
      +
      +
      +
      + +

      External module "builtInMessageFilters"

      +
      +
      +
      +
      +
      +
      +
      +

      Index

      +
      + +
      +
      +
      +

      Functions

      +
      + +

      ignoreEndOfConversationEventFilter

      +
        +
      • ignoreEndOfConversationEventFilter(message: IMessage): boolean
      • +
      + +
      +
      + +

      ignoreInternalSaveMessageFilter

      +
        +
      • ignoreInternalSaveMessageFilter(message: IMessage): boolean
      • +
      + +
      +
      + +

      ignoreTypingEventFilter

      +
        +
      • ignoreTypingEventFilter(message: IMessage): boolean
      • +
      + +
      +
      +
      + +
      +
      +
      +
      +

      Legend

      +
      +
        +
      • Module
      • +
      • Object literal
      • +
      • Variable
      • +
      • Function
      • +
      • Function with type parameter
      • +
      • Index signature
      • +
      • Type alias
      • +
      +
        +
      • Enumeration
      • +
      • Enumeration member
      • +
      • Property
      • +
      • Method
      • +
      +
        +
      • Interface
      • +
      • Interface with type parameter
      • +
      • Constructor
      • +
      • Property
      • +
      • Method
      • +
      • Index signature
      • +
      +
        +
      • Class
      • +
      • Class with type parameter
      • +
      • Constructor
      • +
      • Property
      • +
      • Method
      • +
      • Accessor
      • +
      • Index signature
      • +
      +
        +
      • Inherited constructor
      • +
      • Inherited property
      • +
      • Inherited method
      • +
      • Inherited accessor
      • +
      +
        +
      • Protected property
      • +
      • Protected method
      • +
      • Protected accessor
      • +
      +
        +
      • Private property
      • +
      • Private method
      • +
      • Private accessor
      • +
      +
        +
      • Static property
      • +
      • Static method
      • +
      +
      +
      +
      +
      + + + + + \ No newline at end of file diff --git a/docs/modules/_config_.html b/docs/modules/_config_.html index b0254e9..ad8a36f 100644 --- a/docs/modules/_config_.html +++ b/docs/modules/_config_.html @@ -74,6 +74,12 @@

      Interfaces

    • IConfig
    +
    +

    Type aliases

    + +

    Variables

      @@ -84,6 +90,45 @@

      Variables

    +
    +

    Type aliases

    +
    + +

    MessageFilter

    +
    MessageFilter: function
    + +
    +
    +

    Returns true if a message

    +
    +
    +
    +

    Type declaration

    +
      +
    • +
        +
      • (message: IMessage): boolean
      • +
      +
        +
      • +

        Parameters

        +
          +
        • +
          message: IMessage
          +
        • +
        +

        Returns boolean

        +
      • +
      +
    • +
    +
    +
    +

    Variables

    @@ -92,7 +137,7 @@

    NO_TIMEOUT

    NO_TIMEOUT: -1 = -1
    @@ -107,7 +152,7 @@

    config

    config: IConfig = configInternal
    @@ -152,6 +197,9 @@

    config

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • @@ -162,6 +210,9 @@

    config

  • IConfig
  • +
  • + MessageFilter +
  • NO_TIMEOUT
  • diff --git a/docs/modules/_expectedmessage_.html b/docs/modules/_expectedmessage_.html index 3561401..92b25f6 100644 --- a/docs/modules/_expectedmessage_.html +++ b/docs/modules/_expectedmessage_.html @@ -98,7 +98,7 @@

    PossibleExpectedMessageCollections

    PossibleExpectedMessageCollections: PossibleExpectedMessageType[]
    @@ -111,10 +111,10 @@

    PossibleExpectedMessageCollections

    PossibleExpectedMessageType

    -
    PossibleExpectedMessageType: string | IMessage | RegExp
    +
    PossibleExpectedMessageType: string | IMessage | RegExp | IEvent
    @@ -164,6 +164,9 @@

    PossibleExpectedMessageType

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/modules/_index_.html b/docs/modules/_index_.html index 30ffec0..b03378f 100644 --- a/docs/modules/_index_.html +++ b/docs/modules/_index_.html @@ -104,6 +104,9 @@

    External module "index"

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/modules/_messageservice_.html b/docs/modules/_messageservice_.html index dcf5b67..37b4d1d 100644 --- a/docs/modules/_messageservice_.html +++ b/docs/modules/_messageservice_.html @@ -91,7 +91,7 @@

    botToUserMessageCheckerFunction

    botToUserMessageCheckerFunction: function
    @@ -157,6 +157,9 @@

    Returns void "assertionLibraries/IExpectation" +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/modules/_outgoingmessagecomparator_.html b/docs/modules/_outgoingmessagecomparator_.html index efa7651..9d1da7f 100644 --- a/docs/modules/_outgoingmessagecomparator_.html +++ b/docs/modules/_outgoingmessagecomparator_.html @@ -117,6 +117,9 @@

    Classes

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/modules/_sessionservice_.html b/docs/modules/_sessionservice_.html index 4d52cbf..74b317b 100644 --- a/docs/modules/_sessionservice_.html +++ b/docs/modules/_sessionservice_.html @@ -117,6 +117,9 @@

    Classes

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/docs/modules/_testconnector_.html b/docs/modules/_testconnector_.html index a6c961a..38aec2a 100644 --- a/docs/modules/_testconnector_.html +++ b/docs/modules/_testconnector_.html @@ -117,6 +117,9 @@

    Classes

  • "assertionLibraries/IExpectation"
  • +
  • + "builtInMessageFilters" +
  • "config"
  • diff --git a/package.json b/package.json index 2b1c8cf..c5b2003 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bot-tester", - "version": "3.0.2", + "version": "3.1.0", "description": "Easily test bots made with the bot builder framework", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/BotTester.ts b/src/BotTester.ts index 0559f99..c4207ba 100644 --- a/src/BotTester.ts +++ b/src/BotTester.ts @@ -1,6 +1,7 @@ import * as Promise from 'bluebird'; import { IAddress, IMessage, Message, Session, UniversalBot } from 'botbuilder'; -import { config, IConfig } from './config'; +import { ignoreEndOfConversationEventFilter, ignoreTypingEventFilter } from './builtInMessageFilters'; +import { config, IConfig, MessageFilter } from './config'; import { ExpectedMessage, PossibleExpectedMessageCollections, PossibleExpectedMessageType } from './ExpectedMessage'; import { botToUserMessageCheckerFunction, MessageService } from './MessageService'; import { SessionService } from './SessionService'; @@ -10,51 +11,159 @@ export type checkSessionFunction = (s: Session) => void; type TestStep = () => Promise; //tslint:enable +/** + * methods that the Test builder can call to edit/modify the options. These can be called until any of the IBotTester method are called. + */ +export interface IOptionsModifier { + /** + * adds a message filter to the options. + * @param filter message filter to add + */ + addMessageFilter(filter: MessageFilter): BotTester; + + /** + * sets the timeout time that the BotTester will wait for any particular message before failing + */ + setTimeout(milliseconds: number): BotTester; + + /** + * adds prebuilt filter to ignore typing event + */ + ignoreTypingEvent(): BotTester; + + /** + * adds prebuilt filter to ignore endOfConversationEvent + */ + ignoreEndOfConversationEvent(): BotTester; +} + +/** + * Test builder/runner suite. After any of these are called, no functions in IConfigModified should be accessible + */ +export interface IBotTester { + /** + * executes each test step serially. + */ + runTest(): Promise<{}>; + + /** + * loads a session associated with an address and passes it to a user defined function + * @param sessionCheckerFunction function passed in to inspect message + * @param address (Optional) address of the session to load. Defaults to bot's default address if not defined + */ + checkSession(sessionCheckerFunction: checkSessionFunction, address?: IAddress): IBotTester; + + /** + * sends a message to a bot and compares bot responses against expectedResponsess. Expected responses can be a variable number of args, + * each of which can be a single expected response of any PossibleExpectedMessageType or a collection of PossibleExpectedMessageType + * that mocks a randomly selected response by the bot + * @param msg message to send to bot + * @param expectedResponses (Optional) responses the bot-tester framework checks against + */ + sendMessageToBot( + msg: IMessage | string, + // currently only supports string RegExp IMessage + ...expectedResponses: (PossibleExpectedMessageType | PossibleExpectedMessageType[])[]): IBotTester; + + /** + * same as sendMessageToBot, but the order of responses is not checked. This will cause the test to hang until all messages it expects + * are returned + */ + sendMessageToBotIgnoringResponseOrder( + msg: IMessage | string, + // currently only supports string RegExp IMessage + ...expectedResponses: (PossibleExpectedMessageType | PossibleExpectedMessageType[])[] + ): IBotTester; + + /** + * sends a message to the bot. This should be used whenever session.save() is used without sending a reply to the user. This exists due + * to a limitation in the current implementation of the botbuilder framework + * + * @param msg message to send to bot + */ + sendMessageToBotAndExpectSaveWithNoResponse(msg: IMessage | string): IBotTester; + + /** + * Works exactly like Promise's .then function, except that the return value is not passed as an arg to the next function (even if its + * another .then) + * @param fn some function to run + */ + then(fn: Function): IBotTester; + + /** + * Waits for the given delay between test steps. + * @param delayInMiliseconds time to wait in milliseconds + */ + wait(delayInMilliseconds: number): IBotTester; +} + /** * Test builder and runner for botbuilder bots */ -export class BotTester { +export class BotTester implements IBotTester, IOptionsModifier { private bot: UniversalBot; - private defaultAddress: IAddress; private sessionLoader: SessionService; + + // this is instantiated in the runTest function. This is done to allow any changes to the config to accumulate private messageService: MessageService; private testSteps: TestStep[]; + private config: IConfig; - //tslint:disable - /** - * - * @param bot bot that will be tested against - * @param options (optional) options to pass to bot. Sets the default address and test timeout - */ - //tslint:enable constructor(bot: UniversalBot, options: IConfig = config) { - const defaultAndInputOptionMix = Object.assign({}, config, options); + this.config = Object.assign({}, config, options); + this.config.messageFilters = this.config.messageFilters.slice(); this.bot = bot; - this.defaultAddress = defaultAndInputOptionMix.defaultAddress; - this.messageService = new MessageService(bot, defaultAndInputOptionMix); + this.messageService = new MessageService(bot, this.config); this.sessionLoader = new SessionService(bot); this.testSteps = [] as TestStep[]; } + public addMessageFilter(messageFilter: MessageFilter): BotTester { + this.config.messageFilters.push(messageFilter); + + return this; + } + + public setTimeout(milliseconds: number): BotTester { + this.config.timeout = milliseconds; + + return this; + } + + public ignoreEndOfConversationEvent(): BotTester { + this.config.ignoreEndOfConversationEvent = true; + + return this; + } + + public ignoreTypingEvent(): BotTester { + this.config.ignoreTypingEvent = true; + + return this; + } + /** - * executes each test step serially + * Initializes the MessegeService here to allow config changes to accumulate */ - //tslint:disable - public runTest(): Promise { - //tslint:enable + public runTest(): Promise<{}> { + if (this.config.ignoreTypingEvent) { + this.config.messageFilters.push(ignoreTypingEventFilter); + } + + if (this.config.ignoreEndOfConversationEvent) { + this.config.messageFilters.push(ignoreEndOfConversationEventFilter); + } + + this.messageService = new MessageService(this.bot, this.config); + return Promise.mapSeries(this.testSteps, (fn: TestStep) => fn()); } - /** - * loads a session associated with an address and passes it to a user defined function - * @param sessionCheckerFunction function passed in to inspect message - * @param address (Optional) address of the session to load. Defaults to bot's default address if not defined - */ public checkSession( sessionCheckerFunction: checkSessionFunction, address?: IAddress - ): BotTester { - const runSessionChecker = () => this.sessionLoader.getSession(address || this.defaultAddress) + ): IBotTester { + const runSessionChecker = () => this.sessionLoader.getSession(address || this.config.defaultAddress) .then(sessionCheckerFunction); this.testSteps.push(runSessionChecker); @@ -62,18 +171,11 @@ export class BotTester { return this; } - /** - * sends a message to a bot and compares bot responses against expectedResponsess. Expected responses can be a variable number of args, - * each of which can be a single expected response of any PossibleExpectedMessageType or a collection of PossibleExpectedMessageType - * that mocks a randomly selected response by the bot - * @param msg message to send to bot - * @param expectedResponses (Optional) responses the bot-tester framework checks against - */ public sendMessageToBot( msg: IMessage | string, // currently only supports string RegExp IMessage ...expectedResponses: (PossibleExpectedMessageType | PossibleExpectedMessageType[])[] - ): BotTester { + ): IBotTester { const message = this.convertToIMessage(msg); // possible that expected responses may be undefined. Remove them @@ -86,7 +188,7 @@ export class BotTester { msg: IMessage | string, // currently only supports string RegExp IMessage ...expectedResponses: (PossibleExpectedMessageType | PossibleExpectedMessageType[])[] - ): BotTester { + ): IBotTester { const message = this.convertToIMessage(msg); // possible that expected responses may be undefined. Remove them @@ -95,38 +197,19 @@ export class BotTester { return this.sendMessageToBotInternal(message, expectedResponses, true); } - /** - * sends a message to the bot. This should be used whenever session.save() is used without sending a reply to the user. This exists due - * to a limitation in the current implementation of the botbuilder framework - * - * @param msg message to send to bot - */ - public sendMessageToBotAndExpectSaveWithNoResponse( - msg: IMessage | string - ): BotTester { + public sendMessageToBotAndExpectSaveWithNoResponse(msg: IMessage | string): IBotTester { const message = this.convertToIMessage(msg); return this.sendMessageToBotInternal(message, [this.sessionLoader.getInternalSaveMessage(message.address)]); } - /** - * Works exactly like Promise's .then function, except that the return value is not passed as an arg to the next function (even if its - * another .then) - * @param fn some function to run - */ - //tslint:disable - public then(fn: Function): BotTester { - //tslint:enable + public then(fn: Function): IBotTester { this.testSteps.push(() => Promise.method(fn)()); return this; } - /** - * Waits for the given delay between test steps. - * @param delayInMiliseconds time to wait in milliseconds - */ - public wait(delayInMilliseconds: number): BotTester { + public wait(delayInMilliseconds: number): IBotTester { this.testSteps.push(() => Promise.delay(delayInMilliseconds)); return this; @@ -136,7 +219,7 @@ export class BotTester { if (typeof(msg) === 'string') { return new Message() .text(msg as string) - .address(this.defaultAddress) + .address(this.config.defaultAddress) .toMessage(); } @@ -163,9 +246,9 @@ export class BotTester { } else if (expectedResponses instanceof Array) { if (expectedResponses.length > 0) { expectedMessages = (expectedResponses as PossibleExpectedMessageCollections[]) - // tslint:disable - .map((currentExpectedResponseCollection: PossibleExpectedMessageCollections) => new ExpectedMessage(currentExpectedResponseCollection)); - // tslint:enable + + .map((currentExpectedResponseCollection: PossibleExpectedMessageCollections) => + new ExpectedMessage(currentExpectedResponseCollection)); } } diff --git a/src/ExpectedMessage.ts b/src/ExpectedMessage.ts index ed839e2..294ca54 100644 --- a/src/ExpectedMessage.ts +++ b/src/ExpectedMessage.ts @@ -1,4 +1,4 @@ -import { IMessage } from 'botbuilder'; +import { IMessage, IEvent } from 'botbuilder'; import { expect } from './assertionLibraries/IExpectation'; export enum ExpectedMessageType { @@ -10,7 +10,7 @@ export enum ExpectedMessageType { /** * Types accepted for responses checkers */ -export type PossibleExpectedMessageType = string | IMessage | RegExp; +export type PossibleExpectedMessageType = string | IMessage | RegExp | IEvent; /** * Response expectations area always collections. The collection is the set of possible responses, chosen at random. If the collection size diff --git a/src/MessageService.ts b/src/MessageService.ts index b103544..da4e8c3 100644 --- a/src/MessageService.ts +++ b/src/MessageService.ts @@ -1,7 +1,7 @@ import * as Promise from 'bluebird'; import { IAddress, IMessage, Message, Session, UniversalBot } from 'botbuilder'; import { setTimeout } from 'timers'; -import { IConfig, NO_TIMEOUT } from './config'; +import { IConfig, MessageFilter, NO_TIMEOUT } from './config'; import { ExpectedMessage } from './ExpectedMessage'; import { OutgoingMessageComparator } from './OutgoingMessageComparator'; @@ -87,7 +87,6 @@ export class MessageService { } catch (e) { return rej(e); } - }); if (!outgoingMessageComparator.expectsAdditionalMessages()) { @@ -101,12 +100,15 @@ export class MessageService { * Inject middleware to intercept outgoing messages to check their content */ private applyOutgoingMessageListener(): void { - this.bot.on('outgoing', (e: IMessage | IMessage[]) => { - if (!(e instanceof Array)) { - e = [e]; + this.bot.on('outgoing', (outgoingMessages: IMessage | IMessage[]) => { + if (!(outgoingMessages instanceof Array)) { + outgoingMessages = [outgoingMessages]; } - this.botToUserMessageChecker(e); + this.config.messageFilters.forEach( + (messageFilter: MessageFilter) => outgoingMessages = (outgoingMessages as IMessage[]).filter(messageFilter)); + + this.botToUserMessageChecker(outgoingMessages); }); } } diff --git a/src/builtInMessageFilters.ts b/src/builtInMessageFilters.ts new file mode 100644 index 0000000..b8129dd --- /dev/null +++ b/src/builtInMessageFilters.ts @@ -0,0 +1,13 @@ +import { IMessage } from 'botbuilder'; + +export function ignoreInternalSaveMessageFilter(message: IMessage): boolean { + return message.type !== '__save__'; +} + +export function ignoreEndOfConversationEventFilter(message: IMessage): boolean { + return message.type !== 'endOfConversation'; +} + +export function ignoreTypingEventFilter(message: IMessage): boolean { + return message.type !== 'typing'; +} diff --git a/src/config.ts b/src/config.ts index 2c183c7..744f1fd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,11 @@ -import { IAddress } from 'botbuilder'; +import { IAddress, IMessage } from 'botbuilder'; import * as fs from 'fs'; +/** + * Returns true if a message + */ +export type MessageFilter = (message: IMessage) => boolean; + export interface IConfig { /** * timeout in milliseconds before a BotTester runner will fail a test (when not overriden) @@ -10,6 +15,21 @@ export interface IConfig { * default address bot will use for all communication (when not overriden) */ defaultAddress?: IAddress; + + /** + * ignores typing event messages + */ + ignoreTypingEvent?: boolean; + + /** + * ignores end of conversation event messages + */ + ignoreEndOfConversationEvent?: boolean; + + /** + * filters for messages that the BotTester framework should use + */ + messageFilters?: MessageFilter[]; } const configFilePath = `bot-tester.json`; @@ -34,4 +54,6 @@ if (configFileExists) { configInternal = JSON.parse(fs.readFileSync(configFilePath, { encoding: 'utf8' })); } +configInternal.messageFilters = []; + export const config = configInternal; diff --git a/test/BotTester.spec.ts b/test/BotTester.spec.ts index aba2dc5..ef9cb55 100644 --- a/test/BotTester.spec.ts +++ b/test/BotTester.spec.ts @@ -1,9 +1,13 @@ //```javascript import { IAddress, IMessage, Message, Prompts, Session, UniversalBot } from 'botbuilder'; -import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; import { BotTester } from './../src/BotTester'; import { TestConnector } from './../src/TestConnector'; +chai.use(chaiAsPromised); +const expect = chai.expect; + const connector = new TestConnector(); // lines with //# should be converted to headers for markdown docs @@ -336,6 +340,70 @@ describe('BotTester', () => { }); //``` +//# can apply one or more message filters in the BotTester options for messages to ignore +//``` javascript + it('can apply one or more message filters in the BotTester options for messages to ignore', () => { + bot.dialog('/', (session) => { + session.send('hello'); + session.send('how'); + session.send('are'); + session.send('you?'); + }); + + const ignoreHowMessage = (message) => !message.text.includes('how'); + const ignoreAreMessage = (message) => !message.text.includes('are'); + + return new BotTester(bot, { messageFilters: [ignoreHowMessage, ignoreAreMessage]}) + .sendMessageToBot('intro', 'hello', 'you?') + .runTest(); + }); +//``` + +//# can modify BotTester options +//``` javascript + describe('can modifiy options in line in builder chain', () => { + it('add a message filter', () => { + bot.dialog('/', (session) => { + session.send('hello'); + session.send('there'); + session.send('green'); + }); + + return new BotTester(bot) + .addMessageFilter((msg) => !msg.text.includes('hello')) + .addMessageFilter((msg) => !msg.text.includes('there')) + .sendMessageToBot('hey', 'green') + .runTest(); + }); + + it('change timeout time', (done) => { + const timeout = 750; + bot.dialog('/', (session) => { + setTimeout(() => session.send('hi there'), timeout * 2 ); + }); + + expect(new BotTester(bot) + .setTimeout(timeout) + .sendMessageToBot('hey', 'hi there') + .runTest() + ).to.be.rejected.notify(done); + }); + + it('can ignore typing events', () => { + bot.dialog('/', (session) => { + session.send('hello'); + session.sendTyping(); + session.send('goodbye'); + }); + + return new BotTester(bot) + .ignoreTypingEvent() + .sendMessageToBot('hey', 'hello', 'goodbye') + .runTest(); + }); + }); +//``` + describe('Cases not for docs', () => { it('can handle undefined expectedResponses', () => { bot.dialog('/', (session: Session) => { diff --git a/test/BotTesterFailure.spec.ts b/test/BotTesterFailure.spec.ts index 1bf4d4f..37dcbd4 100644 --- a/test/BotTesterFailure.spec.ts +++ b/test/BotTesterFailure.spec.ts @@ -202,4 +202,55 @@ describe('BotTester', () => { .sendMessageToBotIgnoringResponseOrder('anything', 'NOPE?', 'hi', 'there') .runTest()).to.be.rejected.notify(done); }); + + it('will fail if a message filter is not correctly applied', (done: Function) => { + bot.dialog('/', (session: Session) => { + session.send('hello'); + session.send('how'); + session.send('are'); + session.send('you?'); + }); + + const ignoreHowMessage = (message: IMessage) => !message.text.includes('how'); + const ignoreAreMessage = (message: IMessage) => !message.text.includes('are'); + + expect(new BotTester(bot, { messageFilters: [ignoreHowMessage, ignoreAreMessage]}) + .sendMessageToBot('intro', 'hello', 'how', 'are', 'you?') + .runTest()).to.be.rejected.notify(done); + }); + + it('will fail if a endOfConversationEvent is seen with an ingoreEndOfConversationEventFilter', (done: Function) => { + bot.dialog('/', (session: Session) => { + session.send('hello'); + session.endConversation(); + }); + + expect(new BotTester(bot) + // need to timeout before the tests do to catch the error + .setTimeout(500) + .ignoreEndOfConversationEvent() + //tslint:disable + .sendMessageToBot('hey', 'hello', {type: 'endOfConversation'} as any) + //tslint:enable + .runTest()) + .to.be.rejected.notify(done); + }); + + it('will fail if a typing event is seen with an ignoreTypingEventFilter', (done: Function) => { + bot.dialog('/', (session: Session) => { + session.send('hello'); + session.sendTyping(); + session.send('hey'); + }); + + expect(new BotTester(bot) + // need to timeout before the tests do to catch the error + .setTimeout(500) + .ignoreTypingEvent() + //tslint:disable + .sendMessageToBot('hey', 'hello', {type: 'typing'} as any, 'hey') + //tslint:enable + .runTest()) + .to.be.rejected.notify(done); + }); });