'use strict';

/**
 * Module dependencies.
 */

var AuthenticateHandler = require('../../../lib/handlers/authenticate-handler');
var Request = require('../../../lib/request');
var sinon = require('sinon');
var should = require('should');
var ServerError = require('../../../lib/errors/server-error');

/**
 * Test `AuthenticateHandler`.
 */

describe('AuthenticateHandler', function() {
  describe('getTokenFromRequest()', function() {
    describe('with bearer token in the request authorization header', function() {
      it('should call `getTokenFromRequestHeader()`', function() {
        var handler = new AuthenticateHandler({ model: { getAccessToken: function() {} } });
        var request = new Request({
          body: {},
          headers: { 'Authorization': 'Bearer foo' },
          method: {},
          query: {}
        });

        sinon.stub(handler, 'getTokenFromRequestHeader');

        handler.getTokenFromRequest(request);

        handler.getTokenFromRequestHeader.callCount.should.equal(1);
        handler.getTokenFromRequestHeader.firstCall.args[0].should.equal(request);
        handler.getTokenFromRequestHeader.restore();
      });
    });

    describe('with bearer token in the request query', function() {
      it('should call `getTokenFromRequestQuery()`', function() {
        var handler = new AuthenticateHandler({ model: { getAccessToken: function() {} } });
        var request = new Request({
          body: {},
          headers: {},
          method: {},
          query: { access_token: 'foo' }
        });

        sinon.stub(handler, 'getTokenFromRequestQuery');

        handler.getTokenFromRequest(request);

        handler.getTokenFromRequestQuery.callCount.should.equal(1);
        handler.getTokenFromRequestQuery.firstCall.args[0].should.equal(request);
        handler.getTokenFromRequestQuery.restore();
      });
    });

    describe('with bearer token in the request body', function() {
      it('should call `getTokenFromRequestBody()`', function() {
        var handler = new AuthenticateHandler({ model: { getAccessToken: function() {} } });
        var request = new Request({
          body: { access_token: 'foo' },
          headers: {},
          method: {},
          query: {}
        });

        sinon.stub(handler, 'getTokenFromRequestBody');

        handler.getTokenFromRequest(request);

        handler.getTokenFromRequestBody.callCount.should.equal(1);
        handler.getTokenFromRequestBody.firstCall.args[0].should.equal(request);
        handler.getTokenFromRequestBody.restore();
      });
    });
  });

  describe('getAccessToken()', function() {
    it('should call `model.getAccessToken()`', function() {
      var model = {
        getAccessToken: sinon.stub().returns({ user: {} })
      };
      var handler = new AuthenticateHandler({ model: model });

      return handler.getAccessToken('foo')
        .then(function() {
          model.getAccessToken.callCount.should.equal(1);
          model.getAccessToken.firstCall.args.should.have.length(1);
          model.getAccessToken.firstCall.args[0].should.equal('foo');
        })
        .catch(should.fail);
    });
  });

  describe('validateAccessToken()', function() {
    it('should fail if token has no valid `accessTokenExpiresAt` date', function() {
      var model = {
        getAccessToken: sinon.stub().returns({ user: {} })
      };
      var handler = new AuthenticateHandler({ model: model });

      var failed = false;
      try {
        handler.validateAccessToken(model.getAccessToken);
      }
      catch (err) {
        err.should.be.an.instanceOf(ServerError);
        failed = true;
      }
      failed.should.equal(true);
    });

    it('should succeed if token has valid `accessTokenExpiresAt` date', function() {
      var model = {
        getAccessToken: sinon.stub().returns({
          user: {},
          accessTokenExpiresAt: new Date()
        })
      };
      var handler = new AuthenticateHandler({ model: model });

      try {
        handler.validateAccessToken(model.getAccessToken);
      }
      catch (err) {
        should.fail();
      }
    });
  });

  describe('verifyScope()', function() {
    it('should call `model.getAccessToken()` if scope is defined', function() {
      var model = {
        getAccessToken: function() {},
        verifyScope: sinon.stub().returns(true)
      };
      var handler = new AuthenticateHandler({ addAcceptedScopesHeader: true, addAuthorizedScopesHeader: true, model: model, scope: 'bar' });

      return handler.verifyScope('foo')
        .then(function() {
          model.verifyScope.callCount.should.equal(1);
          model.verifyScope.firstCall.args.should.have.length(2);
          model.verifyScope.firstCall.args[0].should.equal('foo', 'bar');
        })
        .catch(should.fail);
    });
  });
});

@@ -3343,42 +3343,21 @@
 en: 
-sinon.stub().returns(%7B user: %7B%7D %7D)
+function() %7B%7D
 %0A   
@@ -3500,36 +3500,46 @@
 ssToken(
-model.getAccessToken
+%7B%0A          user: %7B%7D%0A        %7D
 );%0A     
@@ -3817,104 +3817,21 @@
 en: 
-sinon.stub().returns(%7B%0A          user: %7B%7D,%0A          accessTokenExpiresAt: new Date()%0A        %7D)
+function() %7B%7D
 %0A   
@@ -3895,25 +3895,24 @@
 : model %7D);%0A
-%0A
       try %7B%0A
@@ -3947,36 +3947,118 @@
 ssToken(
-model.getAccessToken
+%7B%0A          user: %7B%7D,%0A          accessTokenExpiresAt: new Date(new Date().getTime() + 10000)%0A        %7D
 );%0A     

make tests easier to understand!