Git Product home page Git Product logo

supertest-session's Introduction

Supertest sessions

Session wrapper around supertest.

Coverage Status

References:

Installation

$ npm install --save-dev supertest supertest-session

Test

$ npm test

Usage

Require supertest-session and pass in the test application:

var session = require('supertest-session');
var myApp = require('../../path/to/app');

var testSession = null;

beforeEach(function () {
  testSession = session(myApp);
});

And set some expectations:

it('should fail accessing a restricted page', function (done) {
  testSession.get('/restricted')
    .expect(401)
    .end(done)
});

it('should sign in', function (done) {
  testSession.post('/signin')
    .send({ username: 'foo', password: 'password' })
    .expect(200)
    .end(done);
});

You can set preconditions:

describe('after authenticating session', function () {

  var authenticatedSession;

  beforeEach(function (done) {
    testSession.post('/signin')
      .send({ username: 'foo', password: 'password' })
      .expect(200)
      .end(function (err) {
        if (err) return done(err);
        authenticatedSession = testSession;
        return done();
      });
  });

  it('should get a restricted page', function (done) {
    authenticatedSession.get('/restricted')
      .expect(200)
      .end(done)
  });

});

Accessing cookies

The cookies attached to the session may be retrieved from session.cookies:

var sessionCookie = testSession.cookies.find(function (cookie) {
  return cookie.name === connect.sid;
});

If you're using

Request hooks

By default, supertest-session authenticates using session cookies. If your app uses a custom strategy to restore sessions, you can provide before and after hooks to adjust the request and inspect the response:

var testSession = session(myApp, {
  before: function (req) {
    req.set('authorization', 'Basic aGVsbG86d29ybGQK');
  }
});

Cookie Jar Access Options

By default supertest-session will derive the CookieAccessInfo config of the cookie jar from the agent configuration. There might be cases where you want to override this, e.g. if you're testing a service which is configured to run behind a proxy but which sets secure cookies. To have supertest-session expose these secure cookies you can provide an override config to the internal call to CookieAccessInfo:

var cookieAccess = {
  domain: 'example.com',
  path: '/testpath',
  secure: true,
  script: true,
};
var testSession = session(myApp, { cookieAccess: cookieAccess });

By default the underlying supertest agent will still determine the CookieAccessInfo from the URL. If you want supertest-session to instead send cookies according to this cookieAccess config you can make use of the before hook:

var cookieAccess = {
  domain: 'example.com',
  path: '/testpath',
  secure: true,
  script: true,
};
var testSession = session(myApp, {
  cookieAccess: cookieAccess,
  before: function (req) {
    req.cookies = this.cookies.toValueString();
  },
});

License

MIT

supertest-session's People

Contributors

aaronik avatar ctavan avatar danpe avatar dependabot[bot] avatar merceyz avatar neamar avatar ngerakines avatar rjz avatar steebchen 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

supertest-session's Issues

pass envs to application

the following documentation is missleading, but obvious passing envs to the app ist not possible, when the app is already initialized.

var Session = require('supertest-session')({
  app: require('../../path/to/app'),
  envs: { NODE_ENV: 'development' }
});

what you have to do work with envs consistently:

process.env['NODE_ENV'] = "development";
var Session = require('supertest-session')({
  app: require('../../path/to/app'),
}); 

I would suggest to depreciate the use of your envs, cause the status of envs changes over runtime.

Dependency declarations missing for clean load in Yarn PnP / Berry

When running supertest-session in a project that uses Yarn PnP / Berry, the following two errors are reported:

supertest-session tried to access methods, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.

    Required package: methods (via "methods")
    Required by: supertest-session@virtual:640d59121dc50aef8c4e2e9c0fc24c425951c20d64b04f5476f7080bfeeaf953e8d8f92366ff62026e8f3b035a2de8fa49aa2900c07271fe8ad998892fded072#npm:4.0.0 (via .yarn/$$virtual/supertest-session-virtual-c7c934f209/0/cache/supertest-session-npm-4.0.0-30aab972e9-4b62b93e4e.zip/node_modules/supertest-session/)
supertest-session tried to access cookiejar, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.

    Required package: cookiejar (via "cookiejar")
    Required by: supertest-session@virtual:640d59121dc50aef8c4e2e9c0fc24c425951c20d64b04f5476f7080bfeeaf953e8d8f92366ff62026e8f3b035a2de8fa49aa2900c07271fe8ad998892fded072#npm:4.0.0 (via .yarn/$$virtual/supertest-session-virtual-c7c934f209/0/cache/supertest-session-npm-4.0.0-30aab972e9-4b62b93e4e.zip/node_modules/supertest-session/)

This is using version [email protected].

Workaround

Add the following to .yarnrc.yml:

packageExtensions:
  supertest-session@*:
    dependencies:
      methods: '*'
      cookiejar: '*

Don't send Expires options

Hi,

In my use-case I have cookies with the option "Expires", so I send headers like that :

Set-Cookie : connect.sid=s%3AlMtQUjJP9PkhsoIlWwFCMjm-rawiAuS4.aIvx9Vi%2BEisilzFza9SO6U7Ko8doDy4QF5ypVWTCz%2BI; Path=/; Expires=Mon, 17 Nov 2014 13:53:31 GMT; HttpOnly

But with this lib when I make a request you remove the parameter "Path" but keep "Expires".
Here is an example :

Cookies : connect.sid=s:QGr6asW74gtqnC-PQ_bsP2wXHG3por9U.EejvZh2m2TU6i3te4LIcmBNCUsTYqDHDBTvkc5OkLA8,Expires=Mon, 17 Nov 2014 13:59:54 GMT

If I'm not mistaken, it would remove "Expires".

Test stops after when use authenticatedSession

const session = require('supertest-session');
const myApp = require('../../app');

describe('Test sample', () => {

  let testSession;
  let authenticatedSession;

  beforeEach( () => {
    testSession = session(myApp);
  });

  it('/member/login', (done) => {
    testSession.post('/member/login')
      .send({ userid: '[email protected]', password: 'test' })
      .expect(302)
      .end(function (err) {
        if (err) { return done(err); }
        authenticatedSession = testSession;
        return done();
      });
  });

  // if there is this test, test freezes after all test suite finished
  it('/member/profile', (done) => {
    authenticatedSession.get('/member/profile')
      .expect(200)
      .end(done); 
  });
});

Written by Typescript, but executed as javascript with jest

Use superagent for cookie handling

supertest instances now expose a superagent .agent that includes cookie attachment/handling. Leaning on this implementation will simplify supertest-session and allow its users to take advantage of any features and options supported by superagent.

legacySession is completely broken

I want to use supertest-session to test a non-Express API. In my original code, I'd have this line:

request('http://www.google.com').get('/asdf').expect(404).end(done);

I get an error along the lines of "undefined is not a function." Through a little debugging, I found that it thought request("...").get is undefined. So I opened up the module and found this in the module.exports function:

if (typeof app != 'function') {
  return deprecatedLegacySession(app);
}

deprecatedLegacySession calls:

function legacySession (config) {
  if (!config) config = {};

  // Bind session to `config`
  function LegacySession () {
    Session.call(this, config.app, config);
  }

  util.inherits(LegacySession, Session);
  assign(LegacySession.prototype, {}, config.helpers);

  return LegacySession;
}

And there's a lot of issues with this. First, config is the app string I passed in and is not used properly as the string. The function returns the inner LegacySession function, it should create a new instance of the LegacySession instead of returning the function. That doesn't matter because the LegacySession is messed up. It tries to get config.app but config is a string. The whole legacySession function should be:

function legacySession (app, config) {
  if (!config) config = {};

  // Bind session to `config`
  function LegacySession () {
    Session.call(this, app, config);
  }

  util.inherits(LegacySession, Session);
  assign(LegacySession.prototype, {}, config.helpers);

  return new LegacySession();
}

Or, an even easier solution, completely remove the if (typeof app != 'function') {...} check out of your module.exports function. Doing so means I can properly use request("http://www.google.com") as advertised.

Promise wrapper method

Would you be open to a PR that adds a mongoose-style exec method?

Usage would look like this:

supertest( app )
.get( '/someRoute' )
.expect( 200 )
// wraps supertest.end in a promise
.exec()
.then( function() {
    // success
})
.catch( function( error ) {
    // failure
});

Server sets two cookies during a request, supertest-session persists only one

I have the followin test routes, the first sets a cookie, the second retrieves it.

    server.get('/t2/:z',  (req, res) => {
        req.session = {v: req.params.z}
        res.send(req.session)
    })

    server.get('/t3',  (req, res) => {
        logger.debug("cookie header: %s", req.headers.cookie)
        res.send(req.session)
    })

I am using cookie-session: https://github.com/expressjs/cookie-session
to handle sessions

When I test the above routes with a browser, it works as expected, and I can see that cookie-session sets two cookies, one for the session object, and one for the signature (session.sig), as the log shows:

cookie header: _ga=GA1.1.984665860.1553382018; session=eyJ2IjoicXEifQ==; session.sig=kJH4iEj4NkYR4HwYyo0QI42fF9A

When I use supertest-session, only one cookie gets set, as show by the log :

cookie header: session=eyJ2IjoicXdlcnR5In0=

Which causes cookie-session to not recognize the session, since it has no signature cookie.

The jest / supertest-session code is below.

Is there a way to tell supertest-session to persist all cookies set during a request ?

import cookieSession from 'cookie-session'
import session from 'supertest-session'
import express from 'express'

const server = createRoutes(
    express()
    .use(express.json())
    .use(cookieSession({
        name: 'session',
        signed: true,
        secret: process.env.COOKIE_SIGNING_SECRET,
        maxAge: 30 * 60 * 1000
      }))
      .use((req, res, next) => {
        req.session.now = Date.now()
        next()
      })
)


    test.only("test session-cookie", async done => {

        const testSession = session(server)

        const res1 = await testSession.get('/t2/qwerty').send()

        expect(res1.status).toEqual(200)
        expect(res1.body.v).toEqual("qwerty")

        const res2 = await testSession.get('/t3').send()

        expect(res2.status).toEqual(200)
        expect(res2.body.v).toEqual("qwerty")
    })

NPM Audit report - Supertest version update.

Hi @rjz,

We just bumped our stack to Node 10 and NPM6 and I got this report from npm audit from this lib.

│ Low │ Large gzip Denial of Service
│ Package │ superagent
│ Patched in │ >=3.7.0
│ Dependency of │ supertest-session [dev]
│ Path │ supertest-session > supertest > superagent
│ More info │ https://nodesecurity.io/advisories/479

I have tried updating supertest to the 3.1.0 on my local, tests are passing, our projects haven't got issues and the security issue is resolved.

Would you considering update this dependency to remove the warning? I can send a PR if you prefer it, just let me know.

Thanks!

Impossible to write on req.session

Hello guys, actually i'm trying to test with supertest-session when I initialize the login I set the informations of the user on req.session.infoUser but jest is returning the error : Cannot set properties of undefined (setting 'infoUser')

I don't understand why i have this problem bc the function is working well and i can connect on my server req.session is working well

Clarity in Readme

Hey RJ,

I'm updating express for my company and in the process updating supertest-session. There's a piece of the README I'm a bit confused on, maybe you could help me and then clarify the README if it's accurate and fix it if it isn't.

On L51 it looks like we can go through with a privileged request after a previous signin. But, our testSession from the example is repopulated in a beforeEach callback. If testSession is trampled each time, wouldn't the signed in session cookies get nuked for each one? If so, looks like the README should employ a before function instead of a beforeEach. If not, color me confused, and maybe the README could use a note on it, depending on from how deep a well my confusion comes.

Cheers,

-- Aaron

Chaining problem when calling done inside expect

Supertest lets you call done inside of an expect call instead of calling .end(done). When you use supertest-session to do this, you cannot chain methods. For example, when you try something like this:

var request = require('supertest-session');
var user = request(app)
    .post('/login')
    .type('form')
    .send(credentials)
    .expect(302, done);

It does not chain correctly, and you need to instead use:

var request = require('supertest-session');
var user = request(app);
user
    .post('/login')
    .type('form')
    .send(credentials)
    .expect(302, done);

supertest-session is causing mocha test suite to hang

👋 @rjz thanks for creating this module. It looks like just what we need for testing the electron website.

I have the following test:

test('language query param for one-off viewing in other languages', async () => {
  const frenchContent = 'fenêtres'
  const sesh = session(app)

  let res = await sesh.get('/docs/api/browser-window?lang=fr-FR')
  let $ = cheerio.load(res.text)
  $('blockquote').text().should.include(frenchContent)

  // verify that the query param does not persist as a cookie
  res = await sesh.get('/docs/api/browser-window')
  $ = cheerio.load(res.text)
  $('blockquote').text().should.not.include(frenchContent)
})

The test itself passes, but it causes mocha to hang forever after the suite has run. If I disable this single test, the problem goes away. I thought maybe this was an issue with async/await. I change the code to use Promises, then, and done, but it still hangs.

Any ideas?

Failing PR: electron/electronjs.org-old#1034

Cannot retrieve session data stored in prior request

Hi.
My team is struggling to implement csrf tokens to our express APIs and run tests correctly.
Our app works well on real browsers, but the tests related with sessions fail.
We added csrf secret to session in GET request, but we cannot retrieve the secret in subsequent POST request.
We're trying to figure out whether we're using supertest-session in a wrong way, or something unexpected is happening (ex. some other Express middlewares interfere the test code).
We also want to know how to access session objects in test code to debug more closely.
We'd appreciate any help!

  • Problem

    • When we run the test , req.session._csrf in router.post('/login') is undefined
      • _csrf key is added to req.session in router.get('/login').
  • Test code

    var request = require('supertest'),
    var app = require('../../app');
    var session;
    var testSession = null;

    before(function(done) {
      session = require('supertest-session');
      testSession = session(app);
      testSession.get('/login')
        .end(function(err, res) {
          if (err) {
            console.log(err);
          }
          cookie = res.headers['set-cookie'];

          testSession.post('/login')
            .type('form')
            .set('cookie', cookie)
            .send({username: 'xxxxxxx'})
            .send({password: 'xxxxxxx'})
            .end(function(err, res) {
              if (err) {
                console.log(err);
              }
            });
        });
    });
  • Source code
router.get('/login',
  function(req, res, next) {
    var secret = tokens.secretSync();
    var token = tokens.create(secret);

    req.session._csrf = secret;
    res.cookie("_csrf", token);
    res.render('login', {error: req.flash('error')});
  }
);

router.post('/login', function(req, res, next) {
  var secret = req.session._csrf;
  var token = req.cookies._csrf;
  console.log(secret);  // undefined
  console.log(token);

  if (tokens.verify(secret, token) === false) {
    return next(new Error("Invalid Token"));
  }

  // authenticate user
});

Version 1.0.0 causes 'process out of memory'

After updating to 1.0.0 from 0.0.7, I get the following error

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

I noticed this error when then the HTTP status was set to 400 or 500 in some rather complex tests.

Missing documentation for manipulating session BEFORE calling methods

This is the how to do, hoping that will be putted into documentation:

    var session = new Session();
    // here we are setting the session value
    session.app.request.session = {
      user: {
        account: {
          username: USERNAME
        }
      }
    };
    session
      .post(util.format(urlAnsw, _id, 'FAKEUSER'))
      .expect(400)
      .expect('Content-Type', /json/)
      .end(function(err, res) {
        res.body.should.have.property('ok', false);
        res.body.err.should.be.exactly('Username is not the one online from this IP.');
        session.destroy();
        done();
      })

Use conformant API

supertest-session has two deviations from the supertest API:

  1. the package export is a function wrapping definition of the Session class with a specific config
  2. Sessions are created using the new keyword, but may not adjust their configuration at this time

Both decisions may be convenient in certain cases, but they limit runtime configuration (see #12) and add unnecessary complexity to the public API. An easy fix? Create Session instances via a supertest-esque factory function.

having the same issue

getting XSRF-TOKEN successfully but when i try to login it shows XSRF-TOKEN mismatch also it is working preety fine on browsers and postman**

`const app = require('../../../app.js');
const expect = require('chai').expect;
const request = require('supertest');
var csrfToken;

describe('GET /api/csrf-token', () => {
it('OK, Getting CSRF Token', (done) => {
request(app).get('/api/csrf-token')
.expect(200)
.then((res) => {
const body = res.body;
csrfToken=body.csrfToken;
expect(body).to.contain.property('csrfToken');
done();
})
.catch((err) => done(err));
});
});

describe('POST /api/users/login', () => {
it('OK, Logging in with super admin crediantials', (done) => {
request(app).post('/api/users/login')
.set('Content-Type', 'application/json')
.set("Accept","/")
.set("XSRF-TOKEN",csrfToken)
.set("Cookie","XSRF-TOKEN",csrfToken)
.set("withCredentials",true)
.expect(200)
.send({"email":"[email protected]","password":"abc"})
.expect((res) => {
const body = res.body;
console.log(body);
expect(body.message).to.contain.property('Auth Successful');
expect(body).to.contain.property('token');
done();
})
.catch((err) => done(err));
});
});
`

Originally posted by @ahmadbingulzar in #32 (comment)

Tests fail for instantiated app

The fix in #29 broke tests that create sessions around an existing instance of an app.

app, in my case, is an Object and not a Function. I already have a full working server, but I still need to extract the url from the app object itself.

HT @XVincentX

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.