UNPKG

@nypl/node-lambda-boilerplate

Version:

An AWS node-lambda boilerplate written in ES7 via Babel that includes various configuration, testing, and deployment scripts

185 lines (146 loc) 9.21 kB
/* eslint-disable semi */ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { getOauthConfig, fetchAccessToken, handleAuthentication } from '../../src/helpers/OAuthHelper'; import LambdaError from '../../src/helpers/ErrorHelper'; const expect = chai.expect; chai.should(); chai.use(chaiAsPromised); describe('OAuth Helper', () => { let mock; beforeEach(() => { mock = new MockAdapter(axios); }); afterEach(() => { mock.reset(); }); describe('getOauthConfig(clientId, clientSecret, scope, grantType) function', () => { it('should throw an error if the cliendId parameter is NULL', () => { expect(() => getOauthConfig(null, 'clientSecret', 'scope')).to.throw(/the clientId parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the clientId parameter is NOT a string', () => { expect(() => getOauthConfig({}, 'clientSecret', 'scope')).to.throw(/the clientId parameter is not defined or invalid; must be of type string and not empty/); expect(() => getOauthConfig(123, 'clientSecret', 'scope')).to.throw(/the clientId parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the clientId parameter is an EMPTY string', () => { expect(() => getOauthConfig('', 'clientSecret', 'scope')).to.throw(/the clientId parameter is not defined or invalid; must be of type string and not empty/); expect(() => getOauthConfig(' ', 'clientSecret', 'scope')).to.throw(/the clientId parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the clientSecret parameter is NULL', () => { expect(() => getOauthConfig('clientId', null, 'scope')).to.throw(/the clientSecret parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the clientSecret parameter is NOT a string', () => { expect(() => getOauthConfig('clientId', {}, 'scope')).to.throw(/the clientSecret parameter is not defined or invalid; must be of type string and not empty/); expect(() => getOauthConfig('clientId', 123, 'scope')).to.throw(/the clientSecret parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the clientSecret parameter is an EMPTY string', () => { expect(() => getOauthConfig('clientId', '', 'scope')).to.throw(/the clientSecret parameter is not defined or invalid; must be of type string and not empty/); expect(() => getOauthConfig('clientId', '', 'scope')).to.throw(/the clientSecret parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the scope parameter is NULL', () => { expect(() => getOauthConfig('clientId', 'clientSecret', null)).to.throw(/the scope parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the scope parameter is NOT a string', () => { expect(() => getOauthConfig('clientId', 'clientSecret', {})).to.throw(/the scope parameter is not defined or invalid; must be of type string and not empty/); expect(() => getOauthConfig('clientId', 'clientSecret', 123)).to.throw(/the scope parameter is not defined or invalid; must be of type string and not empty/); }); it('should throw an error if the scope parameter is an EMPTY string', () => { expect(() => getOauthConfig('clientId', 'clientSecret', '')).to.throw(/the scope parameter is not defined or invalid; must be of type string and not empty/); expect(() => getOauthConfig('clientId', 'clientSecret', ' ')).to.throw(/the scope parameter is not defined or invalid; must be of type string and not empty/); }); it('should set the grantType as default value if not defined', () => { const result = getOauthConfig('clientId', 'clientSecret', 'scope'); expect(result).to.be.an('object').and.to.deep.equal({ client_id: 'clientId', client_secret: 'clientSecret', grant_type: 'client_credentials', scope: 'scope' }); }); it('should set the grantType optional parameter and NOT use the default', () => { const result = getOauthConfig('clientId', 'clientSecret', 'scope', 'customGrantType'); expect(result).to.be.an('object').and.to.deep.equal({ client_id: 'clientId', client_secret: 'clientSecret', grant_type: 'customGrantType', scope: 'scope' }); }); }); describe('fetchAccessToken(oauthUrl, clientId, clientSecret, scope, grantType) function', () => { it('should reject the Promise if the oauthUrl string parameter is NULL', () => { const result = fetchAccessToken(null, 'clientId', 'clientSecret', 'scope', 'customGrantType'); return result.should.be.rejectedWith(LambdaError, 'the oauthUrl function parameter is not defined or invalid; must be of type string and not empty'); }); it('should reject the Promise if the oauthUrl string parameter is NOT a string', () => { const result = fetchAccessToken({}, 'clientId', 'clientSecret', 'scope', 'customGrantType'); return result.should.be.rejectedWith(LambdaError, 'the oauthUrl function parameter is not defined or invalid; must be of type string and not empty'); }); it('should reject the Promise if the oauthUrl string parameter is EMPTY', () => { const result = fetchAccessToken(' ', 'clientId', 'clientSecret', 'scope', 'customGrantType'); return result.should.be.rejectedWith(LambdaError, 'the oauthUrl function parameter is not defined or invalid; must be of type string and not empty'); }); it('should resolve the Promise with an access_token when the OAuth URL is valid', () => { mock.onPost().reply( 200, { access_token: 'validaccesstoken' } ); const response = fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope'); return response.should.be.fulfilled.and.should.become('validaccesstoken'); }); it('should reject the Promise with an error response when response does not contain an access_token key', () => { mock.onPost().reply( 200, {} ); const response = fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope'); return response.should.be.rejectedWith(LambdaError, 'the oAuthResponse object contained an undefined access_token property'); }); it('should reject the Promise with an error response when the OAuth server returns a 404', () => { mock.onPost().reply(404); const response = fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope'); return response.should.be.rejected.and.should.eventually.have.property('statusCode', 404); }); it('should reject the Promise with an error response when the OAuth server returns a 500 (Internal Server Error)', () => { mock.onPost().reply(500); const response = fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope'); return response.should.be.rejected.and.should.eventually.have.property('statusCode', 500); }); }); describe('handleAuthentication(cachedToken, fetchTokenCallbackFn) function', () => { it('should resolve the Promise when the cachedToken parameter is already defined', () => { const result = handleAuthentication('cachedTokenValue'); return result.should.be.fulfilled.and.should.eventually.deep.equal({ tokenType: 'cached-token', token: 'cachedTokenValue' }); }); it('should call the fetchTokenCallbackFn to resolve a new token when the cachedToken is not defined', () => { mock.onPost().reply( 200, { access_token: 'newAccessTokenResolved' } ); const result = handleAuthentication(null, fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope')); return result.should.be.fulfilled.and.should.eventually.deep.equal({ tokenType: 'new-token', token: 'newAccessTokenResolved' }); }); it('should call the fetchTokenCallbackFn when the cachedToken is undefined and if an API (5xx) error occurs should reject the Promise with the error', () => { mock.onPost().reply(500); const result = handleAuthentication(null, fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope')); return result.should.be.rejected.and.should.eventually.have.property('statusCode', 500); }); it('should call the fetchTokenCallbackFn when the cachedToken is undefined and if an API (4xx) error occurs should reject the Promise with the error', () => { mock.onPost().reply(401); const result = handleAuthentication(null, fetchAccessToken('http://oauth.testurl.org', 'clientId', 'clientSecret', 'scope')); return result.should.be.rejected.and.should.eventually.have.property('statusCode', 401); }); }); });