Skip to content

Instantly share code, notes, and snippets.

@cklanac
Last active November 3, 2018 08:48
Show Gist options
  • Save cklanac/8cae35715cc39f76fbb27bfc4d75bc1d to your computer and use it in GitHub Desktop.
Save cklanac/8cae35715cc39f76fbb27bfc4d75bc1d to your computer and use it in GitHub Desktop.
Challenge: 19.1 Testing Local Auth

Challenge - Testing Local Auth

In this challenge you will create a tests which verify the login process.

Create a Local Auth test

To test the login process, you first need to seed the database a user, then POST a username and password to the endpoint. The endpoint will return a JWT that you must verify using your JWT_SECRET.

To get started, create a /test/login.test.js file. And add the require packages and setup to the start of the file.

const app = require('../server');
const chai = require('chai');
const chaiHttp = require('chai-http');
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');

const { TEST_MONGODB_URI, JWT_SECRET } = require('../config');

const User = require('../models/user');

const expect = chai.expect;
chai.use(chaiHttp);

Note the additional of the JWT_SECRET. You will need this to verify the JWT returned from the /login endpoint.

Next, you will create a describe block with Mocha before, beforeEach, afterEach and after hooks. And create fullname, username and password variables with sample data which you will insert in to the DB and use to validate the login process.

The code in the hooks should look familiar, except for the beforeEach hook which hashes the password before inserting the user into the database.

describe.only('Noteful API - Login', function () {

  const fullname = 'Example User';
  const username = 'exampleUser';
  const password = 'password';

  before(function () {
    return mongoose.connect(TEST_MONGODB_URI)
      .then(() => mongoose.connection.db.dropDatabase());
  });

  beforeEach(function () {
    return User.hashPassword(password)
      .then(digest => User.create({ fullname, username, password: digest }));
  });


  afterEach(function () {
    return mongoose.connection.db.dropDatabase();
  });

  after(function () {
    return mongoose.disconnect();
  });

  // TESTS GO HERE
  
});

Add the following test to your file.

The test POSTs the username and password to the endpoint. The endpoint should respond with a JWT which is then verified. Finally, the test compares the payload with the known user info. The payload should not contain a password property, and the username and fullname should match the example user.

it('Should return a valid auth token', function () {
  return chai.request(app)
    .post('/api/login')
    .send({ username, password })
    .then(res => {
      expect(res).to.have.status(200);
      expect(res.body).to.be.an('object');
      expect(res.body.authToken).to.be.a('string');

      const payload = jwt.verify(res.body.authToken, JWT_SECRET);

      expect(payload.user).to.not.have.property('password');
      expect(payload.user.username).to.equal(username);
      expect(payload.user.fullname).to.equal(fullname);
    });
});

Now that you have a tested the positive a.k.a. "happy path" case, you need to test the negative (aka sad path), your challenge is to create tests for the negative a.k.a. "sad path" scenarios

  it('Should reject requests with no credentials');
  it('Should reject requests with incorrect usernames');
  it('Should reject requests with incorrect passwords');

Finally, we're going to test the /api/refresh endpoint. Here you'll need to create a JWT and add it to the Authorization header as part of the request.

Add another describe block with the following code:

  describe('/api/refresh', function () {

    it('should return a valid auth token with a newer expiry date', function () {
      const user = { username, fullname };
      const token = jwt.sign({ user }, JWT_SECRET, { subject: username, expiresIn: '1m' });
      const decoded = jwt.decode(token);

      return chai.request(app)
        .post('/api/refresh')
        .set('Authorization', `Bearer ${token}`)
        .then(res => {
          expect(res).to.have.status(200);
          expect(res.body).to.been.a('object');
          const authToken = res.body.authToken;
          expect(authToken).to.be.a('string');

          const payload = jwt.verify(authToken, JWT_SECRET);
          expect(payload.user).to.deep.equal({ username, fullname });
          expect(payload.exp).to.be.greaterThan(decoded.exp);
        });
    });
    
  });

Just like the /login tests, now that you have a tested the positive a.k.a. "happy path" case, your challenge is to create tests for the negative a.k.a. "sad path" scenarios

it('should reject requests with no credentials');
it('should reject requests with an invalid token');
it('should reject requests with an expired token');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment