Repository: forwardemail/supertest
Stars: 14346
README.md
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 `` You may pass an supertest works with any test framework, here is an example without using anyrequire('supertest');http.ServerExample
, 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.
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 torequestorrequest.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 passdonestraight 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 useauthmethod 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.expect(302)
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.)..end()If you are using the
method.expect()assertions that fail will.end()
not throw - they will return the assertion as an error to thecallback. Inerr
order to fail the test case, you will need to rethrow or passtodone(), 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('[email protected]');
})
});
});
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('[email protected]');
});
});
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 testingTest
the same host you may simply re-assign the request variable with the
initialization app or url, a newis created perrequest.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.jsHere 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();
});
.write()API
You may use any superagent methods,
including,.pipe()etc and perform assertions in the.end()callbackstatus
for lower-level needs..expect(status[, fn])
Assert response
code.status.expect(status, body[, fn])
Assert response
code andbody.body.expect(body[, fn])
Assert response
text with a string, regular expression, orfield
parsed body object..expect(field, value[, fn])
Assert header
valuewith 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");
}
fn(err, res).end(fn)
Perform the request and invoke
.setCookies
Here is an example of using the
andnotcookie assertions:
// setup super-test
const request = require('supertest');
const express = require('express');
const cookies = request.cookies;
// setup express test service
const app = express();
app.get('/users', function(req, res) {
res.cookie('alpha', 'one', { domain: 'domain.com', path: '/', httpOnly: true });
res.send(200, { name: 'tobi' });
});
// test request to service
request(app)
.get('/users')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
// assert 'alpha' cookie is set with domain, path, and httpOnly options
.expect(cookies.set({ name: 'alpha', options: ['domain', 'path', 'httponly'] }))
// assert 'bravo' cookie is NOT set
.expect(cookies.not('set', { name: 'bravo' }))
.end(function(err, res) {
if (err) {
throw err;
}
});
It is also possible to chain assertions:cookies.set({/ ... /}).not('set', {/ ... /})
`
Cookie assertions
Functions and methods are chainable.
#### cookies([secret], [asserts])
Get assertion function for super-test
.expect() method.Arguments
-
secret - String or array of strings. Cookie signature secrets.
- asserts(req, res) - Function or array of functions. Failed custom assertions should throw.#### .set(expects, [assert])
Assert that cookie and options are set.
Arguments
-
expects - Object or array of objects.
- name - String name of cookie.
- options - Optional array of options.
- assert - Optional boolean "assert true" modifier. Default: true.#### .reset(expects, [assert])
Assert that cookie is set and was already set (in request headers).
Arguments
-
expects - Object or array of objects.
- name - String name of cookie.
- assert - Optional boolean "assert true" modifier. Default: true.#### .new(expects, [assert])
Assert that cookie is set and was NOT already set (NOT in request headers).
Arguments
-
expects - Object or array of objects.
- name - String name of cookie.
- assert - Optional boolean "assert true" modifier. Default: true.#### .renew(expects, [assert])
Assert that cookie is set with a strictly greater
expires or max-age than the given value.Arguments
-
expects - Object or array of objects.
- name - String name of cookie.
- options - Object of options. use one of two options below
- options.expires - String UTC expiration for original cookie (in request headers).
- options.max-age - Integer ttl in seconds for original cookie (in request headers).
- assert - Optional boolean "assert true" modifier. Default: true.#### .contain(expects, [assert])
Assert that cookie is set with value and contains options.
Requires
cookies(secret) initialization if cookie is signed.Arguments
-
expects - Object or array of objects.
- name - String name of cookie.
- value - Optional string unsigned value of cookie.
- options - Optional object of options.
- options.domain - Optional string domain.
- options.path - Optional string path.
- options.expires - Optional string UTC expiration.
- options.max-age - Optional integer ttl, in seconds.
- options.secure - Optional boolean secure flag.
- options.httponly - Optional boolean httpOnly flag.
- assert - Optional boolean "assert true" modifier. Default: true.#### .not(method, expects)
Call any cookies assertion method with "assert true" modifier set to
false.Syntactic sugar.
Arguments
-
method - String method name. Arguments of method name apply in expects.
- expects - Object or array of objects.
- name - String name of cookie.
- value - Optional string unsigned value of cookie.
- options` - Optional object of options.Notes
Inspired by api-easy minus vows coupling.
License
MIT
[coverage-badge]: https://img.shields.io/codecov/c/github/ladjs/supertest.svg
[coverage]: https://codecov.io/gh/ladjs/supertest
[travis-badge]: https://travis-ci.org/ladjs/supertest.svg?branch=master
[travis]: https://travis-ci.org/ladjs/supertest
[dependencies-badge]: https://david-dm.org/ladjs/supertest/status.svg
[dependencies]: https://david-dm.org/ladjs/supertest
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
[license]: https://github.com/ladjs/supertest/blob/master/LICENSE