UNPKG

7.97 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 return done();
104 });
105 });
106});
107```
108
109You can also use promises:
110
111```js
112describe('GET /users', function() {
113 it('responds with json', function(done) {
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 done();
122 })
123 .catch(err => done(err))
124 });
125});
126```
127
128Expectations are run in the order of definition. This characteristic can be used
129to modify the response body or headers before executing an assertion.
130
131```js
132describe('POST /user', function() {
133 it('user.name should be an case-insensitive match for "john"', function(done) {
134 request(app)
135 .post('/user')
136 .send('name=john') // x-www-form-urlencoded upload
137 .set('Accept', 'application/json')
138 .expect(function(res) {
139 res.body.id = 'some fixed id';
140 res.body.name = res.body.name.toLowerCase();
141 })
142 .expect(200, {
143 id: 'some fixed id',
144 name: 'john'
145 }, done);
146 });
147});
148```
149
150Anything you can do with superagent, you can do with supertest - for example multipart file uploads!
151
152```js
153request(app)
154 .post('/')
155 .field('name', 'my awesome avatar')
156 .attach('avatar', 'test/fixtures/avatar.jpg')
157 ...
158```
159
160Passing the app or url each time is not necessary, if you're testing
161the same host you may simply re-assign the request variable with the
162initialization app or url, a new `Test` is created per `request.VERB()` call.
163
164```js
165request = request('http://localhost:5555');
166
167request.get('/').expect(200, function(err){
168 console.log(err);
169});
170
171request.get('/').expect('heya', function(err){
172 console.log(err);
173});
174```
175
176Here's an example with mocha that shows how to persist a request and its cookies:
177
178```js
179const request = require('supertest');
180const should = require('should');
181const express = require('express');
182const cookieParser = require('cookie-parser');
183
184describe('request.agent(app)', function() {
185 const app = express();
186 app.use(cookieParser());
187
188 app.get('/', function(req, res) {
189 res.cookie('cookie', 'hey');
190 res.send();
191 });
192
193 app.get('/return', function(req, res) {
194 if (req.cookies.cookie) res.send(req.cookies.cookie);
195 else res.send(':(')
196 });
197
198 const agent = request.agent(app);
199
200 it('should save cookies', function(done) {
201 agent
202 .get('/')
203 .expect('set-cookie', 'cookie=hey; Path=/', done);
204 });
205
206 it('should send cookies', function(done) {
207 agent
208 .get('/return')
209 .expect('hey', done);
210 });
211});
212```
213
214There is another example that is introduced by the file [agency.js](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js)
215
216Here is an example where 2 cookies are set on the request.
217
218```js
219agent(app)
220 .get('/api/content')
221 .set('Cookie', ['nameOne=valueOne;nameTwo=valueTwo'])
222 .send()
223 .expect(200)
224 .end((err, res) => {
225 if (err) {
226 return done(err);
227 }
228 expect(res.text).to.be.equal('hey');
229 return done();
230 });
231```
232
233## API
234
235You may use any [superagent](http://github.com/visionmedia/superagent) methods,
236including `.write()`, `.pipe()` etc and perform assertions in the `.end()` callback
237for lower-level needs.
238
239### .expect(status[, fn])
240
241Assert response `status` code.
242
243### .expect(status, body[, fn])
244
245Assert response `status` code and `body`.
246
247### .expect(body[, fn])
248
249Assert response `body` text with a string, regular expression, or
250parsed body object.
251
252### .expect(field, value[, fn])
253
254Assert header `field` `value` with a string or regular expression.
255
256### .expect(function(res) {})
257
258Pass a custom assertion function. It'll be given the response object to check. If the check fails, throw an error.
259
260```js
261request(app)
262 .get('/')
263 .expect(hasPreviousAndNextKeys)
264 .end(done);
265
266function hasPreviousAndNextKeys(res) {
267 if (!('next' in res.body)) throw new Error("missing next key");
268 if (!('prev' in res.body)) throw new Error("missing prev key");
269}
270```
271
272### .end(fn)
273
274Perform the request and invoke `fn(err, res)`.
275
276## Notes
277
278Inspired by [api-easy](https://github.com/flatiron/api-easy) minus vows coupling.
279
280## License
281
282MIT
283
284[coverage-badge]: https://coveralls.io/repos/github/visionmedia/supertest/badge.svg?branch=master
285[coverage]: https://coveralls.io/github/visionmedia/supertest?branch=master
286[travis-badge]: https://travis-ci.org/visionmedia/supertest.svg?branch=master
287[travis]: https://travis-ci.org/visionmedia/supertest
288[dependencies-badge]: https://david-dm.org/visionmedia/supertest/status.svg
289[dependencies]: https://david-dm.org/visionmedia/supertest
290[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
291[prs]: http://makeapullrequest.com
292[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
293[license]: https://github.com/visionmedia/supertest/blob/master/LICENSE