pax_global_header00006660000000000000000000000064124122725620014515gustar00rootroot0000000000000052 comment=8fcc31cfd1838af0c620a69d2570f44625e928a8 supertest-0.14.0/000077500000000000000000000000001241227256200136355ustar00rootroot00000000000000supertest-0.14.0/.gitignore000066400000000000000000000000151241227256200156210ustar00rootroot00000000000000node_modules supertest-0.14.0/.travis.yml000066400000000000000000000000731241227256200157460ustar00rootroot00000000000000language: node_js node_js: - "0.11" - "0.10" - "0.8" supertest-0.14.0/History.md000066400000000000000000000052771241227256200156330ustar00rootroot000000000000000.14.0 / 2014-09-29 =================== * Update superagent dependency * Update methods dependency 0.13.0 / 2014-05-22 =================== * Wait for server close before invoke the callback for `end()` * Fix global leak in tests 0.12.1 / 2014-05-09 =================== * update methods dependency 0.11.0 / 2014-04-14 ================== * close internal server upon test end * add .delete() method (aliases .del()) 0.10.0 / 2014-03-20 ================== * assert respond body prior to the status code * add documentation for .agent() 0.9.2 / 2014-03-17 ================== * fix package.json 0.9.1 / 2014-03-17 ================== * update superagent 0.9.0 / 2014-01-17 ================== * add expect(function(res) {}) syntax 0.8.3 / 2014-01-07 ================== * update superagent. 0.8.2 / 2013-11-26 ================== * update superagent. Closes #85 0.8.1 / 2013-10-28 ================== * merge pull request #82 from jonathanong/patch-1 * bump node-methods * merge pull request #79 from menzoic/patch-1 * update Readme.md * Merge pull request #73 from repoify/add/repository * add repository field to readme 0.8.0 / 2013-08-09 ================== * add ability for multiple assertions per header 0.7.1 / 2013-07-02 ================== * update superagent 0.7.0 / 2013-06-04 ================== * add error properties so test frameworks can show diffs etc. Closes #65 0.6.1 / 2013-06-02 ================== * fix: EADDRINUSE errnos, use ephemeral ports now * fix: handling of socket errors 0.6.0 / 2013-04-15 ================== * add exposing of `Test` to enable extensibility * add request.agent(app) support * add request(url) test. Closes #33 0.5.1 2012-12-07 ================== * fix .expect(status) should assert only status 0.5.0/ 2012-11-28 ================== * add support for multiple body assertions 0.4.2 / 2012-11-17 ================== * add .buffer() so that responses with no content-length are testable. closes #36 * add failing test for #36 * update superagent 0.4.1 / 2012-11-14 ================== * update superagent 0.4.0 / 2012-10-18 ================== * add url support [vesln] 0.3.1 / 2012-10-01 ================== * update superagent 0.3.0 / 2012-09-24 ================== * add `https.Server` support [fengmk2] 0.2.0 / 2012-08-29 ================== * update superagent. Closes #18 0.1.2 / 2012-07-15 ================== * change bind address from 0.0.0.0 to 127.0.0.1 to prevent EADDRNOTAVAIL on windows 0.1.1 / 2012-07-03 ================== * add `.expect(status, body, fn)` support * add `.expect(status, body)` support 0.1.0 / 2012-07-02 ================== * add parsed body assertion support. Closes #1 supertest-0.14.0/LICENSE000066400000000000000000000021121241227256200146360ustar00rootroot00000000000000(The MIT License) Copyright (c) 2014 TJ Holowaychuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. supertest-0.14.0/Makefile000066400000000000000000000002131241227256200152710ustar00rootroot00000000000000 test: @NODE_TLS_REJECT_UNAUTHORIZED=0 ./node_modules/.bin/mocha \ --require should \ --reporter spec \ --check-leaks .PHONY: test supertest-0.14.0/Readme.md000066400000000000000000000113671241227256200153640ustar00rootroot00000000000000# SuperTest HTTP assertions made easy via [super-agent](http://github.com/visionmedia/superagent). ## 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 super-agent. ## 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: ```js var request = require('supertest') , express = require('express'); var app = express(); app.get('/user', function(req, res){ res.send(200, { name: 'tobi' }); }); request(app) .get('/user') .expect('Content-Type', /json/) .expect('Content-Length', '20') .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: ```js describe('GET /users', function(){ it('respond with json', function(done){ request(app) .get('/user') .set('Accept', 'application/json') .expect('Content-Type', /json/) .expect(200, done); }) }) ``` 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: ```js describe('GET /users', function(){ it('respond with json', function(done){ request(app) .get('/user') .set('Accept', 'application/json') .expect(200) .end(function(err, res){ if (err) return done(err); done() }); }) }) ``` Anything you can do with superagent, you can do with supertest - for example multipart file uploads! ```js request(app) .post('/') .attach('avatar', 'test/fixtures/homeboy.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. ```js 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: ```js var request = require('supertest') , should = require('should') , express = require('express'); var app = express(); app.use(express.cookieParser()); describe('request.agent(app)', function(){ var app = express(); app.use(express.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(':(') }); var 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](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js) ## API You may use any [super-agent](http://github.com/visionmedia/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 response is ok, it should return falsy, most commonly by not returning anything. If the check fails, throw an error or return a truthy value like a string that'll be turned into an error. Here the string or error throwing options are both demonstrated: ```js request(app) .get('/') .expect(hasPreviousAndNextKeys) .end(done); function hasPreviousAndNextKeys(res) { if (!('next' in res.body)) return "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](https://github.com/flatiron/api-easy) minus vows coupling. ## License MIT supertest-0.14.0/example.js000066400000000000000000000005711241227256200156310ustar00rootroot00000000000000 var request = require('./') , express = require('express'); var app = express(); app.get('/user', function(req, res){ res.send(201, { name: 'tobi' }); }); request(app) .get('/user') .expect('Content-Type', /json/) .expect('Content-Length', '20') .expect(201) .end(function(err, res){ if (err) throw err; console.log('done'); process.exit(); }); supertest-0.14.0/index.js000066400000000000000000000013201241227256200152760ustar00rootroot00000000000000 /** * Module dependencies. */ var methods = require('methods') , Test = require('./lib/test') , http = require('http'); /** * Test against the given `app`, * returning a new `Test`. * * @param {Function|Server} app * @return {Test} * @api public */ module.exports = function(app){ if ('function' == typeof app) app = http.createServer(app); var obj = {}; methods.forEach(function(method){ obj[method] = function(url){ return new Test(app, method, url); }; }); // Support previous use of del obj.del = obj['delete']; return obj; }; /** * Expose `Test` */ module.exports.Test = Test; /** * Expose the agent function */ module.exports.agent = require('./lib/agent'); supertest-0.14.0/lib/000077500000000000000000000000001241227256200144035ustar00rootroot00000000000000supertest-0.14.0/lib/agent.js000066400000000000000000000020261241227256200160370ustar00rootroot00000000000000 /** * Module dependencies. */ var Agent = require('superagent').agent , methods = require('methods') , http = require('http') , Test = require('./test'); /** * Expose `Agent`. */ module.exports = TestAgent; /** * Initialize a new `TestAgent`. * * @param {Function|Server} app * @api public */ function TestAgent(app){ if (!(this instanceof TestAgent)) return new TestAgent(app); if ('function' == typeof app) app = http.createServer(app); Agent.call(this); this.app = app; } /** * Inherits from `Agent.prototype`. */ TestAgent.prototype.__proto__ = Agent.prototype; // override HTTP verb methods methods.forEach(function(method){ TestAgent.prototype[method] = function(url, fn){ var req = new Test(this.app, method.toUpperCase(), url); req.on('response', this.saveCookies.bind(this)); req.on('redirect', this.saveCookies.bind(this)); req.on('redirect', this.attachCookies.bind(this, req)); this.attachCookies(req); return req; }; }); TestAgent.prototype.del = TestAgent.prototype.delete; supertest-0.14.0/lib/test.js000066400000000000000000000124521241227256200157240ustar00rootroot00000000000000/** * Module dependencies. */ var request = require('superagent') , util = require('util') , http = require('http') , https = require('https') , assert = require('assert') , Request = request.Request; /** * Expose `Test`. */ module.exports = Test; /** * Initialize a new `Test` with the given `app`, * request `method` and `path`. * * @param {Server} app * @param {String} method * @param {String} path * @api public */ function Test(app, method, path) { Request.call(this, method, path); this.redirects(0); this.buffer(); this.app = app; this._fields = {}; this._bodies = []; this._asserts = []; this.url = 'string' == typeof app ? app + path : this.serverAddress(app, path); } /** * Inherits from `Request.prototype`. */ Test.prototype.__proto__ = Request.prototype; /** * Returns a URL, extracted from a server. * * @param {Server} app * @param {String} path * @returns {String} URL address * @api private */ Test.prototype.serverAddress = function(app, path){ var addr = app.address(); if (!addr) this._server = app.listen(0); var port = app.address().port; var protocol = app instanceof https.Server ? 'https' : 'http'; return protocol + '://127.0.0.1:' + port + path; }; /** * Expectations: * * .expect(200) * .expect(200, fn) * .expect(200, body) * .expect('Some body') * .expect('Some body', fn) * .expect('Content-Type', 'application/json') * .expect('Content-Type', 'application/json', fn) * .expect(fn) * * @return {Test} * @api public */ Test.prototype.expect = function(a, b, c){ var self = this; // callback if ('function' == typeof a) { this._asserts.push(a); return this; } if ('function' == typeof b) this.end(b); if ('function' == typeof c) this.end(c); // status if ('number' == typeof a) { this._status = a; // body if ('function' != typeof b && arguments.length > 1) this._bodies.push(b); return this; } // header field if ('string' == typeof b || 'number' == typeof b || b instanceof RegExp) { if (!this._fields[a]) this._fields[a] = []; this._fields[a].push(b); return this; } // body this._bodies.push(a); return this; }; /** * Defer invoking superagent's `.end()` until * the server is listening. * * @param {Function} fn * @api public */ Test.prototype.end = function(fn){ var self = this; var server = this._server; var end = Request.prototype.end; end.call(this, function(err, res){ if (err) return fn(err); if (server) return server.close(assert); assert(); function assert(){ self.assert(res, fn); } }); return this; }; /** * Perform assertions and invoke `fn(err)`. * * @param {Response} res * @param {Function} fn * @api private */ Test.prototype.assert = function(res, fn){ var status = this._status , fields = this._fields , bodies = this._bodies , expecteds , actual , re; // body for (var i = 0; i < bodies.length; i++) { var body = bodies[i]; var isregexp = body instanceof RegExp; // parsed if ('object' == typeof body && !isregexp) { try { assert.deepEqual(body, res.body); } catch (err) { var a = util.inspect(body); var b = util.inspect(res.body); return fn(error('expected ' + a + ' response body, got ' + b, body, res.body)); } } else { // string if (body !== res.text) { var a = util.inspect(body); var b = util.inspect(res.text); // regexp if (isregexp) { if (!body.test(res.text)) { return fn(error('expected body ' + b + ' to match ' + body, body, res.body)); } } else { return fn(error('expected ' + a + ' response body, got ' + b, body, res.body)); } } } } // fields for (var field in fields) { expecteds = fields[field]; actual = res.header[field.toLowerCase()]; if (null == actual) return fn(new Error('expected "' + field + '" header field')); for (var i = 0; i < expecteds.length; i++) { var fieldExpected = expecteds[i]; if (fieldExpected == actual) continue; if (fieldExpected instanceof RegExp) re = fieldExpected; if (re && re.test(actual)) continue; if (re) return fn(new Error('expected "' + field + '" matching ' + fieldExpected + ', got "' + actual + '"')); return fn(new Error('expected "' + field + '" of "' + fieldExpected + '", got "' + actual + '"')); } } // status if (status && res.status !== status) { var a = http.STATUS_CODES[status]; var b = http.STATUS_CODES[res.status]; return fn(new Error('expected ' + status + ' "' + a + '", got ' + res.status + ' "' + b + '"'), res); } // asserts for (var i = 0; i < this._asserts.length; i++) { var check = this._asserts[i]; var err; try { err = check(res); } catch(e) { err = e; } if (!err) continue; return fn(err instanceof Error ? err : new Error(err)) } fn.call(this, null, res); }; /** * Return an `Error` with `msg` and results properties. * * @param {String} msg * @param {Mixed} expected * @param {Mixed} actual * @return {Error} * @api private */ function error(msg, expected, actual) { var err = new Error(msg); err.expected = expected; err.actual = actual; err.showDiff = true; return err; } supertest-0.14.0/package.json000066400000000000000000000011601241227256200161210ustar00rootroot00000000000000{ "name": "supertest", "version": "0.14.0", "description": "Super-agent driven library for testing HTTP servers", "main": "index.js", "scripts": { "test": "make test" }, "dependencies": { "superagent": "0.19.0", "methods": "1.1.0" }, "devDependencies": { "express": "3.1.0", "mocha": "1.19.0", "should": "3.3.1" }, "keywords": [ "superagent", "request", "tdd", "bdd", "http", "test", "testing" ], "author": "TJ Holowaychuk", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/visionmedia/supertest.git" } } supertest-0.14.0/test/000077500000000000000000000000001241227256200146145ustar00rootroot00000000000000supertest-0.14.0/test/fixtures/000077500000000000000000000000001241227256200164655ustar00rootroot00000000000000supertest-0.14.0/test/fixtures/test_cert.pem000066400000000000000000000016641241227256200211730ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICjzCCAfgCCQCduAjYszOZ3DANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMC Q04xEzARBgNVBAgTCkd1YW5nIERvbmcxFDASBgNVBAcTC0d1YW5nIFpob3VlMQ4w DAYDVQQKEwVUQkVEUDENMAsGA1UECxMEVEVTVDEQMA4GA1UEAxMHZmVuZ21rMjEg MB4GCSqGSIb3DQEJARYRZmVuZ21rMkBnbWFpbC5jb20wHhcNMTIwOTIzMTQxMDI5 WhcNMTIxMDIzMTQxMDI5WjCBizELMAkGA1UEBhMCQ04xEzARBgNVBAgTCkd1YW5n IERvbmcxFDASBgNVBAcTC0d1YW5nIFpob3VlMQ4wDAYDVQQKEwVUQkVEUDENMAsG A1UECxMEVEVTVDEQMA4GA1UEAxMHZmVuZ21rMjEgMB4GCSqGSIb3DQEJARYRZmVu Z21rMkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALOEtchk KBK8WTqwXR2Aov2mc0+igyQTGbxBDSyyULHPiecMqOBHs5bV4DL1pc/01hLKIp4T 2j2KNTTmeivrtKd3wMQL7A+IgyqdmeqRi98pYUylFZrHxb9Kiwm7mpHanodmgnTT zOluEpi/K9h9zM0DbIOynsOh9/w4E2Aq6JvrAgMBAAEwDQYJKoZIhvcNAQEFBQAD gYEAnPd0JvCKQQBrm9jI6TkJKmfBa4NH0wUpMQv/bo2NWw1tA8fTQYb0S4aTep5Q JdYctLQeE7abY1fpXFIwFY/FC0rE3alkEK+4PlCXvHGTYMiq90oH0JtlEqYTdTWJ i99gtHarMEfzejyY3VDa2XFGmZrQCP6Co5NGDjAEr2A4ECg= -----END CERTIFICATE----- supertest-0.14.0/test/fixtures/test_key.pem000066400000000000000000000015671241227256200210300ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCzhLXIZCgSvFk6sF0dgKL9pnNPooMkExm8QQ0sslCxz4nnDKjg R7OW1eAy9aXP9NYSyiKeE9o9ijU05nor67Snd8DEC+wPiIMqnZnqkYvfKWFMpRWa x8W/SosJu5qR2p6HZoJ008zpbhKYvyvYfczNA2yDsp7Doff8OBNgKuib6wIDAQAB AoGAAp2tdHUZLGS4PCWzxalJNr8FMSTiGlV464hbI8qZaG3oyYgisdn5oPoO4U85 ElW0BOQTKxCI/pqT+ehd4WP25u+RXBqOSfpIRQvY2RjXmeyrkDEZWATP/BUa/Oqa 0YitEsAXvt3pQli+LVc9GZSFZQECgwDVdAs4n7DdQlkLwIECQQDmFL9rIE/6wF3h fJkvPFs67MJgMF/T4omLnv/FGSH7KBpjFHts9AbPIGjD1dadRpmHxk7ahbSTKMxu uoZ1R1irAkEAx73MW4fJDQZDdJHwskYyGXuL99Fcr8xz6YZv75tm5O3eF2a/UvoO UIgDGpTIWFrm+gli27p3J0rJhhOiI4JJwQJAYOjUR3bwuRlVcahdjTvK4WLf7Evz 0PdWH+z0pjwTyAn4M0tpQVb3lz57YiErqEsYV8v7Yqd2i5VfpjQCdlt6yQJBAIpm 7kph/SLEO0tzsGenEiHsJKFT9bhun8ape7h4YsSwOdrXPC0fzXlptVTe0S+/1Rpe FJ0SSGv2e0snIYsfRUECQQCP8VOp3IIE8beytDoqn3QbWvobx94NVhHKUX5UB6C+ bhY0LpTTFb8VMfSkICZXhbpcKf5zIdRjOh0ZLDeZJl5v -----END RSA PRIVATE KEY----- supertest-0.14.0/test/supertest.js000066400000000000000000000422541241227256200172170ustar00rootroot00000000000000 var request = require('..') , https = require('https') , fs = require('fs') , path = require('path') , should = require('should') , express = require('express'); describe('request(url)', function(){ it('should be supported', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hello'); }); var s = app.listen(function(){ var url = 'http://localhost:' + s.address().port; request(url) .get('/') .expect("hello", done); }); }) describe('.end(cb)', function() { it('should set `this` to the test object when calling cb', function(done) { var app = express(); var s = app.listen(function(){ var url = 'http://localhost:' + s.address().port; var test = request(url).get('/'); test.end(function(err, res) { this.should.eql(test); done(); }); }); }) }) }) describe('request(app)', function(){ it('should fire up the app on an ephemeral port', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .end(function(err, res){ res.should.have.status(200); res.text.should.equal('hey'); done(); }); }) it('should work with an active server', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); var server = app.listen(4000, function(){ request(server) .get('/') .end(function(err, res){ res.should.have.status(200); res.text.should.equal('hey'); done(); }); }); }) it('should work with remote server', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); var server = app.listen(4001, function(){ request('http://localhost:4001') .get('/') .end(function(err, res){ res.should.have.status(200); res.text.should.equal('hey'); done(); }); }); }) it('should work with a https server', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); var fixtures = path.join(__dirname, 'fixtures'); var server = https.createServer({ key: fs.readFileSync(path.join(fixtures, 'test_key.pem')), cert: fs.readFileSync(path.join(fixtures, 'test_cert.pem')) }, app); request(server) .get('/') .end(function(err, res){ if (err) return done(err); res.should.have.status(200); res.text.should.equal('hey'); done(); }); }) it('should work with .send() etc', function(done){ var app = express(); app.use(express.bodyParser()); app.post('/', function(req, res){ res.send(req.body.name); }); request(app) .post('/') .send({ name: 'tobi' }) .expect('tobi', done); }) it('should work when unbuffered', function(done){ var app = express(); app.get('/', function(req, res){ res.end('Hello'); }); request(app) .get('/') .expect('Hello', done); }) it('should default redirects to 0', function(done){ var app = express(); app.get('/', function(req, res){ res.redirect('/login'); }); request(app) .get('/') .expect(302, done); }) it('should handle socket errors', function(done) { var app = express(); app.get('/', function(req, res){ res.destroy(); }); request(app) .get('/') .end(function(err) { should.exist(err); done(); }); }) describe('.end(fn)', function(){ it('should close server', function(done){ var app = express(); app.get('/', function(req, res){ res.send('supertest FTW!'); }); var test = request(app) .get('/') .end(function(){}); test._server.on('close', function(){ done(); }); }); it('should wait for server to close before invoking fn', function(done){ var app = express(); var closed = false; app.get('/', function(req, res){ res.send('supertest FTW!'); }); var test = request(app) .get('/') .end(function(){ closed.should.be.true; done(); }); test._server.on('close', function(){ closed = true; }); }); it('should support nested requests', function(done){ var app = express(); var test = request(app); app.get('/', function(req, res){ res.send('supertest FTW!'); }); test .get('/') .end(function(){ test .get('/') .end(function(err, res){ (err === null).should.be.true; res.should.have.status(200); res.text.should.equal('supertest FTW!'); done(); }); }); }); }); describe('.expect(status[, fn])', function(){ it('should assert the response status', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect(404) .end(function(err, res){ err.message.should.equal('expected 404 "Not Found", got 200 "OK"'); done(); }); }) }) describe('.expect(status)', function () { it('should assert only status', function (done) { var app = express(); app.get('/', function (req, res) { res.send('hey'); }) request(app) .get('/') .expect(200) .end(done) }) }) describe('.expect(status, body[, fn])', function(){ it('should assert the response body and status', function(done){ var app = express(); app.get('/', function(req, res){ res.send('foo'); }); request(app) .get('/') .expect(200, 'foo', done) }); describe("when the body argument is an empty string", function() { it("should not quietly pass on failure", function(done) { var app = express(); app.get('/', function(req, res){ res.send('foo'); }); request(app) .get('/') .expect(200, '') .end(function(err, res){ err.message.should.equal('expected \'\' response body, got \'foo\''); done(); }); }); }); }) describe('.expect(body[, fn])', function(){ it('should assert the response body', function(done){ var app = express(); app.set('json spaces', 0); app.get('/', function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/') .expect('hey') .end(function(err, res){ err.message.should.equal('expected \'hey\' response body, got \'{"foo":"bar"}\''); done(); }); }) it('should assert the body before the status', function (done) { var app = express(); app.set('json spaces', 0); app.get('/', function(req, res){ res.send(500, { message: 'something went wrong' }); }); request(app) .get('/') .expect(200) .expect('hey') .end(function(err, res){ err.message.should.equal('expected \'hey\' response body, got \'{"message":"something went wrong"}\''); done(); }); }); it('should assert the response text', function(done){ var app = express(); app.set('json spaces', 0); app.get('/', function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/') .expect('{"foo":"bar"}', done); }) it('should assert the parsed response body', function(done){ var app = express(); app.set('json spaces', 0); app.get('/', function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/') .expect({ foo: 'baz' }) .end(function(err, res){ err.message.should.equal('expected { foo: \'baz\' } response body, got { foo: \'bar\' }'); request(app) .get('/') .expect({ foo: 'bar' }) .end(done); }); }) it('should support regular expressions', function(done){ var app = express(); app.get('/', function(req, res){ res.send('foobar'); }); request(app) .get('/') .expect(/^bar/) .end(function(err, res){ err.message.should.equal('expected body \'foobar\' to match /^bar/'); done(); }); }) it('should assert response body multiple times', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey tj'); }); request(app) .get('/') .expect(/tj/) .expect('hey') .expect('hey tj') .end(function (err, res) { err.message.should.equal("expected 'hey' response body, got 'hey tj'"); done(); }); }) it('should assert response body multiple times with no exception', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey tj'); }); request(app) .get('/') .expect(/tj/) .expect(/^hey/) .expect('hey tj', done); }) }) describe('.expect(field, value[, fn])', function(){ it('should assert the header field presence', function(done){ var app = express(); app.get('/', function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/') .expect('Content-Foo', 'bar') .end(function(err, res){ err.message.should.equal('expected "Content-Foo" header field'); done(); }); }) it('should assert the header field value', function(done){ var app = express(); app.get('/', function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/') .expect('Content-Type', 'text/html') .end(function(err, res){ err.message.should.equal('expected "Content-Type" of "text/html", got "application/json; charset=utf-8"'); done(); }); }) it('should assert multiple fields', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Type', 'text/html; charset=utf-8') .expect('Content-Length', '3') .end(done); }) it('should support regular expressions', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Type', /^application/) .end(function(err){ err.message.should.equal('expected "Content-Type" matching /^application/, got "text/html; charset=utf-8"'); done(); }); }) it('should support numbers', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Length', 4) .end(function(err){ err.message.should.equal('expected "Content-Length" of "4", got "3"'); done(); }); }) describe('handling arbitrary expect functions', function(){ it('reports errors',function(done) { var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect(function(res) { throw new Error("failed") }) .end(function(err) { err.message.should.equal('failed'); done() }); }); it('ensures truthy non-errors returned from asserts are promoted to errors',function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect(function(res) { return "some descriptive error"; }) .end(function(err) { err.message.should.equal('some descriptive error'); done() }); }); it("doesn't create false negatives", function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect(function(res) {}) .end(done); }); it("handles multiple asserts", function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); var calls = []; request(app) .get('/') .expect(function(res) { calls[0] = 1 }) .expect(function(res) { calls[1] = 1 }) .expect(function(res) { calls[2] = 1 }) .end(function() { var callCount = [0,1,2].reduce(function(count,i) { return count + calls[i] },0); callCount.should.equal(3,"didn't see all assertions run"); done(); }); }); it("plays well with normal assertions - no false positives", function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect(function(res) {}) .expect('Content-Type', /json/) .end(function(err) { err.message.should.match(/Content-Type/); done(); }) }); it("plays well with normal assertions - no false negatives", function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect(function(res) {}) .expect('Content-Type', /html/) .expect(function(res) {}) .expect('Content-Type', /text/) .end(done) }); }); describe('handling multiple assertions per field', function(){ it('should work', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Type', /text/) .expect('Content-Type', /html/) .end(done); }); it('should return an error if the first one fails', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Type', /bloop/) .expect('Content-Type', /html/) .end(function(err){ err.message.should.equal('expected "Content-Type" matching /bloop/, got "text/html; charset=utf-8"'); done(); }); }); it('should return an error if a middle one fails', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Type', /text/) .expect('Content-Type', /bloop/) .expect('Content-Type', /html/) .end(function(err){ err.message.should.equal('expected "Content-Type" matching /bloop/, got "text/html; charset=utf-8"'); done(); }); }); it('should return an error if the last one fails', function(done){ var app = express(); app.get('/', function(req, res){ res.send('hey'); }); request(app) .get('/') .expect('Content-Type', /text/) .expect('Content-Type', /html/) .expect('Content-Type', /bloop/) .end(function(err){ err.message.should.equal('expected "Content-Type" matching /bloop/, got "text/html; charset=utf-8"'); done(); }); }); }); }) }) describe('request.agent(app)', function(){ var app = express(); app.use(express.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(':(') }); var 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); }) }) describe(". works as expected", function(){ it(".delete should work", function (done){ var app = express(); app.delete('/', function(req, res){ res.send(200); }); request(app) .delete('/') .expect(200, done); }); it(".del should work", function (done){ var app = express(); app.del('/', function(req, res){ res.send(200); }); request(app) .del('/') .expect(200, done); }); it(".get should work", function (done){ var app = express(); app.get('/', function(req, res){ res.send(200); }); request(app) .get('/') .expect(200, done); }); it(".post should work", function (done){ var app = express(); app.post('/', function(req, res){ res.send(200); }); request(app) .post('/') .expect(200, done); }); it(".put should work", function (done){ var app = express(); app.put('/', function(req, res){ res.send(200); }); request(app) .put('/') .expect(200, done); }); });