Repo of the Day
forwardemail/supertest
Published: Jan 15, 2023
Open repository ↗Looks cool for testing HTTP servers in node, maybe stuff like express, nest, or fastify servers
Summary
Supertest is a Node.js library for testing HTTP servers through a fluent API built on top of the superagent HTTP client. You hand it an Express app, an http.Server, or a function, and it makes real HTTP requests against that server without requiring you to bind a real port. The project is MIT-licensed, written in JavaScript, and is the maintained fork used by the @forwardemail and @ladjs organizations.
What it is useful for
Supertest is useful for writing integration tests against any Node.js HTTP server. Because it binds servers to an ephemeral port automatically, tests don't collide on port numbers, and there is no manual teardown. It is framework-agnostic, so it pairs with Mocha, Jest, AVA, or no test runner at all. The README documents a number of concrete use cases:
- Asserting response status codes, headers, and bodies via chained
.expect()calls - Testing JSON endpoints with content-type and content-length checks
- Hitting protected routes with
.auth(username, password) - Uploading multipart form data with
.field()and.attach() - Simulating a logged-in user across multiple requests using
request.agent(app), which persists cookies between calls - Asserting cookie attributes such as
domain,path,httpOnly,expires, andmax-ageusing therequest.cookieshelper - Testing HTTP/2 endpoints by passing
{ http2: true }torequest()orrequest.agent() - Dropping down to the lower-level superagent API (
.write(),.pipe(), etc.) for cases the higher-level assertions do not cover
How engineers can use it
The documented setup is a single install command:
npm install supertest --save-dev
Then require('supertest') in a test file. A typical Mocha test from the README looks like this:
const request = require('supertest');
const express = require('express');
const app = express();
app.get('/user', function(req, res) {
res.status(200).json({ name: 'john' });
});
describe('GET /user', function() {
it('responds with json', function(done) {
request(app)
.get('/user')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
The same pattern works with promises, async/await, or raw .end(function(err, res) { ... }) callbacks, all of which the README shows. Assertions run in the order they are chained, so a custom .expect(function(res) { ... }) can mutate res.body before a later structural check.
A documented gotcha: when using .end(), failing .expect() assertions do not throw — they are returned as the first argument to the .end() callback, so you must forward that error to done(err) or rethrow it. The README does not describe a browser entry point, so for anything outside HTTP assertions against a Node server, the README redirects you to the underlying superagent client.