DEV Community

loading...
Cover image for How to Test Slack Notifications
platformOS

How to Test Slack Notifications

pavelloz profile image Paweł Kowalski Originally published at platformos.com Updated on ・4 min read

Marketing forms are often connected to a third-party system to help the marketing team provide faster and more accurate responses.

We integrated our contact page with Slack, HubSpot, SendGrid, and emails. Whenever someone fills in the form, we notify the appropriate people via email, Slack message, and create records in HubSpot and SendGrid for future management of those contacts.

Contact form

One day we received the email, but the Slack notification did not come through, and this made me think about testing Slack notifications to catch regressions in this area.

To achieve this, we need two things:

  • A test channel for test messages
  • A test that will send the form for us

platformOS notification setup

platformOS API Call notifications support WebHooks, so that's what we used for Slack messages. The setup involves only a couple of lines of code, but the most important in the context of this article is the WebHook URL.

---
name: slack_landing_sales
delay: '0'
enabled: true
format: http
headers: '{ "Content-Type": "application/json" }'
request_type: POST
to: https://hooks.slack.com/services/XXX/XXX/XXX
trigger_condition: true
---
{
"text": "
Heads up! Contact from {{ form.properties.url }}.
Name: {{ form.properties.first_name }} {{ form.properties.last_name }}
Email: {{ form.properties.email }}
Phone: {{ form.properties.phone }}
Comments: {{ form.properties.description }}",
} 
Enter fullscreen mode Exit fullscreen mode

The line to change is the one with to: [https://hooks.slack.com/services/XXX/XXX/XXX](https://hooks.slack.com/services/XXX/XXX/XXX) which I censored. You need your own webhook URL to be able to send messages to your channel.

To not send test data to the production Slack channel, it is a good idea to differentiate production from everything else:

to: >
  {% if form.properties.url contains 'https://www.platformos.com' %}
  https://hooks.slack.com/services/XXX/XXX/XXX
  {% else %}
  https://hooks.slack.com/services/YYY/YYY/YYY
  {% endif %}
Enter fullscreen mode Exit fullscreen mode

This if condition will check if the form field called url contains a particular string. Because we are populating it before sending the form, it is filled in with the URL of the instance. In the case of our production site, it is https://www.platformos.com.

E2E test in TestCafe

Now, we need to programmatically go through the form, fill it, send it, and validate that it has been sent successfully.

We use TestCafe for E2E tests. It is not too difficult to start using it if you have experience with testing.

import { Selector } from 'testcafe';
import { BASE_URL } from './env';
import faker from 'faker';

fixture('Contact').page(`${BASE_URL}/contact`);

test('Contact form works', async (t) => {
  const fn = Selector('[name="form[properties_attributes][first_name]"]');
  const ln = Selector('[name="form[properties_attributes][last_name]"]');
  const email = Selector('[name="form[properties_attributes][email]"]');
  const phone = Selector('[name="form[properties_attributes][phone]"]');
  const description = Selector('[name="form[properties_attributes][description]"]');
  const submitBtn = Selector('button').withText('SUBMIT');

  const notice = Selector('[role="alert"]').withText('Your contact form has been sent');

  await t
    .typeText(fn, faker.name.firstName())
    .typeText(ln, faker.name.lastName())
    .typeText(email, faker.internet.email())
    .typeText(phone, faker.phone.phoneNumber())
    .typeText(description, faker.lorem.paragraph(), { paste: true });

  await t.click(submitBtn);

  await t.expect(notice.exists).ok();
});
Enter fullscreen mode Exit fullscreen mode

A short summary of what is going on here:

  1. Importing TestCafe and faker (generates fake data so that the test varies every time it is run)
  2. Telling TestCafe the URL at which the test will be run
  3. Defining selectors for all the DOM elements we will be interacting with
  4. Filling in all the data in the form
  5. Submitting the form
  6. Checking if the Your contact form has been sent message is visible after the form has been sent

Running the test in chromium results in a pretty video:

TestCafe running

In your terminal, you should see something similar after running TestCafe:

> testcafe chromium tests --video artifacts --video-encoding-options r=20

 Running tests in:
 - Chrome 88.0.4295.0 / macOS 10.15.7

 Contact
 ✓ Contact form works

 1 passed (38s)
Enter fullscreen mode Exit fullscreen mode

This means that the test passed, so now it is time to verify if the Slack notification came through. This is what this test generated:

Slack message

Continuous Integration

To make our lives even more automated, we add the npm run test-ci command to our CI workflow. For this project, we use Jenkins, but you might use Github Actions, Travis, or CircleCI if you prefer. Remember that your CI server has to have a browser supported by TestCafe (see the list of officially supporter browsers here).

In our case, making tests run on every master branch run was similar to:

stage('Test on URL') {
    agent { docker { image "platformos/testcafe" } }
    environment { MP_URL = "${params.MP_URL}" }
    steps {
      sh 'npm run test-ci'
    }
    post { failure { archiveArtifacts "screenshots/" } }
}
Enter fullscreen mode Exit fullscreen mode

We also use a different command on CI because we want to take screenshots of failures only and run the test in a headless browser (it is much faster — the test above runs in 6 seconds instead of 38):

testcafe 'chromium:headless' --screenshots-on-fails --screenshots=screenshots tests
Enter fullscreen mode Exit fullscreen mode

Now every time any code is merged into the master branch, TestCafe will test this form and trigger the Slack webhook. If the message will be missing one day, or if the test fails, we will know something is wrong either on our side or Slack's.

Resources

I hope this guide will help you avoid some of the regressions. Here are some resources that you might find useful if you decide to follow our path:

platformOS Website

platformOS Documentation

Slack - Creating App with WebHooks

TestCafe testing framework

faker npm package

Read more

If you are interested in more performance oriented content, follow me and I promise to deliver original, or at least effective methods of improving your website.

Discussion

pic
Editor guide