describe('session library', () => { // respond to session requests with empty session object const sessionNoUser = jest.fn((opts, callback) => { callback(null, {}, {statusCode: 200}); }); // respond to session requests with session object that indicates // successfully logged-in user const sessionYesUser = jest.fn((opts, callback) => { callback(null, {user: {username: 'test_username'}}, {statusCode: 200}); }); // respond to first two requests with empty session object; after that, // respond with user in object const sessionNoThenYes = jest.fn((opts, callback) => { if (sessionNoThenYes.mock.calls.length <= 2) { callback(null, {}, {statusCode: 200}); } else { callback(null, {user: {username: 'test_username'}}, {statusCode: 200}); } }); // respond to session requests with response code 404, indicating no session // found for that user const sessionNotFound = jest.fn((opts, callback) => { callback(null, null, {statusCode: 404}); }); // respond to session requests with response code 503, indicating connection failure const sessionConnectFailure = jest.fn((opts, callback) => { callback(null, null, {statusCode: 503}); }); // by changing whichMockAPIRequest, we can simulate different api responses let whichMockAPIRequest = null; const mockAPIRequest = (opts, callback) => { whichMockAPIRequest(opts, callback); }; // mock lib/api.js, and include our mocked version in lib/session.js jest.mock('../../../src/lib/api', () => mockAPIRequest); const sessionLib = require('../../../src/lib/session'); // eslint-disable-line global-require afterEach(() => { jest.clearAllMocks(); }); test('requestSession can call api 1 time, when session found', done => { whichMockAPIRequest = sessionYesUser; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSession(resolve, reject); }).then(body => { expect(sessionYesUser).toHaveBeenCalledTimes(1); expect(body).toEqual({user: {username: 'test_username'}}); done(); }); }); test('requestSession can call api 1 time, when session not found', done => { whichMockAPIRequest = sessionNoUser; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSession(resolve, reject); }).then(body => { expect(sessionNoUser).toHaveBeenCalledTimes(1); expect(body).toEqual({}); done(); }); }); test('requestSessionWithRetry can call api once', done => { whichMockAPIRequest = sessionNoUser; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSessionWithRetry(resolve, reject, 0, 0); }).then(() => { expect(sessionNoUser).toHaveBeenCalledTimes(1); done(); }); }); test('requestSessionWithRetry can call api multiple times', done => { whichMockAPIRequest = sessionNoUser; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSessionWithRetry(resolve, reject, 2, 0); }).then(() => { expect(sessionNoUser).toHaveBeenCalledTimes(3); done(); }); }); test('requestSessionWithRetry respects total delay time param within a reasonable tolerance', done => { whichMockAPIRequest = sessionNoUser; const startTime = new Date().getTime(); new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSessionWithRetry(resolve, reject, 2, 2500); }).then(() => { const endTime = new Date().getTime(); expect(endTime - startTime > 2000).toBeTruthy(); expect(endTime - startTime < 3000).toBeTruthy(); done(); }); }); test('requestSessionWithRetry will retry if no user found, then stop when user is found', done => { whichMockAPIRequest = sessionNoThenYes; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSessionWithRetry(resolve, reject, 4, 3000); }).then(body => { expect(body).toEqual({user: {username: 'test_username'}}); expect(sessionNoThenYes).toHaveBeenCalledTimes(3); done(); }); }); test('requestSessionWithRetry handles session not found as immediate error', done => { whichMockAPIRequest = sessionNotFound; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSessionWithRetry(resolve, reject, 2, 0); }).then(() => {}, err => { expect(err).toBeFalsy(); done(); }); }); test('requestSessionWithRetry handles connection failure by retrying', done => { whichMockAPIRequest = sessionConnectFailure; new Promise((resolve, reject) => { // eslint-disable-line no-undef sessionLib.requestSessionWithRetry(resolve, reject, 2, 0); }).then(body => { expect(sessionConnectFailure).toHaveBeenCalledTimes(3); expect(body).toBeFalsy(); done(); }); }); });