GithubHelp home page GithubHelp logo

ladjs / supertest Goto Github PK

View Code? Open in Web Editor NEW
13.5K 112.0 758.0 781 KB

๐Ÿ•ท Super-agent driven library for testing node.js HTTP servers using a fluent API. Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.

License: MIT License

JavaScript 100.00%
supertest superagent assertions node

supertest's Introduction

code coverage Build Status Dependencies PRs Welcome MIT License

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('[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 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

supertest's People

Contributors

9renpoto avatar alekbarszczewski avatar alexandre-abrioux avatar andyburke avatar dependabot[bot] avatar dougwilson avatar drewish avatar eldargab avatar fengmk2 avatar gjohnson avatar jimmywarting avatar jonathanong avatar jpbochi avatar jtomaszewski avatar jtwebman avatar lamweili avatar mikelax avatar mmerkes avatar morganherlocker avatar niftylettuce avatar oprogramador avatar ozzywalsh avatar rimiti avatar rob--w avatar siddtheone avatar steff-mueller avatar swang avatar titanism avatar tj avatar vesln avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

supertest's Issues

doesn't work with express < 3.0.0

I noticed that supertest doesn't work with express 2.4.3 or 2.5.11 instances.

This is what you get

     TypeError: Bad file descriptor argument
      at HTTPServer.address (net.js:1129:10)
      at new Test (/usr/src/node/node_modules/Windshaft/node_modules/supertest/lib/test.js:39:18)
      at Object.post (/usr/src/node/node_modules/Windshaft/node_modules/supertest/index.js:30:14)

with this code:

    test("get call to server returns 200",  function(done){
        request(server)
          .get('/')
          .expect(200)
          .end(done);
    });

express 3.0.0beta5 seems supported (but won't work with node-0.4...)

Extend mocha to enable response re-use in multiple tests

I would love to have a short syntax to re-use the response of the previous request in another test case:

describe('ServiceStack hello', function(){
    it.seq('Get some data', function(data, done){
        request('http://localhost')
        .get('/hello')
        .set('Accept', 'application/json')
        .expect({Id: 5})
        .expect(200, done);
    });

    it.seq('Should have data', function(data, done){
        request('http://localhost')
        .get('/hello/' + data.Id) //Use data from previous request
        .set('Accept', 'application/json')
        .expect(200, done);
    });
});

... รก la https://github.com/Arxisos/trestle

What do you think about that? Does it make sense to integrate that into supertest or mocha?

custom expectations

Hi,
I was wondering, how bad it would be if supertest would export lib/Test to allow add custom (application specific) expectations?
My use case is that I want to test expressjs routes and need to test in many places thinks like 'unauthorized', 'unauthenticated', 'owneronly' conditions for many urls, so currently I do:

  request(app)
      .get('/test/threads/34567/edit')
      .expect(500)
      .expect(/Unauthenticated/)
      .end(done);

but would prefer something like:

  request(app)
      .get('/test/threads/34567/edit')
      .expectUnauthenticatedError()
      .end(done);

Pros of that approach is that I have to test such things for many urls, so test code would be more readable and in case I'd change middleware Error I wouldn't have to replace it as well in 'x' places in tests.

Cheers,
Tadek

.expect(body) giving false success

I'm passing an object to .expect() hoping for it to perform a deepEqual with the parsed body of a response.
The result is I'm getting a success, but I'm sure the object isn't the same as the actual body.
How come ?

Is .expect() converting both res.body and the passed object to a string or something like that ?
It sounds counter-intuitive...

has no method "get"

oops, might be noobie problem but..

I get "..return obj; } has no method 'get'" etc.

This works..

var request = require('superagent');

request.get('http://localhost', function(res){
console.info(res);
});


var request = require('superagent');

request
.get('http://localhost')

Does not work :(

Cheers,

TiM

Feature: chaining

It would be awesome to be able to do this:

request(app)
  .get('/signin')
  .expect(200)
  .post('/signin')
  .send({ user: 'foo', pass: 'bar' })
  .expect(200)
  // ...etc...

Can't have it working with Express 3, Mocha, Node 0.8 and a simple app

Hi

I'm new to Node development in general, and I'm trying to write some tests against a basic app. It will evolve as soon as the tests work.

On OSX 10.6.8, using node 0.8.0, express 3.0.0rc3, mocha 1.4.1, supertest 0.1.2.

Here's the my app code :

// Dependencies
var express   = require('express'),
    app = express(),
    mongoose  = require('mongoose'),
    consolidate = require('consolidate'),
    request = require('superagent'),
    OAuth2 = require('oauth').OAuth2,
    config = require('./lib/config'),
    routes = require('./lib/routes');

// Application and Express server configuration
config.init(app, express, consolidate);

// Create routes
routes(app);

// Launch application
app.listen(config.port);
console.log("Application listening @ %s", config.hostBaseUrl);

// Exports application for testing
module.exports = app;

and the test file :

// Dependencies
var app = require('./../app.js'),
//    chai = require('chai'),
    request = require('supertest');

// Tests
describe('GET /', function(){
  it('should respond OK', function(done){
    request(app)
      .get('/')
      .end();
//      .expect(200, done);
//      .expect('Content-Type', /text\/html/, done)
  });
});

The application works fine by itself, but when using mocha to test it, supertest gives me this error :

1) GET / should respond with the home page:
     TypeError: undefined is not a function
      at Test.assert (/Users/khalid_jebbari/Documents/Javascript/SinglyApp/node_modules/supertest/lib/test.js:175:3)
      at Test.end (/Users/khalid_jebbari/Documents/Javascript/SinglyApp/node_modules/supertest/lib/test.js:105:10)
      at Test.<anonymous> (/Users/khalid_jebbari/Documents/Javascript/SinglyApp/node_modules/supertest/node_modules/superagent/lib/node/index.js:124:10)
      at Test.EventEmitter.emit (events.js:88:17)
      at IncomingMessage.Request.end (/Users/khalid_jebbari/Documents/Javascript/SinglyApp/node_modules/supertest/node_modules/superagent/lib/node/index.js:565:12)
      at IncomingMessage.EventEmitter.emit (events.js:115:20)
      at IncomingMessage._emitEnd (http.js:366:10)
      at HTTPParser.parserOnMessageComplete [as onMessageComplete] (http.js:149:23)
      at Socket.socketOnData [as ondata] (http.js:1356:20)
      at TCP.onread (net.js:404:27)

Am I doing something wrong ? I'm sure I am, but can't find what... Any help really appreciated.

SuperAgent method absent?

'Anything you can do with SuperAgent you can do with SuperTest' -- but it seems the SA method 'data' is renamed to 'send' in ST...?

How about setting range of ephemeral ports?

I'm having 260+ tests with mocha + supertest

I have faced eaddrinuse.


using below to get

lsof -Pni4 | grep LISTEN

listened port to avoid them (putting them blacklist)

would be a good way (automatic)


Or

instead of starting with 3456 port and keep increasing by 1

how about let users to pick a starting port?

Work with URLs too instead of apps?

Great work on supertest -- nice library to use. I'd love to use it for continuous testing against our deployed site too, instead of just for unit tests. Would it be possible and straightforward to support testing against URLs instead of servers-as-code?

E.g.:

request('http://staging.example.com/')
  .get('/foo')
  .set('Accept', 'application/json')
  // ...
  .expect(200)
  .expect('Content-Type', /json/)
  .expect({foo: 'foo'})
  .end(function (err, res) {})

So instead of an app, a URL string or object would be passed in, and on get()/etc., it'd be joined with the path.

.expect(status[, fn]) expect undefined response body !?!

Hallo,

I tried to use this module to test my express app. But I got a strange error.

You may can reproduce it, if you try the following code with mocha. it based on your example.js:

var request = require('supertest')
  , express = require('express');

var app = express();

app.get('/user', function(req, res){
    res.format({
        json : function(req, res, next) {
            res.send( { name: 'tobi' } );
        }
    });
});

describe('GET /users', function(){
    it('respond with json', function(done){
        request(app)
            .get('/user')
            .set('Accept', 'application/json')
            .expect('Content-Length', '20')
            .expect(200)
            .expect('Content-Type', /json/)
            .end(function(err, res){
                if (err) { return done(err); }
                done();
            });
    });
});

If I run it with mocha, I got the following error message:

  GET /users
    1) respond with json


  ร— 1 of 1 test failed:

  1) GET /users respond with json:
     Error: expected undefined response body, got '{\n  "name": "tobi"\n}'

Why it expect an undefined body?
I guess that .expect(status[, fn]) delegates the call to .expect(status, body[, fn]) and that check the body to be undefined.

upload file to a remote nginx-proxied server failed

when using .attatch('<key>', '<filename>'); to make a file upload request to the remote server ( var driver = request('http://remotehost') ) behind Nginx, test failed with error

Error: expected 200 "OK", got 411 "Length Required"

Access the server directly does not occur the problem.

How to Persist a request (with cookies, ie sessions) Like super-agent

To access some urls in application, one must login first. I must go back to use super-agent to unit test these urls. Can supertest do thing like this?

server = require './testServer'
request = require 'superagent'

r = request.agent()
server.start 3002

fakeUser = 
  username:'tj',
  password:'foobar'

describe 'after login', ->
      beforeEach (done)  ->
        r
          .post("http://localhost:3002/login") 
          .send(fakeUser) 
          .end (err, res) ->
            assert res.statusCode is 200
            done()

      it 'can show restricted page', (done) ->
         r
          .get("http://localhost:3002/restricted")
          .end (err, res) ->
             assert.include res.text,'Wahoo!'
             assert res.statusCode is 200
             done()

fuzzy matching of response bodies

Idea would be be able to be able to match partial responses ala component/to-function:

request(app)
.get('/users')
// don't care about other properties
// nor the exact details of timestamp property
// just that it exists and is numeric
.expect({ "timestamp":/\n+/}) 
.expect(200, done)

How to access res.body and res.text?

My apologies if I am missing something obvious. But I was trying to do something like #10 and can't figure out how with .body or .text. I'd like to run a test with some additional assertions like this:

  describe('with valid email address', function() {
    it('should return status 201', function(done) {
      request('https://api.myapidomain.com')
        .post('/users')
        .send({
          'email': 'myuser',
          'password': 'mypass'
        })
        .set('Accept', 'application/json')
        .expect(201)
        .expect('Content-Type', /application\/json/)
        .body(function(body) {
           expect(body.id).to.equal(500);
        })
        .end(function(err, res) {
          if (err) return done(err);
          done();
        });
    });

If I put the assertion in .end() then done() gets called before the test is finished. Is there a way to do arbitrary assertions before .end()?

Testing the response body from res.end

I'm using Mocha and Supertest to test a Connect middleware. This test succeeds:

describe('supertest', function() {

  it('matches the response body', function(done) {
    var app = new (require('express'));
    app.use(function(req, res) {
      res.send('Hi!');
    });

    request(app).get('/').expect(200, 'Hi!').end(done);
  });
});

But change res.send to res.end and it fails:

Error: expected 'Hi!' response body, got undefined

Is there a good reason why this doesn't work? I'm using [email protected] and [email protected].

Publish to NPM

Latest release on NPM is 0.7.1. Please publish latest versions.

Passing a url

Hi!

When I want to pass a url instead of a server, I do:

var request = require('supertest')
  , request = request.bind(request, 'http://localhost:3000')
  ;

In the tests:

request
  .post('/smth...')
  .expect(200)
  .end(function(err,res) {...});

But I get the error:

TypeError: Object function() { [native code] } has no method 'post'

Can you please tell me what I'm doing bad?

Best,
Philmod

node v0.8.12
supertest v0.4.0

request .get .send doesn't work

if combining a get request with the send() method the query doesn't get submitted like expected:

request(app)
  .get('/my/path')
  .send({ foo='bar' })
  .end ...
  // doesn't produce http://localhost/my/path?foo=bar
  // seems to work if I just use 'super-agent'

edit: seems to work if using .query instead of .send

request(app)
  .get('/my/path')
  .query({ foo='bar' })
  .end ...
  // produces http://localhost/my/path?foo=bar
  // ... wonder why .send works if using super-agent directly
  // could be related to the hardcoded this.url in 'function Test'?!

undefined locals variables in response

This is the source code, when trying to assert the res.locals.userId, res.locals is undefined

it('should set res.locals', function(done) {
    var app = express();

    app.get('/', function(req, res) {
        res.locals.userId = 1
        return res.send(200);
    });

    request(app)
        .get('/')
        .expect(200)
        .end(function(err, res){
            if (err) return done(err);
            assert.equal(res.locals.userId, 1); // res.locals is undefined
            done();
        });
});

superagent `pipe` is broken when using supertest

I have a fix, but need an opinion before submitting.

Doing something like:

supertest.get('/path/to/file.mp3')
  .buffer(false)
  .pipe(new _Speaker()) 
  .end(function(err, res){
    console.log('all done');
  })

Fails with:

/Users/drewp/dev/link-pipes/node_modules/supertest/lib/test.js:197
  fn(null, res);
  ^
TypeError: undefined is not a function
    at Test.assert (/Users/drewp/dev/link-pipes/node_modules/supertest/lib/test.js:197:3)
    at Test.end (/Users/drewp/dev/link-pipes/node_modules/supertest/lib/test.js:126:10)
    at Test.Request.callback (/Users/drewp/dev/link-pipes/node_modules/supertest/node_modules/superagent/lib/node/index.js:575:3)
    at Test.<anonymous> (/Users/drewp/dev/link-pipes/node_modules/supertest/node_modules/superagent/lib/node/index.js:133:10)
    at Test.EventEmitter.emit (events.js:96:17)
    at ClientRequest.Request.end (/Users/drewp/dev/link-pipes/node_modules/supertest/node_modules/superagent/lib/node/index.js:693:12)
    at ClientRequest.EventEmitter.emit (events.js:126:20)
    at HTTPParser.parserOnIncomingClient [as onIncoming] (http.js:1569:7)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:111:23)
    at Socket.socketOnData [as ondata] (http.js:1472:20)

If I replace this.end() in line 384 of superagent/lib/node/index.js with this.end(noop), everything works as expected.

I've tracked this down but am not sure the best way to fix it. The issue is due to inheritance.

Request.pipe calls this.end()... (no args). Request.end checks for a passed fn or defaults to noop. But end is redefined in supertest to blindly call this.assert(res, fn), which always assumes fn is defined. So this.end in Request.pipe is actually calling Test.end.

I could fix this by editing either supertest or superagent, but I'm not sure of the intended behavior. If I were to change supertest so that assert's fn param was optional, that would fix all of this, but then assert wouldn't be relaying the results anywhere. Changing this is superagent requires all calls to this.end to always pass noop, which feels weird considering this only happens because supertest subclasses Request.

So perhaps the best thing to do is allow fn to be optional in Test.assert?

Nested request (GET then DELETE) returns empty body

        request(app)
            .post('/api/tips')
            .send({title:'test-add-tip',text:'this is a new tip',hash_tags:['brocode1','brocode2']})
            .end(function(err, res) {
                assert(res.body.data.length === 1, 'Should get one object on adding');
                assert(res.body.data[0]._id.length > 1, 'Should have one id on new object');
                request(app)
                    .del('/api/tips/' + res.body.data[0]._id)
                    .end(function(err, res){
                        console.log(res.body);
                        done();
                    });
            });

Not sure if I am missing something or misunderstanding the problem. But if I do another request inside the end function of a different request, res will come back with empty body

I got EMFILE

I wrote many tests(about one hundred) with super test, and I got EMFILE in later tests.

I'm using following pattern. (CoffeeScript)

app = express()
req = (supertest app)['get'] '/users'
req.expect(200).end (error) ->
  ...

I found that supertest opens a port for each test, and doesn't close it.

How about closing socket after request?

Test.prototype.assert = function(res, fn){
  if('string' != typeof this.app) {
    this.app.close();
  }
  ...
}

Attach() should put files on request.files?

Hello, this is more a doubt than a issue.

I'm using the method attach() to simulate a file upload to a express middleware. I was expecting that the request.files would be filled with the information of the attached file, but instead I'm receiving an undefined variable on request.

Am I doing something wrong?

request(app)
      .post('/test')
      .attach('image', __dirname + '/fixtures/fatcat.jpeg')
      .expect('Content-Type', /json/)
      .expect('Content-Length', '15')
      .expect(201)
      .end(function(err, res){
        if (err) throw err;
        done();
      });

middleware

return function handler(req, res, next) {
      console.log(req.files); // returns undefined :(
}

Thanks in advance.

.end() doesn't accept function with arity 1

I attempted to use this for matching specific keys in the response, to avoid conditional error handling, as shown by the superagent docs:

test('user xx', function(done) {
  request.post('/user')
    ...
    .expect(201)
    .on('error', done)
    .end(function(res){
        res.body.should.have.property('username')
        // TypeError: Cannot read property 'body' of null
    })

but the end callback is being called with (err, res) arguments regardless.

Error: connect EADDRNOTAVAIL on Windows

Node 8.0.2
Error: connect EADDRNOTAVAIL
at errnoException (net.js:776:11)
at Object.afterConnect as oncomplete

workaround:
supertest/lib/test.js

function Test line 43 setting this.url

replace 0.0.0.0 address with 127.0.0.1

What can be the problem with 0.0.0.0?

Access to superagent's agent?

Supertest exposes the superagent Request methods, but not the agent. Could it expose agent so you could use supertest with sessions/cookies?

Supertest throws 500 when browsers display page correctly

I'm not sure if I have done something wrong but I can't get my test to pass. I am trying to test a user registration page. I've added a local variabel to populate the form fields if the server responds with a validation error.

My app.js file has

app.use(function (req, res, next) { 
    res.locals({
        formData: req.session.formData
    })
    next()
})

In my registration page I have the following (Jade)

input#first(type='text', name='first', placeholder='First name', value=formData.first)

This behaves as expected in the browser - field is blank when first enter the page but is populated when a validation error is presented. My test keeps failing with 'Cannot read property 'first' of undefined' though.

Have I done something wrong or are the tests not recognising the local variables?

sexy webpage

I pity the fool who hasn't yet discovered this library for testing their http apis. Mayhaps some gh-pages would reduce the number of fools worthy of such pity.

Routes that redirect result in 'Moved Temporarily.' response body

First of all, excellent library. Thanks for your work.

Even the simplest route that redirects results in a Moved Temporarily. response body. For example,

app.get '/foobar', (req, res) ->
  res.redirect '/login'

app.get '/login', (req, res) ->
  res.render "#{__dirname}/views/login"
request = require('supertest')
app     = require('../../app')

describe '/foobar', ->
  it 'redirects to /login', (done) ->
    request(app)
      .get('/foobar')
      .expect('Login', done)
$ mocha test/my-test.coffee --compilers coffee:coffee-script

  Express server listening on port 3000
GET /foobar 302 3ms - 56
โ€ค

  โœ– 1 of 1 test failed:

  1) /foobar redirects to /login:
     Error: expected 'Login' response body, got 'Moved Temporarily. Redirecting to //127.0.0.1:3456/login'

One thing that looks odd is the different ports in the output Express server listening on port 3000, and the test Redirecting to //127.0.0.1:3456/login.

.expect(201) passes when res.status == 400

Sorry to create another ticket out of what may be ignorance but...

describe('POST /', function(){
  it('should pass with good img_uri', function(done){
    request(app)
        .post('/')
        .send({
            img_uri: '/foo.png'
        })
        .expect(201)
        .expect('Content-Type', /json/)
        .expect( { ok: 1 } )
        .end(function(err, res){
            console.log( 'BODY: ' );
            console.log( res.body );
            console.log( res.status );
            console.log( 'res.status == 201: '+ res.status == 201 );
            done()
        })
    })
});

The output (in TAP format):

BODY: 
{ ok: 0, msg: 'Missing parameters: img_uri' }
400
false
ok 1 POST / should pass with good img_uri

This seems to show that either the chained .expect() calls are behaving differently than in the examples, or that I failed to understand how they should work.

TIA
Lee

how to set a proxy

following code does not work:

var request = require('supertest');
var url = '192.168.254.121';
var proxy = 'http://127.0.0.1:8888';

request = request(url)

request.get( proxy + '/verify?user=sample')
.set('Host', "192.168.254.121")
.set('Port', 8000)
.end(function (res) {
})

Custom Serialization / Parser support

Testing framework is great, except I use a custom serializer / parser for json in expressjs. It would be great if I could plugin my parser into this testing framework.

In the underlying "superagent" framework it is possible to modify parsers and serializers with superagent.parse[content-type] = function(){}, and superagent.serialize[content-type] = function(){}.

However, supertest in all its glory doesn't give me access to its instance of superagent so I can't work-around the issue.

Not sure of the best way to expose the underlying parsing. A good call might be something like:

request(app)
.serialize(mySerializer)
.parse(myParser)

of course this would require modification to the superagent library, maybe it is best done there.

Thoughts?

Regular expression usage in json body

When I make an API call I want to inspect the returned JSON for its results. I can see the body and some the static data is being checked properly, but wherever I use regular expression things are broken. Here is an example of my test:

describe('get user', function() {

    it('should return 204 with expected JSON', function(done) {
      oauth.passwordToken({
        'username': config.username,
        'password': config.password,
        'client_id': config.client_id,
        'client_secret': config.client_secret,
        'grant_type': 'password'
      }, function(body) {
        request(config.api_endpoint)
        .get('/users/me')
        .set('authorization', 'Bearer ' + body.access_token)
        .expect(200)
        .expect({
          "id": /\d{10}/,
          "email": "[email protected]",
          "registered": /./,
          "first_name": "",
          "last_name": ""
        })
        .end(function(err, res) {
          if (err) return done(err);
          done();
        });
      });
    });
  });

Here is an image of the output:

screen shot 2013-07-23 at 3 45 48 pm

Notice where I used regular expression for pattern matching only {} is displayed and the pattern is not matched. The README.md file says I can used regular expression based on the following:

.expect(body[, fn])
Assert response body text with a string, regular expression, or parsed body object.

Any ideas on using regular expression for pattern matching the json body response?

multiple execution of similar routes

Hi guys, I'm trying to test two routes that are pretty much the same except that one of them is more specific as the latest url segment is a hardcoded value (edit) while the other has a parameter (:slug).

The issue I'm experiencing is that when the request is executed it will call both routes (edit, show) causing my mock never() expectation never pass :(

Am I doing something wrong? I dont't get why both routes are executing if one of them is more specific...

This is the test:

var request = require('supertest')
    , express = require('express')


describe('routes', function() {
    it('should call only edit', function(done) {
        var usersController = require('./users-controller');
        var sandbox = require('sinon').sandbox.create();
        var mockController = sandbox.mock(usersController);

        mockController.expects('edit').yields(null).once();
        mockController.expects('show').never();

        var app = express();

        app.get('/users/:id/edit', usersController.edit);
        app.get('/users/:id/:slug', usersController.show);

        request(app)
          .get('/users/123/edit')
          .end(function(err, res){
            if (err) throw err;
            mockController.verify();
            done();
          });
    });
});

and here is the users-controlle.js I'm mocking above:

exports.edit = function(req, res, next) {
    res.send('edit');
}

exports.show = function(req, res, next) {
    res.send('show');
}

.expect() won't work with .end()

Try:

describe('.expect() with .end()', function () {
  it('should not pass', function (done) {
    var app = require('express')()
    app.use(function (request, response) {
      response.send(500)
    })

    require('supertest')(app)
    .get('/')
    .expect(200) // !!!
    .end(function (error, response) {
      response.statusCode.should.equal(500)
      done()
    })
  })
})

Upgrade to latest superagent! =)

Currently supertest specifies 0.5.1 for superagent, when superagent is already up to 0.9!

I'd personally love the fix for query(), support for cookies, and the timeout() feature. =)

Is 0.5.1 specified for a particular reason? E.g. not quite straightforward to upgrade?

Thanks for the great library again!

Optionally print response body/text on failure

If I get a wrong status code back from a controller, it'd be nice if supertest had an optional 'print response body on failure' mode so I can see the content of the message associated with that wrong status code. Currently you have to go in and manually add additional debugging into like: .expect(200, function() { console.log(arguments); done(); }) every time a test starts failing.

Another option might be to be smarter about generating the Error response in supertest, e.g. parsing the res.body and (optionally) jamming that into the error message. It could even somehow do some specialcase handling of the default connect error handler to populate the stack trace (if that's even possible).

Support Jasmine-node continuous testing

Jasmine has the --autotest option which can continuously execute the test as the files are changing. supertest works fine when the test first start. But when I changed my test file, and save, supertest failed to release the address, and cause below error:

Error: listen EADDRINUSE
at errnoException (net.js:769:11)
at Server._listen2 (net.js:909:14)
at listen (net.js:936:10)
at Server.listen (net.js:985:5)
at Test.serverAddress (C:\proxy\node_modules\supertest\lib\test.js:63:18)
at new Test (C:\proxy\node_modules\supertest\lib\test.js:42:12)

Please add a close, or stop method so the user can choose when to release the address.

How to handle Mongoose timeout best practice

Hi TJ

Thanks for all your great apps!

I am wondering what you would recommend to deal with testing my app - I often get a timeout issue due to mongoose connecting. I have seen solutions such as http://www.scotchmedia.com/tutorials/express/authentication/2/02 but they recreate the mongoose connection. Is there a way that you would recommend that can just call my existing express app and let it connect on its own without timeout?

I currently call my app like this in supertest: app = require('../../app').app,

While the solution linked above works I am looking for a simpler/cleaner/alternative method.

Thanks

Stacked assertions fail due to api inconsistency

When attempting to execute this test:

request(app)
.get('/report/all')
.redirects(1)
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.end(function (err, res) { ...custom jasmine assertions here... } );

I get this error:

node_modules/supertest/lib/test.js:186
actual = res.header[field.toLowerCase()];
^
TypeError: Cannot read property 'header' of null
at Test.assert (node_modules/supertest/lib/test.js:186:17)
at Test.end (node_modules/supertest/lib/test.js:124:10)
at Test.assert (node_modules/supertest/lib/test.js:196:3)
at Test.end (node_modules/supertest/lib/test.js:124:10)
at Test.Request.callback (node_modules/supertest/node_modules/superagent/lib/node/index.js:575:3)
at Test. (node_modules/supertest/node_modules/superagent/lib/node/index.js:133:10)
at Test.EventEmitter.emit (events.js:93:17)
at IncomingMessage.Request.end (node_modules/supertest/node_modules/superagent/lib/node/index.js:705:12)
at IncomingMessage.EventEmitter.emit (events.js:123:20)
at IncomingMessage._emitEnd (http.js:366:10)

My best understanding from analysis is that the the previous assert is passing through to another assert, but the input to the end event/method is just the response (res) and the input to whatever is passed through includes the error (err, res) making the inconsistency of the api causing the issue. (perhaps a small wrapper for the first call inserting a null error after revising the api to consistently be err, res would do the job)

Unexpected Output

describe('POST /', function(){
  it('should pass with good img_uri', function(done){
    request(app)
        .post('/')
        .send({
            'img_uri' : app.config.DOCUMENT_ROOT
                        + app.config.IMG_DIR
                        + 'animals/00e48710d0904b2743ff96192585f6ca.png'
        })
        .expect(201)
        .expect('Content-Type', /json/)
        .end(function(err, res){
            console.log( res );
            done()
        })
    })
})
;

Outputs:

Lee:lib leegoddard$ mocha supertest.js 

  ...


  โœ” 3 tests complete (41ms)

I expected a failure on the content-type test, but it is not there...?

Thanks for what otherwise looks like a great set of modules.
Lee

req.body is undefined

Hi guys,

I'm trying to parse the req.body and it returns undefined, I've tested the same endpoint with a rest client and it works.

describe('body', function() {
    it('should parse body ', function(done) {
        var app = express();

        app.post('/test', function(req, res) {
            console.log(req.body); // => this output is undefined
            res.send(req.body);
        });

        request(app)
            .post('/test')
            .type('form')
            .send({ name: 'tj' })
            .expect(200, '{ name: \'tj\' }')
            .end(function(err, res){                
                if (err) return done(err);
                done()
            });
    });
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.