Testing POST Routes

We can send 'fake' data to our POST routes to check that the response is what we expect.

We could do this manually, by entering data into a form on a browser. However, we don't need to do this and it's probably better not to. We want to test in a way that's automated and repeatable. We'll use Supertest to do our POST route testing.

Strictly speaking, this kind of test is not a unit test: we are testing our server, starting from the point where it receives a request to the moment it sends a response back to the client. Some tests involve more than one 'unit' of code, and they often follow the same path as a user making a request from the browser... we're just skipping the browser part!

Example: checking for confirmation

Say we have a route that renders a Handlebars template and returns HTML confirming the form submission. We could test this like so:

import request from 'supertest'
test("POST '/' returns confirmation including name", async () => {
// Arrange
const formData = {
name: 'flargle',
address: '1 Flargle Lane'
}
const expected = 'Your submission was accepted, ' + formData.name
// Act
const res = await request(server)
.post('/')
.type('form')
.send(formData)
// Assert
expect(res.text).toContain(expected)
})

There's quite a bit going on in this example! Let's break down some of the major points to note:

  • We use request.post to specify the route we wish to test
  • We use request.type to specify that the data we're sending is a form
  • We use request.send to send the data, which Supertest will automatically convert to form fields
  • We only do our assertions after the await.

Example: server-side validation

Sometimes users don't submit all the information they're supposed to! Maybe even most of the time. We shouldn't trust that all data we expect is actually being sent to our route. Try this on for size:

test("POST '/' returns an error when name is missing", () => {
// Arrange
const formData = {
address: '1 Flargle Lane'
}
const expected = 'Error'
// Act
const res = await request(server)
.post('/')
.type('form')
.send(formData)
// Assert
expect(res.text).toContain(expected)
})

This test looks for the word 'Error' in the response text as an indication that the route has returned with a notice letting the user know they didn't provide all the information we needed.

Try writing the route so that both tests pass.