A lot of the built-in assertions do get the job done for the majority of cases. There are times where you want a little more flexibility. For example, in the previous chapter, we learned about all those cool assertions expect can make. We can use toInclude, toExclude, all of that stuff is really handy and it's a shame to lose it. Luckily, there's a lot of flexibility with SuperTest. What we can do instead of taking an object and passing it into expect, or a number for the status code, we can provide a function. This function will get called by SuperTest and it will get passed the response:
.expect((res) => {
})
This means we can access headers, body, anything we want to access from the HTTP response—it's going to be available in the function. We can pipe it through the regular expect assertion library like we've done in the previous chapter.
Let's load it in, creating a constant called expect and setting it equal to require expect:
const express = require('supertest');
const express = require('express');
Now before we look at how it's going to work, we'll make a change in server.js. Here, we'll add a second property on to the .status object. We'll add an error and then add something else. Let's use name, setting it equal to the application name, Todo App v1.0:
app.get('/', (req, res) => {
res.status(404).send({
error: 'Page not found.',
name: 'Todo App v1.0'
});
});
Now that we have this in place, we can take a look at how we can use those custom assertions inside our test file. In the .expect object, we'll have access to the response and in the response there is a body property. This will be a JavaScript object with key-value pairs, which means we would expect to have an error property and a name property, which we set in server.js.
Back inside our test file, we can make a custom assertion using expect. I'll expect something about the body, res.body. Now we can use any assertion we like, not just the equals assertion, which is the only one SuperTest supports. Let's use the toInclude assertion:
.expect((res) => {
expect(res.body).toInclude({
});
})
Remember, toInclude lets you specify a subset of the properties on the object. As long as it has those ones that's fine. It doesn't matter that it has extra ones. In our case, inside toInclude, we can just specify the error message, leaving off the fact that name exists at all. We want to check that error: Page not found, formatted exactly like we have it inside of server.js:
.expect((res) => {
expect(res.body).toInclude({
error: 'Page not found.'
});
})
Now when we save the file back inside the Terminal, things restart and all of my tests are passing:

Using a combination of SuperTest and expect we can have super flexible test suites for our HTTP endpoints. With this in place, we'll create another express route and we'll define a test that makes sure it works as expected.