UNPKG

7.91 kBMarkdownView Raw
1# SuperTest
2
3[![Coveralls][coverage-badge]][coverage]
4[![Build Status][travis-badge]][travis]
5[![Dependencies][dependencies-badge]][dependencies]
6[![PRs Welcome][prs-badge]][prs]
7[![MIT License][license-badge]][license]
8
9HTTP assertions made easy via [superagent](http://github.com/visionmedia/superagent).
10
11## About
12
13The motivation with this module is to provide a high-level abstraction for testing
14HTTP, while still allowing you to drop down to the [lower-level API](https://visionmedia.github.io/superagent/) provided by superagent.
15
16## Getting Started
17
18Install SuperTest as an npm module and save it to your package.json file as a development dependency:
19
20```bash
21npm install supertest --save-dev
22```
23
24 Once installed it can now be referenced by simply calling ```require('supertest');```
25
26## Example
27
28You may pass an `http.Server`, or a `Function` to `request()` - if the server is not
29already listening for connections then it is bound to an ephemeral port for you so
30there is no need to keep track of ports.
31
32SuperTest works with any test framework, here is an example without using any
33test framework at all:
34
35```js
36const request = require('supertest');
37const express = require('express');
38
39const app = express();
40
41app.get('/user', function(req, res) {
42 res.status(200).json({ name: 'john' });
43});
44
45request(app)
46 .get('/user')
47 .expect('Content-Type', /json/)
48 .expect('Content-Length', '15')
49 .expect(200)
50 .end(function(err, res) {
51 if (err) throw err;
52 });
53```
54
55Here's an example with mocha, note how you can pass `done` straight to any of the `.expect()` calls:
56
57```js
58describe('GET /user', function() {
59 it('responds with json', function(done) {
60 request(app)
61 .get('/user')
62 .set('Accept', 'application/json')
63 .expect('Content-Type', /json/)
64 .expect(200, done);
65 });
66});
67```
68
69You can use `auth` method to pass HTTP username and password in the same way as in the [superagent](http://visionmedia.github.io/superagent/#authentication):
70
71 ```js
72describe('GET /user', function() {
73 it('responds with json', function(done) {
74 request(app)
75 .get('/user')
76 .auth('username', 'password')
77 .set('Accept', 'application/json')
78 .expect('Content-Type', /json/)
79 .expect(200, done);
80 });
81});
82```
83
84One thing to note with the above statement is that superagent now sends any HTTP
85error (anything other than a 2XX response code) to the callback as the first argument if
86you do not add a status code expect (i.e. `.expect(302)`).
87
88If you are using the `.end()` method `.expect()` assertions that fail will
89not throw - they will return the assertion as an error to the `.end()` callback. In
90order to fail the test case, you will need to rethrow or pass `err` to `done()`, as follows:
91
92```js
93describe('POST /users', function() {
94 it('responds with json', function(done) {
95 request(app)
96 .post('/users')
97 .send({name: 'john'})
98 .set('Accept', 'application/json')
99 .expect('Content-Type', /json/)
100 .expect(200)
101 .end(function(err, res) {
102 if (err) return done(err);
103 done();
104 });
105 });
106});
107```
108
109You can also use promises:
110
111```js
112describe('GET /users', function() {
113 it('responds with json', function() {
114 return request(app)
115 .get('/users')
116 .set('Accept', 'application/json')
117 .expect('Content-Type', /json/)
118 .expect(200)
119 .then(response => {
120 assert(response.body.email, 'foo@bar.com')
121 })
122 });
123});
124```
125
126Expectations are run in the order of definition. This characteristic can be used
127to modify the response body or headers before executing an assertion.
128
129```js
130describe('POST /user', function() {
131 it('user.name should be an case-insensitive match for "john"', function(done) {
132 request(app)
133 .post('/user')
134 .send('name=john') // x-www-form-urlencoded upload
135 .set('Accept', 'application/json')
136 .expect(function(res) {
137 res.body.id = 'some fixed id';
138 res.body.name = res.body.name.toLowerCase();
139 })
140 .expect(200, {
141 id: 'some fixed id',
142 name: 'john'
143 }, done);
144 });
145});
146```
147
148Anything you can do with superagent, you can do with supertest - for example multipart file uploads!
149
150```js
151request(app)
152 .post('/')
153 .field('name', 'my awesome avatar')
154 .attach('avatar', 'test/fixtures/avatar.jpg')
155 ...
156```
157
158Passing the app or url each time is not necessary, if you're testing
159the same host you may simply re-assign the request variable with the
160initialization app or url, a new `Test` is created per `request.VERB()` call.
161
162```js
163request = request('http://localhost:5555');
164
165request.get('/').expect(200, function(err){
166 console.log(err);
167});
168
169request.get('/').expect('heya', function(err){
170 console.log(err);
171});
172```
173
174Here's an example with mocha that shows how to persist a request and its cookies:
175
176```js
177const request = require('supertest');
178const should = require('should');
179const express = require('express');
180const cookieParser = require('cookie-parser');
181
182describe('request.agent(app)', function() {
183 const app = express();
184 app.use(cookieParser());
185
186 app.get('/', function(req, res) {
187 res.cookie('cookie', 'hey');
188 res.send();
189 });
190
191 app.get('/return', function(req, res) {
192 if (req.cookies.cookie) res.send(req.cookies.cookie);
193 else res.send(':(')
194 });
195
196 const agent = request.agent(app);
197
198 it('should save cookies', function(done) {
199 agent
200 .get('/')
201 .expect('set-cookie', 'cookie=hey; Path=/', done);
202 });
203
204 it('should send cookies', function(done) {
205 agent
206 .get('/return')
207 .expect('hey', done);
208 });
209});
210```
211
212There is another example that is introduced by the file [agency.js](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js)
213
214Here is an example where 2 cookies are set on the request.
215
216 ```js
217agent(app)
218 .get('/api/content')
219 .set('Cookie', ['nameOne=valueOne;nameTwo=valueTwo'])
220 .send()
221 .expect(200)
222 .end((err, res) => {
223 if (err) {
224 return done(err);
225 }
226 expect(res.text).to.be.equal('hey');
227 return done();
228 });
229```
230
231## API
232
233You may use any [superagent](http://github.com/visionmedia/superagent) methods,
234including `.write()`, `.pipe()` etc and perform assertions in the `.end()` callback
235for lower-level needs.
236
237### .expect(status[, fn])
238
239Assert response `status` code.
240
241### .expect(status, body[, fn])
242
243Assert response `status` code and `body`.
244
245### .expect(body[, fn])
246
247Assert response `body` text with a string, regular expression, or
248parsed body object.
249
250### .expect(field, value[, fn])
251
252Assert header `field` `value` with a string or regular expression.
253
254### .expect(function(res) {})
255
256Pass a custom assertion function. It'll be given the response object to check. If the check fails, throw an error.
257
258```js
259request(app)
260 .get('/')
261 .expect(hasPreviousAndNextKeys)
262 .end(done);
263
264function hasPreviousAndNextKeys(res) {
265 if (!('next' in res.body)) throw new Error("missing next key");
266 if (!('prev' in res.body)) throw new Error("missing prev key");
267}
268```
269
270### .end(fn)
271
272Perform the request and invoke `fn(err, res)`.
273
274## Notes
275
276Inspired by [api-easy](https://github.com/flatiron/api-easy) minus vows coupling.
277
278## License
279
280MIT
281
282[coverage-badge]: https://coveralls.io/repos/github/visionmedia/supertest/badge.svg?branch=master
283[coverage]: https://coveralls.io/github/visionmedia/supertest?branch=master
284[travis-badge]: https://travis-ci.org/visionmedia/supertest.svg?branch=master
285[travis]: https://travis-ci.org/visionmedia/supertest
286[dependencies-badge]: https://david-dm.org/visionmedia/supertest/status.svg
287[dependencies]: https://david-dm.org/visionmedia/supertest
288[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
289[prs]: http://makeapullrequest.com
290[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
291[license]: https://github.com/visionmedia/supertest/blob/master/LICENSE