Giter Club home page Giter Club logo

botkit-mock's Issues

Support replyAndUpdate

It would be great if this mock library could also support the replyAndUpdate function from botkit.

Thanks for the library!

bot.whisper is not a function

is this library still maintained? i am using the your test framework to test against slack. Wondering if i can add bot.whisper to your interface as i am using it and its part of botkit now

How to write a conversation test-case when bot says something first before asking

Hi,

I am struggling to setup a test for the example skill (I found it here) below. Currently I am trying to get into the Conversation Testing Thing. I also checked your convo-tests but did not succeed. Can you please help me?

module.exports = function(controller) {

  controller.hears(['cookies'], 'message_received', function(bot, message) {

    bot.startConversation(message, function(err, convo) {

      if (!err) {
        // if the user does not answer within this time, we end the conversation
        convo.setTimeout(5000);

        convo.say('Did someone say cookies!?!!');
        convo.ask('What is your favorite type of cookie?', function(response, convo) {

          convo.say(`Golly, I love ${response.text} too!!!`);
          convo.next();
        });
      }
    });
  });
};

@slack/web-api dependency causes `invalid_auth` throws on every instantiation of adapter

Hi folks,

Botkit 4.5.

Noticed while trying to build out integration tests that we kept getting a little blurb like this:

{ Error: An API error occurred: invalid_auth at Object.platformErrorFromResult (.../@slack/web-api/dist/errors.js:50:33) at WebClient.apiCall (.../node_modules/@slack/web-api/dist/WebClient.js:407:28) at process._tickCallback (internal/process/next_tick.js:68:7) code: 'slack_webapi_platform_error', data: { ok: false, error: 'invalid_auth', response_metadata: {} } }

I was able to remove this invalid_auth by stubbing out WebClient.prototype.makeRequest BEFORE the instantiation of the SlackAdapter with fake information. Wondering if the @slack/web-api dependency in botbuilder-adapter-slack has been accomodated for (or there are plans to) in this library?

Test controller.api.* (eg. Facebook's messenger_profile) functions

Hi guys,

I have again a question. How can I test (no clue yet) features of the Facebook Bot, such as this onecontroller.api.messenger_profile.get_messenger_code (there are other controller.api.* features as well).

Based on the examples of you readme, I was not able to run a test like this:

it('the bot\'s get_messenger_code should be a function', () => {
    this.controller.api.messenger_profile.get_messenger_code.should.be.a.Function();
  });

This is the skill (basically the example from the botkit repo):

module.exports = function(controller) {

  // returns the bot's messenger code image
  controller.hears(['code'], 'message_received,facebook_postback', function(bot, message) {

    controller.api.messenger_profile.get_messenger_code(2000, function(err, url) {

      if (!err) {

        const image = {
          attachment: {
            type: 'image',
            payload: {
              url,
            },
          },
        };
        bot.replyWithTyping(message, image);
      }

    });

  });

};

How to write test case for the conversations? also its failing as convo.on function is not available in botMock.js

How to test conversations, I have a controller which asks the ques to user on "Who am I", if user haven't already given his name asks the user his name, Then if user provides the name then it confirms with user and then it ends the conversation. Is it possible to test conversations, any leads would be really helpful.

Pseudo Code

controller.hears("who am i", function(bot, message)) {
     bot.startConversation(message, function(err, convo) {
           convo.ask('What should I call you?', function(response, convo) {
                convo.ask('You want me to call you `' + response.text + '`?', [
                    {
                        pattern: 'yes',
                        callback: function(response, convo) {
                            convo.next();
                        }
                    },
                    {
                        pattern: 'no',
                        callback: function(response, convo) {
                            convo.stop();
                        }
                    },
                    {
                        default: true,
                        callback: function(response, convo) {
                            convo.repeat();
                            convo.next();
                        }
                    }
                ]);
                convo.next();
            }, {'key': 'nickname'}); // store the results in a field called nickname
            convo.on('end', function(convo) {
                 //Some odd logic here
            }
     });
} 

bot.identity throws on Slack

Seems similar to #28 for Facebook. bot.identity doesn't appear to be mocked so when I try to use it, I get a Slack API auth error because it's trying to use the Slack API with my dummy test credentials.

AssertionError

I keep getting undefined for message.text.

screen shot 2018-05-29 at 00 51 06

This is my code:

const assert = require('assert')
const botmock = require('botkit-mock')
const skill = require('../../server/skills/profile')

describe('[skill]: profile', function () {

  afterEach(function () {
    this.controller.shutdown()
  })

  beforeEach(function () {
    this.userInfo = {
      slackId: 'user123',
      channel: 'channel123'
    }

    this.controller = botmock({
      stats_optout: true,
      debug: false
    })

    this.bot = this.controller.spawn({
      type: 'slack'
    })

    skill(this.controller)
  })

  describe('hears profile', function () {
    beforeEach(function () {
      this.term = 'profile'
    })

    describe('as direct message', function () {
      beforeEach(function() {
        this.sequence = [
          {
            type: 'direct_message',
            user: this.userInfo.slackId,
            channel: this.userInfo.channel,
            messages: [
              {
                text: this.term,
                isAssertion: true
              }
            ]
          }
        ]
      })
      describe('with [1] trigger and [1] convos', function () {
        beforeEach(function () {
          this.bot.receive({ type: 'heard_trigger' })
          this.bot.receive({type: 'conversationStarted'})
        })

        it (`should return text: "Here's your preferences"`, function () {
          return this.bot.usersInput(this.sequence).then((message) => {
            console.log(this)
            return assert.equal(
              message.text.indexOf(`Here's your profile preferences`) > -1,
              true
            )
          })
        })
      })
    })
  })
})

Did I miss anything? I'm following the botkit-starter-slack example

Error in initialUserMessage() and storage missing

  1. You messed up the initialUserMessage() method in line 146 of BotMock, so it does not work with actual regular expressions. You take a RegEx, convert it into a String and then convert it back to a RegEx. So if I use a RegEx: /someRegEx/ it is converted to //someRegEx//i.
    So I solved it like this:

        let p = obj.pattern;
    
        if (Array.isArray(obj.pattern)) {
            for (let i = 0;i < p.length;i++) {
                if ((message.text || message).match(new RegExp(p[i], 'i'))) {
                    message.match = (message.text || message).match(p);
    
                    return (message.text || message).match(new RegExp(p[i], 'i'));
                }
            }
        } else {
            if ((message.text || message).match(new RegExp(p, 'i'))) {
                message.match = (message.text || message).match(new RegExp(p, 'i'))
            }
        }
    
        return (message.text || message).match(new RegExp(p, 'i'));
    
  2. BotMock.js does not support simple_storage:
    If you want to support that just add the simple_storage.js to your requirements, then you only have to add:

        memory_store: {
            users: {
    
            },
            channels: {
    
            },
            teams: {
    
            },
        }
    

    to line 11:
    line 11:

        this.botkit = {
            tasks: [],
            log: function(){}
        };
    

    Additionally, if you want to access the storage with your Bot you have to add the team_id or user_id to the call back:
    See this example:
    add

        this.convo.sourceMessage.username = message.username;
    

    to

        this.convo.sourceMessage.user = message.user;
        this.convo.sourceMessage.channel = message.user;
    

    in line line 77, 78

and
to line 245

        channel: this.sourceMessage.channel

add:

        user: this.sourceMessage.username

v4 is a breaking change.

Hi guys.

Manually updating the botkit dependency to the most recent version squishes botkit-mock and it rejects running tests. And of course, testing my bot's skills with the old version defeats the purpose.

How can I help get this going for the new version of Botkit? You guys already working on it?

Having trouble testing predefined botkit dialogs

I'm trying to create test cases for a predefined dialog I've created with botkit.
The dialog creation code, in botkit's main file (bot.js) looks a bit like this -

function createServiceDialog() {
    const MY_DIALOG_ID = 'my-dialog-name-constant';
    let convo = new BotkitConversation(MY_DIALOG_ID, controller);

    convo.say('Howdy!');

    ... // I've omitted most of the dialog for brevity's sake
}

controller.addDialog(createServiceDialog());

I later use this dialog like so -

const { SlackDialog } = require('botbuilder-adapter-slack');
const { BotkitConversation } = require('botkit');
const MY_DIALOG_ID = 'my-dialog-name-constant';

module.exports = function(controller) {
    controller.hears('create_service', 'message', async(bot, message) => {
        await bot.startConversationInThread(message.channel, message.user, message.incoming_message.channelData.ts);
        await bot.beginDialog(MY_DIALOG_ID);
    });
}

If I try testing this file with hard coded messages, the tests pass just fine.
When I try to use this predefined dialog, I'm getting the following error -
(node:62437) UnhandledPromiseRejectionWarning: Error: DialogContext.beginDialog(): A dialog with an id of 'my-dialog-name-constant:botkit-wrapper' wasn't found.

I've tried porting the dialog definition into the file being tested, but that didn't work nor felt like the right approach.
How should I go about implementing such a test case?

Oh, I almost forgot, here's the test suite I'm trying to execute -

'use strict';
const assert = require('assert');
const {BotMock, SlackApiMock} = require('botkit-mock');
const {SlackAdapter, SlackMessageTypeMiddleware, SlackEventMiddleware} = require('botbuilder-adapter-slack');
const fileBeingTested = require('../features/create_service');

async function setTimeoutAsync(timeout = 100) {
    return new Promise((r) => setTimeout(r, timeout));
}

describe('create_service file slack-feature', () => {
    const initController = () => {
        const adapter = new SlackAdapter({
            clientSigningSecret: "some secret",
            botToken: "some token",
            debug: true,
        });
        adapter.use(new SlackEventMiddleware());
        adapter.use(new SlackMessageTypeMiddleware());

        this.controller = new BotMock({
            adapter: adapter,
        });

        SlackApiMock.bindMockApi(this.controller);

        fileBeingTested(this.controller);
    };

    beforeEach(() => {
        this.userInfo = {
            slackId: 'user123',
            channel: 'channel123',
        };
    });

    describe('create_service', () => {
        beforeEach(() => {
            initController();
        });
        it(`should reply in a correct sequence through message`, async () => {
            const reply = await this.controller.usersInput([
                {
                    type: 'message',
                    user: this.userInfo.slackId, //user required for each direct message
                    channel: this.userInfo.channel, // user channel required for direct message
                    messages: [
                        {
                            text: 'create_service',
                            isAssertion: true,
                        }
                    ]
                }
            ]);

            assert.strictEqual(this.controller.detailed_answers[this.userInfo.channel][0].text, `Howdy!`);
        });
    });
});

Thanks!

botkit 4.x support?

I love the idea of this project. Is it going to be updated for bot.createConversation and other botkit 4.x changes?

Audit issues with Handlebars

Hey guys,

Install is royally barfing on your handlebars dependency on 4.5. Got about 20 of these, and some DDOS warnings on the same dependency:

image

Promise bug in sample code

If I run it as written I get the following:

Error: Resolution method is overspecified. Specify a callback or return a Promise; not both.

    it('should return `help message` if user types `help`', (done)=>{
        var self = this;
        return self.controller.usersInput([{
                first:true,
                user: self.slackId,
                messages:[{text: 'help', isAssertion:true}]
            }]).then((text)=>{
                assert.equal(text, 'help message')
                done()
            })
    });

If I remove the done and just return the promise it's fine. Also, suggest adding a catch and return rejection or you miss out on important errors

    it('should return `help message` if user types `help`', ()=>{
        var self = this;
        return self.controller.usersInput([{
                first:true,
                user: self.slackId,
                messages:[{text: 'help', isAssertion:true}]
      }])
        .catch((err) => {
          return Promise.reject(err);
        }).then((text) => {
          assert.equal(text, 'help message')
        })
    });

replyWithTyping is not supported

Hey everyone. Excellent work on this mock module.

I just try to use it and it seems that atm if I use replyWithTyping it doesn't work.

Looking at the source code is not supported. Should I create a new PR or is it something you are currently working on?

Facebook bot.identity is undefined

Hello,

Facebook messenger doesn't support direct mention, so when i want to test some facebook conversations with this awesome botkit-mock, i got this error :

// BotmockWorker.js:66 -> var direct_mention = new RegExp('^\<\@' + bot.identity.id + '\>', 'i');
TypeError: Cannot read property 'id' of undefined

In BotmockWorker.js you try to prune off the bot's name and trim whitespaces, in my case bot.identity is undefined so bot.identity.id throw an error.

// Example of code
beforeEach(() => {
        let controller = Botmock({});
        bot = controller.spawn({type: 'facebook'});

        controller.hears(['hi'], 'direct_message', function(bot, message){
            bot.startConversation(message, function(response, convo){
                convo.ask('hello there', function(response, convo){
                    convo.say('..user typed any text after `hi`');
                    convo.ask('here a question', function(response, convo){
                        convo.say('here an answer');
                        convo.next();
                    });
                    convo.next();
                });
            })
        });
    });

it('should return `help message` if user types `help`', (done) => {

        let sequence = [
            {
                type: null, // direct_message, message_received, interactive_message_callback, defaults to direct_message
                user: 'someUserId', // this.userInfo.slackId
                channel: 'someChannel', //his.userInfo.channel
                messages:[
                    {
                        text: 'hi',
                    },
                    {
                        text: 'its true',
                        deep: 1,
                        isAssertion:true,
                    }
                ]
            }
        ];

        bot.usersInput(sequence).then((message) => {
            console.log(message);
            expect(message.text).toBe('help message');
            done();
        });
    });

100ms is not enough for some responses

I am using Watson Conversation in my bot and 100ms timeout (hardcoded here) is not enough.
Manually editing the file to change timeout to 1000ms makes it work, but it makes all tests slower so it isn't a good solution.
Also I want to do some processing which takes multiple seconds before sending the response.

Would it be possible to handle messages with callback on reply instead of setting a timeout? That way quick responses would be processed quickly and slow responses would get more time without making everything slow.

Multi-step Testing?

Hi guys,

We're trying to send multiple messages through a mock adapter. First message instantiates some controller events for interactive components, then we need to fake button pushes and assert against the way the bot responds. However, this.controller.detailed_answers don't populate beyond the first message sent through the controller, and we've tried it several ways. Here's how we just tried it:

it("should respond with appropriate verbiage on thumbsup click", async () => {
      this.middlewareStub.returns([{ answer: "This is a test response." }]);
      const message = await this.controller.usersInput([
        {
          type: "message",
          user: "someUserId",
          channel: "someChannel",
          ts: "1234.45",
          messages: [
            {
              text: "A qna question?",
              isAssertion: true
            }
          ]
        },
        {
          type: "block_actions",
          user: "someUserId",
          channel: "someChannel",
          messages: [
            {
              actions: [{ action_id: "qna_answered_question_undefined" }],
              response_url: "flerpity_floop",
              isAssertion: true
            }
          ]
        }
      ]);

      return assert.strictEqual(
        JSON.stringify(
          this.controller.detailed_answers.someChannel[1].channelData.blocks[1]
        ),
        JSON.stringify("poop")
      );
    });

And we've also done it this way:

it("should respond with appropriate verbiage on thumbsup click", async () => {
      this.middlewareStub.returns([{ answer: "This is a test response." }]);
      const message = await this.controller.usersInput([
        {
          type: "message",
          user: "someUserId",
          channel: "someChannel",
          ts: "1234.45",
          messages: [
            {
              text: "A qna question?",
              isAssertion: true
            },
            {
              actions: [{ action_id: "qna_answered_question_undefined" }],
              response_url: "flerpity_floop",
              isAssertion: true
            }
          ]
        }
      ]);

      return assert.strictEqual(
        JSON.stringify(
          this.controller.detailed_answers.someChannel[1].channelData.blocks[1]
        ),
        JSON.stringify("poop")
      );
    });

We've also just plain ol' called this.controller.usersInput() a second time with a message of type block_actions with no effect.

What are we doing wrong? Happy to put this in SO if you prefer.

NPM

Would be nice if it was submitted to NPM so it could be properly versioned, auto-udpated as a dependency, simpler installation, etc. ๐Ÿ˜ธ

Where is "this" coming from in the examples

I tried to setup the botkit-mock and I am a bit confused where "this" comes from

describe("controller tests",()=>{
    beforeEach(()=>{
        this.controller = Botmock({}); // is unndefined

I tried it also to just define controller and bot as variables in the test, but my testbot is still not responding.

Configurable baseUrl for use with yakbak

Hi folks,

I'd like to be able to configure the baseUrl of the underlying Axios adapter (using axios-mock-adapter) so that it hits a local endpoint spun up to use yakbak, a VCR technology so I can stub out API requests. Is that possible? I'm looking through source and I'm not seeing anywhere without monkey patching the source. Thanks.

Twilio SMS adapter?

Hi! Please feel free to point me another direction, but I was reading through this project and interested in using it for a botkit project using Twilio, and I saw a note in the README asking about folks interested in adding support for other adapters. I'm only just reading so this issue is more a question/ ๐Ÿ‘‹ . This looks like a very helpful library!

Relax deps permit use of 4.x

Currently the package.json specifies the 0.x line, which means if the application uses 4.x then two versions of botkit are installed. It would be great to permit use of the 4.x version to avoid this duplication and to shrink the size of node_modules

Events not registering for testing `controller.trigger()`

What I'm doing:

Calling this.controller.loadModule against a feature that I've created in Botkit 4.5 to instantiate a controller with its details.

What's I expect:

this.controller._events should have registered events custom defined in a feature with controller.on(<event_name>)

What I get:

Not that. controller._events is {}.

maybe I'm missing something?

middleware interface

do you guys support mocking middlewares? it doesn't look like it right now, if not do you want to?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.