README
slack-mock
A Slack API mocker for all your Slack bot and Slack app integration tests.
Mock All Slack APIs
Slack Mock will mock a way of pushing data into Slack. You can use it to mock calls to
You can use your API calls as is without changing any URLs or tokens. Slack Mock will capture all outbound HTTP requests to https://slack.com
and https://hooks.slack.com
, so Slack will never receive your API calls.
With Slack-Mock you can inspect all outbound requests and trigger incoming requests to make sure your bot is doing the right thing.
No Magic Included
OK, there's a little magic included in capturing HTTP requests, but that's it. No timeouts, magic promises, or events. Integration tests are hard, trying to make them easy with "convenience" abstractions that are out of your control only makes them harder.
Integration test by their nature are testing a closed system: you are inspecting from the outside a complex flow between at least two entities (your bot and the Slack API) and there is no guaranteed way to know when that flow is complete by observing from the outside. Any attempt to guess when the communication is complete will be wrong some of the time and just cause you frustration.
That's why Slack Mock provides simple, synchronous methods to queue, trigger, and inspect messages to and from Slack. No magic included.
To write a Slack Mock integration test queue up responses from Slack to your bot, then use Slack Mock to send a message from Slack to your bot to trigger a bot action, wait some time, then assert that your bot made the correct calls to Slack in order. How long do you wait? It depends on what your bot is doing. Play around a little and see what works. I find a 50 millisecond wait is more than enough for most flows.
Usage
Incoming Webhooks
// incoming webhooks
import * as SlackMock from "slack-mock-typed";
const mock: SlackMock.Instance = SlackMock.SlackMocker({ logLevel: "debug" });
function setup() {
beforeAll(async () => {
jest.setTimeout(60000);
await mock.incomingWebhooks.start();
await mock.incomingWebhooks.reset();
});
beforeEach(async () => {
jest.resetModules();
await mock.incomingWebhooks.reset();
expect(mock.incomingWebhooks.calls).toHaveLength(0);
});
afterEach(async () => {
await mock.incomingWebhooks.reset();
});
}
function returnMockedSlackWebhookCall() {
expect(mock.incomingWebhooks.calls).toHaveLength(1);
const firstCall = mock.incomingWebhooks.calls[0];
expect(firstCall.url).toEqual(process.env.SLACK_WEBHOOK_URL);
const body = firstCall.params;
return body;
}
API Conventions
Slack Mock will intercept all requests to https://hooks.slack.com
. There's no need to change any URLs in your bot.
Here are the method conventions. Not every API wrapper supports each of these methods, see the API docs below:
addResponse
will add the next response returned. You can call mutlitple times to queue responses. If you set aurl
option, then the response will only be returned for that url. URL specific responses take precedence over unspecified responsescalls
will be in order received and always contain params, headers, and url. Params contain both query params and body properties.reset
will always clear calls and any queued responses you have.
There is also a top level reset
convenience method that will call reset on each API wrapper.
Slack mock will respond to all requests with a 200 OK unless a custom response has been queued. For web requests, a the default body will be {ok: true}
.
API
: require('slack-mock')function(config)
The exported function used to start the Slack Mock server. Returns an instance of the server.
Slack Mock is a singleton so can only be configured once per process. Subsequent calls to SlackMocker() will return the same instance.
Config options are:
logLevel
(String, optional) The log level to use. One oferror
,warn
,info
,verbose
,debug
, orsilly
. Defaults toinfo
.
instance
The configured instance of the Slack Mock SlackMocker.instance
object. This is the same object returned from require('slack-mock')(config)
.
(Incoming Webhooks) instance.incomingWebhooks
The incomingWebhooks
object mocks receiving payloads from you Slack App to all Incoming Webhooks at https://hooks.slack.com/
.
addResponse
:function(opts)
Queues a response payload that Slack Mock will use to respond upon receiving a post to a registered endpoint. This method can be called multiple times. Responses will be used in a FIFO order. Options are:url
(String, optional) The Incoming Webhook URL your app will be POSTing to.statusCode
(Number, optional) The HTTP status code to reply with. Defaults to 200.body
(Object, optional) The response body to reply with. Defaults toOK
.headers
(Object, optional) The HTTP headers to reply with. Defaults to{}
.
reset
:function()
Empties theincomingWebhooks.calls
array and clears any queued responses.calls
:Array
An array of payloads received your from Slack app to an Incoming Webhook url.url
The url of the call that was intercepted.params
The POST body merged with any query string parameters captured from the intercepted request as an Object.headers
The headers of the intercepted request as an Object.
: instance.resetfunction()
Resets all mocks. A convenience method for calling reset on individual API mocks.