EzDevInfo.com

supertest

Super-agent driven library for testing node.js HTTP servers using a fluent API

With Supertest, can I create an alternative request with some headers set by default?

I am using Supertest with Mocha to test an API developed with Node JS.

And I want to do a lót of different tests on the API. With almost all of them I have to set Authorization and Content-Type headers again (because the API requires them for this test).

it('Creation without an email address should fail and return error code 50040', function(done) {
  request
    .post('/mpl/entities')
    .set('Authorization', 'Token 1234567890') //set header for this test
    .set('Content-Type',  'application/json') //set header for this test
    .send({
      firstname: "test"
    })
    .expect('Content-Type', /json/)
    .expect(500)
    .expect(anErrorCode('50040'))
    .end(done);
});

it('Creation with a duplicate email address should fail and return error code 50086', function(done) {
  request
    .post('/mpl/entities')
    .set('Authorization', 'Token 1234567890') //<-- again
    .set('Content-Type',  'application/json') //<-- again, I'm getting tired
    .send({
      email: "a@b.nl"
    })
    .expect('Content-Type', /json/)
    .expect(500)
    .expect(anErrorCode('50086'))
    .end(done);
});

Can I create a alternative request with those headers set by default?


Source: (StackOverflow)

loopback.io Error: Can't set headers after they are sent. confirm user

I'm using mocha and supertest to create functional tests. Below is a copy of the test.

it("should verify user POST /api/User/confirm", function (done) {
    app.models.Users.findById(userId, function (err, usr) {
        json('get', '/api/user/confirm?uid=' + userId + '&token=' + usr.verificationToken)
        .expect(204,done);
    });
});

However this test returns :

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:689:11)
    at ServerResponse.res.setHeader (/node_modules/loopback-explorer/node_modules/express/node_modules/connect/lib/patch.js:134:22)
    at ServerResponse.header (/node_modules/loopback/node_modules/express/lib/response.js:700:10)
    at ServerResponse.send (/node_modules/loopback/node_modules/express/lib/response.js:154:12)
    at ServerResponse.json (/node_modules/loopback/node_modules/express/lib/response.js:240:15)
    at ServerResponse.send (/node_modules/loopback/node_modules/express/lib/response.js:142:21)
    at defaultHandler (/node_modules/loopback/node_modules/strong-remoting/lib/rest-adapter.js:379:11)
    at restErrorHandler (/node_modules/loopback/node_modules/strong-remoting/lib/rest-adapter.js:348:14)
    at Layer.handle_error (/node_modules/loopback/node_modules/express/lib/router/layer.js:58:5)
    at trim_prefix (/node_modules/loopback/node_modules/express/lib/router/index.js:300:13)
    at /node_modules/loopback/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/node_modules/loopback/node_modules/express/lib/router/index.js:321:12)
    at next (/node_modules/loopback/node_modules/express/lib/router/index.js:261:10)
    at Layer.handle_error (/node_modules/loopback/node_modules/express/lib/router/layer.js:54:12)
    at trim_prefix (/node_modules/loopback/node_modules/express/lib/router/index.js:300:13)
    at /node_modules/loopback/node_modules/express/lib/router/index.js:270:7
    at Function.proto.process_params (/node_modules/loopback/node_modules/express/lib/router/index.js:321:12)
    at Object.next (/node_modules/loopback/node_modules/express/lib/router/index.js:261:10)
    at Object. (/node_modules/loopback/node_modules/express/lib/router/index.js:603:15)
    at Object. (/node_modules/loopback/node_modules/continuation-local-storage/node_modules/async-listener/glue.js:188:31)
    at Object.immediate._onImmediate (timers.js:363:16)
    at processImmediate as _immediateCallback

I'm using the latest version of loopback at this point. Can anybody point me in the right direction?


Source: (StackOverflow)

Advertisements

How to mock a third-party api calls in the backend

I'm testing my application with mocha and supertest, so my test always are like

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

describe('...', function() {
  it('...', function() {
    request(app)
      .get('/some/url')
      // ...
  });

});

the bootstrap.js is my real application before listen ports

all works perfect but recently I have to add calls to a third-party API and testing is slow

so when I do, the test for example takes 5 seconds

request(app)
  .get('/my/endpoint/that/makes/call/others')
  // ...

How I can make fake calls during the test but real when running my application?


Source: (StackOverflow)

Possible to remove User-agent header in supertest test?

I am trying to write some Supertest test cases where the User-Agent header is sent with a value, blank, or not at all.

I know I can use .set to handle setting a value for that header or '' for blank, but I am not sure how to omit the User-agent header completely. If I leave it off the request supertest sends a default value of node-superagent/1.2.0. If I .set('User-agent', null) it sends 'null' over the wire.

There doesn't appear to be a .remove or .delete. Anyone have an idea?

it ('example', function(done){
  agent.post('/abc/a')
  .set('User-agent', 'some agent')
  .send('abc')
  .expect(200)
  .end(function(err, results){})
};


Source: (StackOverflow)

Unit testing vs Integration testing of an Express.js app

I'm writing tests for an Express.js app and I don't know how to choose between unit tests and integration tests.

currently I experimented with:

unit tests - using Sinon for stubs/mocks/spies and Injects for dependency injection to modules. with this approach I have to stub MongoDB and other external methods.

I thought about unit testing the individual routes and then using an integration test to verify that the correct routes are actually invoked.

integration tests - using Supertest and Superagent, much less code to write (no need to mock/stub anything) but a test environment should exist (databases, etc..)

I'm using Mocha to run both styles of tests.

how should I choose between those two different approaches ?


Source: (StackOverflow)

Testing a protected api call, mocha, supertest, node js, passport

I have a protected api call with passport as middleware:

  server.get('/api/pipes', auth, api.pipes);

The auth method returns a 401 if the user is no authorized.

I have this test to see if the user is loggedin:

  var postValidLoginCredentials = function(){
    return request(url).post('/api/login')
      .set('Content-Type', 'multipart/form-data')
      .field('email', 'john.smith@example.com')
      .field('password', 'example')
  };

//This pass passes
it('should return 200 OK when a user enters a valid user and pass', function(done){
  postValidLoginCredentials()
  .end(function(err, res){
    res.should.have.status('200');
    done();
  });
});

This is my test for my protected api call:

it('should return 200 OK on GET /api/pipes when user is loggedin', function (done) {
      postValidLoginCredentials()
        .end(function(err, res){
          request(url)
            .get('/api/pipes')
            .set('Accept', 'application/json')
            .expect(200, done);
        })
    });

I first post my login. In the login callback I then call my protected api call. It should be 200 but I get 401. The feature works in my client, so it's something wrong in my test.

I also tried to but my postValidLoginCredentials in a function, but it didn't work.

Any idea?


Source: (StackOverflow)

Is supertest compatible with express.js 2.5.8?

I am using express.js version 2.5.8 (from legacy code) and am looking to test route loading using supertest. I am having an issue with the server running, but not stopping. I run my tests using jasmine-node, which indicates that my assertion succeeds. However, the console shows that the process is still running.

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

describe('Example Test', function() {
  var app;

  beforeEach(function() {
    app = express.createServer();

    app.configure(function() {
      app.set('port', process.env.PORT || 3000);
      app.use(express.logger('dev'));
      app.use(express.bodyParser());
      app.use(express.methodOverride());
    });

    app.get('/', function(req, res){
      res.send(200);
    });
  });

  it('index should return 200', function(done) {
    request(app)
    .get('/')
    .expect(200)
    .end(function(err, res) {
      expect(err).toBe(null);
      done();
    });
  });
});

This example is adapted from one likely using express.js 3.x.x. My assumption is that the express server behaves differently, leading to it not closing when the request terminates inside the test. I am uncertain how to correct this issue.


Source: (StackOverflow)

How to test Express.js routes with Jasmine 2.3 and SuperTest

I'm using Jasmine 2.3 installed via NPM and executed with Grunt.

'use strict';

module.exports = function(grunt) {
    grunt.initConfig({
        package: grunt.file.readJSON('package.json'),
        exec: {
            jasmine: 'node_modules/.bin/jasmine'
        }
    });
    require('load-grunt-tasks')(grunt);
    require('time-grunt')(grunt);
    grunt.registerTask('default', 'exec:jasmine');
};

I exported an Express.js application object and using it in my specs along with SuperTest.

'use strict';

var supertest = require('supertest')
var application = require('../../../../../server');

describe('GET /api/users', function() {
    it('should respond with json', function(done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, done);
    });
});

When I run the spec I get no errors even though a 200 status code was expected and 404 was the result. Is the problem in Jasmine or SuperTest, or maybe I should be using SuperAgent.

I have no routes setup just a 404 error handler setup on the Express application object.

application.use(function(request, response, next) {
    response
        .status(404)
        .send({
            message: 'not found'
        });
});

Source: (StackOverflow)

How can i synchronous test with supertest

codes:

should = require('should')
request = require('supertest')
request = request("stackoverflow.com");

describe "temp", ->

    input_output = [
        { input:"[mocha] [supertest]", output: ["asdf", "asdf"] }
        { input:"아버지가방에들어가신다", output: [ '아버지가방에들어가신다', '아버지', '가방', '에들', '어가', '신다' ] }
        { input:"hi hello", output: ["hi", "hello"] }
    ]

    for item in input_output 

        it "curl http://stackoverflow.com/search?q=#{item.input}", (done) ->

            request
                .get("/search?q=#{item.input}")
                .expect(200)
                .expect (res) ->
                    console.log item.input
                    return
                .end(done)

outputs:

i expected below outputs:

i know if i test without callback then i can synchronous test. but didnt work.


Source: (StackOverflow)

supertest and multiple execution of similar routes

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');
}

Source: (StackOverflow)

Testing if download is successful with supertest

I'm testing my API endpoints with supertest, and it works great, but i can't figure out how to test if a file download is successful.

In my routes file i have defined the endpoint to be:

app.get('/api/attachment/:id/file', attachment.getFile);

and the function getFile() looks something like this:

exports.getFile = function(req, res, next) {
    Attachment.getById(req.params.id, function(err, att) {
        [...]
        if (att) {
            console.log('File found!');
            return res.download(att.getPath(), att.name);
        }

Then, in my test file, I try the following:

describe('when trying to download file', function() {
    it('should respond with "200 OK"', function(done) {
        request(url)
        .get('/api/attachment/' + attachment._id + '/file');
        .expect(200)
        .end(function(err, res) {
            if (err) {
                return done(err);
            }
            return done();
        });
    });
});

I know for sure that the file is found, because it logs out File found!. It also works fine if i try manually, but for some reason, mocha returns Error: expected 200 "OK", got 404 "Not Found".

I've experimented with different mime-types and supertest .set("Accept-Encoding": "*"), but nothing works.

Anyone know how to do this?


Source: (StackOverflow)

mocha supertest ECONNRESET

I'm testing a Nodejs server with Mocha and Supertest. The test suite has grown to more than 1500 tests. Suddenly, although all of the code under test still works, my test suite fails with this error:

{ [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }

If I comment out some tests that run earlier, the tests that cause the error change. What is causing this insanity?


Source: (StackOverflow)

Access to "req" Object in Supertest After a Response

Is there any way to directly access the req object in supertest, while/after the request is being tested? I want to test my passport strategies, so I want to check req.user, req.session, and perhaps others. I know I can test page redirects or flash, as those are what my strategies do, but it seems useful to see if there is a user on the req object, as well. If I do this, I can also check how many users there are at any one time.

I will sign users up with the "local-signup" strategy, which is defined thusly:

'use strict';

// get passport & mongoose
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var UserModel = require('mongoose').model('User');

module.exports = function() {

    // signup function
    passport.use('local-signup', new LocalStrategy({
            passReqToCallback: true // pass the entire request to the callback
        },

        function(req, username, password, done) {

            process.nextTick(function() {

            // find a user with the same username
                UserModel.findOne({username: username}, function(err, user) {

                    // if there is an error, log it then return it
                    if(err) {
                        console.log("Error finding a user in the database: " + err);
                        return done(err);
                    }

                    // if a user was already found
                    if(user) {
                        return done(null, false, "User already exists");
                    }

                    // if we get this far, create a new user from the request body
                    var newUser = new UserModel(req.body);

                    // save it and sign it in
                    newUser.save(function(err) {
                        if(err) {
                            console.log("Error during signup: " + err);
                            return done(err);
                        }
                        return done(null, newUser);
                    });

                });

            });

        }

    ));

};

One way I use this strategy is like this:

My "local" strategy is defined like this:

'use strict';

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var UserModel = require('mongoose').model('User');

module.exports = function() {

    // create our local passport strategy & use it
    passport.use(new LocalStrategy({

            // use the default names for the username & password fields
            usernameField: 'username',
            passwordField: 'password'
        },

        // main strategy function
        function(username, password, done) {

            // find user with given username
            UserModel.findOne({
                username: username
            },

            // with this username, do this
            function(err, user) {

                // if there's an error, log it then pass it along
                if(err) {
                    console.log("Error during login: " + err);
                    return done(err);
                }

                // if the username and/or password is incorrect, return an error
                // along with a message
                if(!user || !user.authenticate(password)) {
                    return done(null, false, {
                        message: 'Invalid username and/or password'
                    });
                }

                // if everything is correct, return the user document from the database
                return done(null, user);

            });
        }

    ));
};

I use both strategies like this, for example:

app.route(pageName).post(function(req, res, next) {
    passport.authenticate(strategyName, function(err, user, info) {
        if(err || !user) {
            res.status(401).send(info);
        }
        else {
            req.login(user, function(err) {
                if(err) {
                    res.status(400).send(err);
                }
                else {
                    res.send(null);
                }
            });
        }
    })(req, res, next);
});

I tried

request = require('supertest');
this.authServer = require('../my-server');

request(this.authServer)
    .put('/signup')
    .set('Content-Type', 'application/json')
    .set('Host', 'konneka.org')
    .send(this.fullUser)
    .end(function(req, res, done) {
        console.log(res);
    });

The res object I logged, inside the end() function, which was way too long to show here, has a req object defined on it, but it seems to only have the objects & functions that were defined before the request was opened. In other words, it does not have req.user, req.session, or other objects I want, because they are defined after the request completes and a new request is started. I noticed it has status codes, as well, which are only defined after the request completes, so I must be missing something.

Is there any way to get access to the req object after the request you are testing is ended? Or am I going about this completely the wrong way?


Source: (StackOverflow)

NodeJS testing HTTPS server with supertest

I read about supertest. I managed to test two of my routes:

it('notAuthorized', function (done) {
    request.agent(server)
        .get('/notAuthorized')
        .expect('Content-Type', /html/)
        .expect(200)
        .expect(/Not authorized!/)
        .end(done)
})

it('redirect', function (done) {
    request.agent(server)
        .get('/no-valid-route')
        .expect('Content-Type', /plain/)
        .expect(302)
        .expect('Location', '/notAuthorized')
        .expect(/Moved Temporarily/)
        .end(done)
})


However, the problem starts when I want to access my other pages, those I need to register for. I found this solution for a regular registration:

describe('When logged in', function () {
    before(function (done) {
        // login the user
        agent
            .post('/users/session')
            .field('email', 'foobar@example.com')
            .field('password', 'foobar')
            .end(done)
    })

    // ...
})


In my application I register with a certificate. Can I somehow configure the test with my certificate? Changing my https options doesn't work either:

///////////////////
// https options
var options = {
    // ...
    requestCert: false,
    rejectUnauthorized: false
};


I assume it is because of my middle ware I use in every of my routes:

 exports.isAuthenticated = function(req, res, next){
    if(req.client.authorized) {
        // user authorized
        if(!req.session.user) {
            // set user session
            var cert = req.connection.getPeerCertificate().subject;
        // ..


// profile
app.get("/profile", mw.isAuthenticated, profileController.getProfile);

// user
app.get("/users", mw.isAuthenticated, userController.getUsers);

// chat
app.get("/chat", mw.isAuthenticated, chatController.getChat);


Question:

  • is there anyway I can configure the agent with my certificate?
  • should I maybe overthink the design of using the isAuthenticated middle ware in every route?
  • can I somehow change the cookie object of supertest's agent?

If I could set the req object like the following snippet, I'd probably have a solution.

    req : {
        client : {
            authorized : true
        },
        connection :{
            getPeerCertificate : function(){
                this.subject = 1;
            }
        }
    }

Source: (StackOverflow)

Reuse Supertest tests on a remote URL

I'm using MochaJS and SuperTest to test my API during development and absolutely LOVE it.

However, I would like to also turn these same tests to remotely tests my staging server before pushing the code out to production.

Is there a way to supply request with a remote URL or proxy to a remote URL?

Here is a sample of a test I use

        request(app)
        .get('/api/photo/' + photo._id)
        .set(apiKeyName, apiKey)
        .end(function(err, res) {
            if (err) throw err;
            if (res.body._id !== photo._id) throw Error('No _id found');
            done();
        });

Source: (StackOverflow)