Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsUse SuperTest to send HTTP-style requests to your Node.js application and assert the responses it produces: status codes, headers, bodies, or custom conditions. A test runner such as Mocha or Jest organizes and runs the tests; SuperTest provides the request-and-assertion layer. The examples below use Express, but SuperTest accepts an application function or an HTTP server.
Prepare an app that tests can import
Export the application separately from the code that starts the production listener. That lets SuperTest exercise the app without your test having to choose or reserve a fixed port.
// app.js
const express = require('express');
const app = express();
app.use(express.json());
app.get('/user', (req, res) => {
res.json({ name: 'Ada' });
});
module.exports = app;
Start the listener in a separate entry point when running the application normally:
// server.js
const app = require('./app');
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Listening on ${port}`);
});
When SuperTest receives an app that is not already listening, it binds it to an ephemeral port. You therefore do not need to hard-code a test port for the examples here.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
Install SuperTest and make a first request
Add SuperTest as a development dependency. The project README setup uses this installation pattern:
npm install --save-dev supertest
For a basic test, pass the exported app to request(), name the HTTP method and path, then chain the response assertions:
// test/user.test.js
const request = require('supertest');
const app = require('../app');
test('GET /user returns a user as JSON', async () => {
await request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect(200)
.expect({ name: 'Ada' });
});
The example uses a Jest-style test function, but it does not configure Jest or imply that Jest is required. Put the request inside the test function your chosen runner provides. SuperTest’s README also demonstrates Mocha and use without a test framework.
Rank #2
Choose a completion style that fits your test runner
SuperTest supports callback, promise, and async/await patterns. Use one completion style per test so the runner knows when the request and its assertions have finished.
Recommended Free Tools
Async/await
Await the request chain. If a status or other .expect() assertion fails, the awaited operation rejects, allowing the test runner to report a failed test.
test('GET /user returns status 200', async () => {
await request(app)
.get('/user')
.expect(200);
});
Promise
Return the request promise from the test. Returning it is important: otherwise a runner may finish the test before the response assertion has completed.
Rank #3
test('GET /user returns status 200', () => {
return request(app)
.get('/user')
.expect(200);
});
Callback with .end()
If you use .end(), pass its error to the test runner’s failure path. This ensures a failed .expect() assertion fails the test instead of being lost in the callback.
it('GET /user returns JSON', (done) => {
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect(200)
.end((err, res) => {
if (err) return done(err);
done();
});
});
SuperTest also supports passing a test-runner callback to an .expect() assertion, as in .expect(200, done). When you chain multiple assertions before .end(), they run in the order declared. Do not call done() before the request finishes.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Test a POST request at the HTTP boundary
For a POST route, test the request method, path, payload, and the response contract your application promises. This small in-memory example is runnable without a database; it checks that JSON input is parsed and that the route returns the expected status and body.
Rank #4
// Add to app.js, after app.use(express.json())
app.post('/echo', (req, res) => {
res.status(201).json({ received: req.body });
});
// test/echo.test.js
const request = require('supertest');
const app = require('../app');
test('POST /echo accepts JSON and returns the received value', async () => {
await request(app)
.post('/echo')
.send({ message: 'hello' })
.expect('Content-Type', /json/)
.expect(201)
.expect({ received: { message: 'hello' } });
});
This verifies the request/response behavior, not persistence or database isolation. For a route backed by storage, arrange test data and cleanup according to your application’s own persistence layer; there is no universal cleanup recipe implied by SuperTest.
Keep cookies between requests with an agent
Independent calls to request(app) are appropriate for independent requests. For a sequence where a cookie from one response must accompany a later request, create an agent with request.agent(app) and use that same agent for both calls.
// Add to app.js
app.get('/start-session', (req, res) => {
res.cookie('session', 'test-session');
res.sendStatus(200);
});
app.get('/session', (req, res) => {
res.json({ cookie: req.get('Cookie') || '' });
});
// test/session.test.js
const request = require('supertest');
const app = require('../app');
test('agent carries a cookie to a later request', async () => {
const agent = request.agent(app);
await agent.get('/start-session').expect(200);
await agent.get('/session')
.expect(200)
.expect((res) => {
if (!res.body.cookie.includes('session=test-session')) {
throw new Error('Expected session cookie on the second request');
}
});
});
The illustrative route above reads the Cookie header to make the carried state observable. In a real app, assert the behavior that matters to the application, such as access to a session-protected route. Keep agent state and test data isolated according to your test suite’s setup.
Other request and assertion choices
- Response checks: chain expectations for the status, a header, or the response body. Use a custom assertion when the check needs application-specific logic.
- Request inputs: choose the method and path that exercise the route, and send the payload needed for that case. The POST example sends a JSON object.
- One request or a sequence: use
request(app)for a standalone request andrequest.agent(app)when state such as cookies must carry across requests. - HTTP or HTTP/2: the README includes an explicit HTTP/2 option. Use it only when the server and project requirements call for HTTP/2; ordinary examples use HTTP requests.
Version and compatibility
Repository package metadata retrieved on October 3, 2026 listed SuperTest 7.3.0 and a Node.js requirement of >=14.18.0. Those are time-sensitive package facts, not a guarantee about the version in your project or a permanent compatibility promise. Check the version and engine requirements in your own lockfile and the package metadata before upgrading or setting a Node.js baseline.
Troubleshooting common test failures
- The test ends before the response arrives: await the request, return its promise, or use the runner’s callback correctly. A callback-style test must call
done()only after the request completes. - An assertion fails but the callback test passes: forward
errfrom.end((err, res) => ...)todone(err). SuperTest reports failed chained expectations through that callback when using.end(). - The app cannot be imported in the test: export the application function from its app module and import that module in the test. Keep production listener startup separate so tests can pass the app directly.
- A later request lacks the expected cookie: use the same
request.agent(app)instance for the request that receives the cookie and the request that needs it. Separate calls torequest(app)do not express that shared-agent flow. - The response body is not parsed as JSON: check that the route actually responds with JSON and the expected content type; then assert the response shape your app returns.
- A route test depends on stale data: make the test’s setup and cleanup explicit for the app’s own storage. SuperTest exercises the boundary; it does not prescribe database fixtures or cleanup.
Or skip browser setup
SuperTest tests an API’s HTTP contract; it does not replace those assertions with a screenshot. If you also need a rendered-page visual check without setting up browser automation, ScreenshotNeo is a separate option: it captures a page as an image or PDF.
For example, this one-call request captures a page as WebP:
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are not billed; and its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month with no card.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




