supertest
🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
Top Related Projects
🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
Newman is a command-line collection runner for Postman
Fast, easy and reliable testing for anything that runs in a browser.
Quick Overview
Supertest is a high-level abstraction for testing HTTP servers, built on top of the popular SuperAgent library. It provides a fluent API for making HTTP assertions, making it easier to write expressive and readable tests for your Node.js HTTP servers.
Pros
- Easy to use and intuitive API for testing HTTP endpoints
- Supports both callback and promise-based testing styles
- Integrates well with popular testing frameworks like Mocha and Jest
- Allows for testing of both Express applications and raw Node.js http servers
Cons
- Limited to testing HTTP servers, not suitable for other types of testing
- May introduce additional complexity for simple API tests
- Requires a running server for tests, which can slow down test execution
- Some users report occasional issues with certain types of assertions
Code Examples
- Basic GET request test:
const request = require('supertest');
const app = require('../app');
request(app)
.get('/users')
.expect('Content-Type', /json/)
.expect(200)
.end((err, res) => {
if (err) throw err;
});
- POST request with data:
const request = require('supertest');
const app = require('../app');
request(app)
.post('/users')
.send({ name: 'John', email: 'john@example.com' })
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(201)
.then(response => {
assert(response.body.id);
});
- Testing with async/await:
const request = require('supertest');
const app = require('../app');
it('should create a new user', async () => {
const response = await request(app)
.post('/users')
.send({ name: 'Jane', email: 'jane@example.com' });
expect(response.status).toBe(201);
expect(response.body).toHaveProperty('id');
});
Getting Started
To use Supertest in your project, first install it via npm:
npm install supertest --save-dev
Then, in your test file:
const request = require('supertest');
const app = require('../your-app');
describe('GET /users', () => {
it('responds with json', (done) => {
request(app)
.get('/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
Run your tests using your preferred test runner (e.g., Mocha, Jest).
Competitor Comparisons
🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
Pros of Supertest (ladjs)
- More established and widely used in the Node.js community
- Extensive documentation and examples available
- Larger contributor base and more frequent updates
Cons of Supertest (ladjs)
- Slightly larger package size
- May have more dependencies, potentially increasing complexity
- Some users report occasional issues with certain edge cases
Code Comparison
Supertest (ladjs):
const request = require('supertest');
const express = require('express');
const app = express();
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect(200, done);
Supertest (forwardemail):
const supertest = require('supertest');
const express = require('express');
const app = express();
supertest(app)
.get('/user')
.expect('Content-Type', /json/)
.expect(200, done);
The code usage is nearly identical between the two libraries, with the main difference being the import statement. Both provide a similar API for making HTTP assertions in tests.
While Supertest (ladjs) has been the go-to choice for many developers due to its maturity and widespread adoption, Supertest (forwardemail) aims to provide a more lightweight alternative with potentially fewer dependencies. The choice between the two may depend on specific project requirements and preferences.
Newman is a command-line collection runner for Postman
Pros of Newman
- Integrates seamlessly with Postman collections, allowing easy execution of existing API tests
- Supports detailed reporting options, including HTML and JSON formats
- Offers CLI functionality for easy integration into CI/CD pipelines
Cons of Newman
- Requires Postman collections, which may not be suitable for all testing scenarios
- Less flexible for writing custom test logic compared to SuperTest
- Steeper learning curve for those not familiar with Postman ecosystem
Code Comparison
SuperTest:
const request = require('supertest');
const app = require('../app');
describe('GET /users', function() {
it('responds with json', function(done) {
request(app)
.get('/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
Newman:
const newman = require('newman');
newman.run({
collection: require('./my-collection.json'),
environment: require('./my-environment.json'),
reporters: 'cli'
}, function (err) {
if (err) { throw err; }
console.log('collection run complete!');
});
SuperTest is more code-centric and allows for direct integration with testing frameworks like Mocha. Newman, on the other hand, relies on Postman collections and environments, offering a more configuration-based approach to API testing.
Fast, easy and reliable testing for anything that runs in a browser.
Pros of Cypress
- Provides an all-in-one testing framework with built-in assertion library and mocking capabilities
- Offers a powerful, interactive test runner with time-travel debugging
- Supports real-time reloading and automatic waiting for elements
Cons of Cypress
- Limited to testing web applications and cannot test native mobile apps
- Runs tests inside the browser, which can lead to some limitations in certain scenarios
- Has a steeper learning curve compared to simpler HTTP assertion libraries
Code Comparison
Cypress example:
describe('Login', () => {
it('should log in successfully', () => {
cy.visit('/login')
cy.get('#username').type('user@example.com')
cy.get('#password').type('password123')
cy.get('button[type="submit"]').click()
cy.url().should('include', '/dashboard')
})
})
Supertest example:
const request = require('supertest');
const app = require('../app');
describe('Login API', () => {
it('should log in successfully', async () => {
const response = await request(app)
.post('/api/login')
.send({ username: 'user@example.com', password: 'password123' })
.expect(200);
expect(response.body).toHaveProperty('token');
});
});
While Cypress focuses on end-to-end testing of web applications with a browser-based approach, Supertest is primarily used for testing HTTP assertions and API endpoints. Cypress offers a more comprehensive testing solution for web applications, but Supertest provides a simpler and more focused approach for API testing.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
supertest
HTTP assertions made easy via superagent. Maintained for Forward Email and Lad.
About
The motivation with this module is to provide a high-level abstraction for testing HTTP, while still allowing you to drop down to the lower-level API provided by superagent.
Getting Started
Install supertest as an npm module and save it to your package.json file as a development dependency:
npm install supertest --save-dev
Once installed it can now be referenced by simply calling require('supertest');
Example
You may pass an http.Server
, or a Function
to request()
- if the server is not
already listening for connections then it is bound to an ephemeral port for you so
there is no need to keep track of ports.
supertest works with any test framework, here is an example without using any test framework at all:
const request = require('supertest');
const express = require('express');
const app = express();
app.get('/user', function(req, res) {
res.status(200).json({ name: 'john' });
});
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});
To enable http2 protocol, simply append an options to request
or request.agent
:
const request = require('supertest');
const express = require('express');
const app = express();
app.get('/user', function(req, res) {
res.status(200).json({ name: 'john' });
});
request(app, { http2: true })
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});
request.agent(app, { http2: true })
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});
Here's an example with mocha, note how you can pass done
straight to any of the .expect()
calls:
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);
});
});
You can use auth
method to pass HTTP username and password in the same way as in the superagent:
describe('GET /user', function() {
it('responds with json', function(done) {
request(app)
.get('/user')
.auth('username', 'password')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200, done);
});
});
One thing to note with the above statement is that superagent now sends any HTTP
error (anything other than a 2XX response code) to the callback as the first argument if
you do not add a status code expect (i.e. .expect(302)
).
If you are using the .end()
method .expect()
assertions that fail will
not throw - they will return the assertion as an error to the .end()
callback. In
order to fail the test case, you will need to rethrow or pass err
to done()
, as follows:
describe('POST /users', function() {
it('responds with json', function(done) {
request(app)
.post('/users')
.send({name: 'john'})
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
return done();
});
});
});
You can also use promises:
describe('GET /users', function() {
it('responds with json', function() {
return request(app)
.get('/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.then(response => {
expect(response.body.email).toEqual('foo@bar.com');
})
});
});
Or async/await syntax:
describe('GET /users', function() {
it('responds with json', async function() {
const response = await request(app)
.get('/users')
.set('Accept', 'application/json')
expect(response.headers["Content-Type"]).toMatch(/json/);
expect(response.status).toEqual(200);
expect(response.body.email).toEqual('foo@bar.com');
});
});
Expectations are run in the order of definition. This characteristic can be used to modify the response body or headers before executing an assertion.
describe('POST /user', function() {
it('user.name should be an case-insensitive match for "john"', function(done) {
request(app)
.post('/user')
.send('name=john') // x-www-form-urlencoded upload
.set('Accept', 'application/json')
.expect(function(res) {
res.body.id = 'some fixed id';
res.body.name = res.body.name.toLowerCase();
})
.expect(200, {
id: 'some fixed id',
name: 'john'
}, done);
});
});
Anything you can do with superagent, you can do with supertest - for example multipart file uploads!
request(app)
.post('/')
.field('name', 'my awesome avatar')
.field('complex_object', '{"attribute": "value"}', {contentType: 'application/json'})
.attach('avatar', 'test/fixtures/avatar.jpg')
...
Passing the app or url each time is not necessary, if you're testing
the same host you may simply re-assign the request variable with the
initialization app or url, a new Test
is created per request.VERB()
call.
request = request('http://localhost:5555');
request.get('/').expect(200, function(err){
console.log(err);
});
request.get('/').expect('heya', function(err){
console.log(err);
});
Here's an example with mocha that shows how to persist a request and its cookies:
const request = require('supertest');
const should = require('should');
const express = require('express');
const cookieParser = require('cookie-parser');
describe('request.agent(app)', function() {
const app = express();
app.use(cookieParser());
app.get('/', function(req, res) {
res.cookie('cookie', 'hey');
res.send();
});
app.get('/return', function(req, res) {
if (req.cookies.cookie) res.send(req.cookies.cookie);
else res.send(':(')
});
const agent = request.agent(app);
it('should save cookies', function(done) {
agent
.get('/')
.expect('set-cookie', 'cookie=hey; Path=/', done);
});
it('should send cookies', function(done) {
agent
.get('/return')
.expect('hey', done);
});
});
There is another example that is introduced by the file agency.js
Here is an example where 2 cookies are set on the request.
agent(app)
.get('/api/content')
.set('Cookie', ['nameOne=valueOne;nameTwo=valueTwo'])
.send()
.expect(200)
.end((err, res) => {
if (err) {
return done(err);
}
expect(res.text).to.be.equal('hey');
return done();
});
API
You may use any superagent methods,
including .write()
, .pipe()
etc and perform assertions in the .end()
callback
for lower-level needs.
.expect(status[, fn])
Assert response status
code.
.expect(status, body[, fn])
Assert response status
code and body
.
.expect(body[, fn])
Assert response body
text with a string, regular expression, or
parsed body object.
.expect(field, value[, fn])
Assert header field
value
with a string or regular expression.
.expect(function(res) {})
Pass a custom assertion function. It'll be given the response object to check. If the check fails, throw an error.
request(app)
.get('/')
.expect(hasPreviousAndNextKeys)
.end(done);
function hasPreviousAndNextKeys(res) {
if (!('next' in res.body)) throw new Error("missing next key");
if (!('prev' in res.body)) throw new Error("missing prev key");
}
.end(fn)
Perform the request and invoke fn(err, res)
.
Notes
Inspired by api-easy minus vows coupling.
License
MIT
Top Related Projects
🕷 Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
Newman is a command-line collection runner for Postman
Fast, easy and reliable testing for anything that runs in a browser.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot