UNPKG

victorops-api-client

Version:

A library for interacting with the VictorOps REST API

444 lines (356 loc) 14.5 kB
const chai = require('chai'); const chaiAsPromised = require('chai-as-promised'); const rewire = require('rewire'); const nock = require('nock'); const VictorOpsApiClient = require('../lib'); // Use 'chai-as-promised'. chai.use(chaiAsPromised); // Get 'expect'. const expect = chai.expect; const clientRewire = rewire('../lib/victorops_api_client'); const baseUrl = clientRewire.__get__('BASE_URL'); const apiPublic = clientRewire.__get__('API_PUBLIC'); const apiReporting = clientRewire.__get__('API_REPORTING'); const userAgent = clientRewire.__get__('USER_AGENT'); describe('VictorOps API Client Tests', () => { let client; const clientOptions = { apiId: 'c97d6dc9', apiKey: '5606f20bd449cfb873d82f59fecb7bba' }; beforeEach(() => { client = new VictorOpsApiClient(clientOptions); }); context(`'VictorOpsApiClient' Class instance`, () => { it(`should be an instance of 'VictorOpsApiClient'`, () => { expect(client).to.be.an('object'); expect(client).to.be.an.instanceof(VictorOpsApiClient); }); it(`should have a public 'constructor' method`, () => { expect(client.constructor).to.be.an('function'); expect(client.constructor).to.be.an.instanceof(Function); }); it(`should have a private '_checkOptions' method`, () => { expect(client._checkOptions).to.be.an('function'); expect(client._checkOptions).to.be.an.instanceof(Function); }); it(`should have a private '_getRequestHeaders' method`, () => { expect(client._getRequestHeaders).to.be.an('function'); expect(client._getRequestHeaders).to.be.an.instanceof(Function); }); it(`should have a private '_getAxiosInstance' method`, () => { expect(client._getAxiosInstance).to.be.an('function'); expect(client._getAxiosInstance).to.be.an.instanceof(Function); }); it(`should have a private '_getRequestOptions' method`, () => { expect(client._getRequestOptions).to.be.an('function'); expect(client._getRequestOptions).to.be.an.instanceof(Function); }); it(`should have a private '_performRequest' method`, () => { expect(client._performRequest).to.be.an('function'); expect(client._performRequest).to.be.an.instanceof(Function); }); it(`should have a private '_handleError' method`, () => { expect(client._handleError).to.be.an('function'); expect(client._handleError).to.be.an.instanceof(Function); }); it(`should have a public 'getApiPrefix' method`, () => { expect(client.getApiPrefix).to.be.an('function'); expect(client.getApiPrefix).to.be.an.instanceof(Function); }); }); context('#constructor()', () => { it(`should have a private '_options' property`, () => { let otherClient; expect(client).to.have.property('_options'); expect(client._options).to.be.an('object'); expect(client._options).to.eql(clientOptions); expect(() => { otherClient = new VictorOpsApiClient(); }).to.throw(); expect(otherClient).to.be.undefined; }); it(`should have a private '_apiId' property`, () => { expect(client).to.have.property('_apiId'); expect(client._apiId).to.be.a('string'); expect(client._apiId).to.eql(clientOptions.apiId); }); it(`should have a private '_apiKey' property`, () => { expect(client).to.have.property('_apiKey'); expect(client._apiKey).to.be.a('string'); expect(client._apiKey).to.eql(clientOptions.apiKey); }); }); context('#_checkOptions()', () => { it('should check and set the options', () => { const options = { apiId: 'ufos9fwo9ls9s', apiKey: '99hf9a9fy9qhuav29sy53gds4ilsu' }; client._checkOptions(options); expect(client._apiId).to.be.a('string'); expect(client._apiId).to.eql(options.apiId); expect(client._apiKey).to.be.a('string'); expect(client._apiKey).to.eql(options.apiKey); }); it(`should throw an error when missing an 'apiId'`, () => { const options = { apiKey: '99hf9a9fy9qhuav29sy53gds4ilsu' }; expect(() => client._checkOptions(options)).to.throw(Error, 'A VictorOps Api ID is a required option.'); }); it(`should throw an error when 'apiId' is empty`, () => { const options = { apiId: '', apiKey: '99hf9a9fy9qhuav29sy53gds4ilsu' }; expect(() => client._checkOptions(options)).to.throw(Error, 'A VictorOps Api ID is a required option.'); }); it(`should throw an error when missing an 'apiKey'`, () => { const options = { apiId: 'ufos9fwo9ls9s' }; expect(() => client._checkOptions(options)).to.throw(Error, 'A VictorOps Api Key is a required option.'); }); it(`should throw an error when 'apiKey' is empty`, () => { const options = { apiId: 'ufos9fwo9ls9s', apiKey: '' }; expect(() => client._checkOptions(options)).to.throw(Error, 'A VictorOps Api Key is a required option.'); }); }); context('#_getRequestHeaders()', () => { it('should get the request headers', () => { const expectedHeaders = { 'Accept': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8', 'X-VO-Api-Id': clientOptions.apiId, 'X-VO-Api-Key': clientOptions.apiKey, 'User-Agent': userAgent, }; const headers = client._getRequestHeaders(); expect(headers).to.be.an('object'); expect(headers).to.eql(expectedHeaders); }); it(`should throw an error when missing an 'apiId'`, () => { client._apiId = null; client._apiKey = clientOptions.apiKey; expect(() => client._getRequestHeaders()).to.throw(Error, 'Missing the Api ID (apiId) or Api Key (apiKey).'); }); it(`should throw an error when missing an 'apiKey'`, () => { client._apiId = clientOptions.apiId; client._apiKey = null; expect(() => client._getRequestHeaders()).to.throw(Error, 'Missing the Api ID (apiId) or Api Key (apiKey).'); }); }); context('#_getRequestOptions()', () => { it('should get the request options without query parameters or body', () => { // Get the options. const options = client._getRequestOptions('GET', '/api-public/v1/user'); expect(options).to.be.an('object'); expect(options).to.have.property('url', '/api-public/v1/user'); expect(options).to.have.property('method', 'GET'); expect(options.params).to.be.undefined; expect(options.data).to.be.undefined; }); it('should get the request options with query parameters and without a body', () => { const query = { daysForward: 14 }; // Get the options. const options = client._getRequestOptions('GET', '/api-public/v2/user/testUser/oncall/schedule', query); expect(options).to.be.an('object'); expect(options).to.have.property('url', '/api-public/v2/user/testUser/oncall/schedule'); expect(options).to.have.property('method', 'GET'); expect(options).to.have.property('params'); expect(options.params).to.be.an('object'); expect(options.params).to.eql(query); expect(options.data).to.be.undefined; }); it('should get the request options with a body and without query parameters', () => { const body = { firstName: 'Boba', lastName: 'Fett', username: 'bobafett', email: 'bobafett@starwars.com', admin: true }; // Get the options. const options = client._getRequestOptions('POST', '/api-public/v1/user', null, body); expect(options).to.be.an('object'); expect(options).to.have.property('url', '/api-public/v1/user'); expect(options).to.have.property('method', 'POST'); expect(options).to.have.property('data'); expect(options.data).to.be.an('object'); expect(options.data).to.eql(body); expect(options.params).to.be.undefined; }); }); context('#_performRequest()', () => { const response = { users: [ [ { firstName: 'Boba', lastName: 'Fett', username: 'bobafett', email: 'bobafett@starwars.com', createdAt: '2020-01-31T14:19:33Z', passwordLastUpdated: '2020-01-31T14:19:33Z', verified: true, _selfUrl: '/api-public/v1/user/bobafett' } ] ] }; const fullResponse = { statusCode: 200, statusMessage: 'OK', headers: { 'content-type': 'application/json' }, data: response, }; it('should return a VictorOps API response', async () => { // Mock the API request. nock(baseUrl, { reqheaders: client._headers }) .get('/api-public/v1/user') .reply(200, response); // Get the options. const options = client._getRequestOptions('GET', '/api-public/v1/user'); // Perform the request. const users = await client._performRequest(options); expect(users).to.be.an('object'); expect(users).to.eql(response); nock.cleanAll(); }); it('should return a full VictorOps API response', async () => { // Mock the API request. nock(baseUrl, { reqheaders: client._headers }) .get('/api-public/v1/user') .reply(200, response); // Set the full response option. client.fullResponse = true; // Get the options. const options = client._getRequestOptions('GET', '/api-public/v1/user'); // Perform the request. const resp = await client._performRequest(options); expect(resp).to.be.an('object'); expect(resp).to.have.property('statusCode'); expect(resp).to.have.property('statusMessage'); expect(resp).to.have.property('headers'); expect(resp).to.have.property('data'); expect(resp).to.eql(fullResponse); nock.cleanAll(); }); it('should throw an error when missing the request options', async () => { await expect(client._performRequest()).to.be.rejectedWith(Error); await expect(client._performRequest('something')).to.be.rejectedWith(Error); await expect(client._performRequest([])).to.be.rejectedWith(Error); await expect(client._performRequest({})).to.be.rejectedWith(Error); }); }); context('#_handleError()', () => { it(`should return a 'StatusCodeError' error`, () => { const statusCode = 403; const statusText = 'Authentication failed or rate-limit reached'; const err = new Error(`Request failed with status code ${statusCode}`); // Mock Axios response object. err.response = { status: statusCode, statusText, headers: {}, data: 'Bad stuff', }; // Add the typical Axios error values. err.code = null; err.config = {}; err.request = {}; err.isAxiosError = true; err.toJSON = () => {}; // Create the error. const handledErr = client._handleError(err); expect(handledErr).to.be.an.instanceof(Error); expect(handledErr.name).to.eql('StatusCodeError'); expect(handledErr.message).to.eql(String(err)); expect(handledErr.statusCode).to.eql(statusCode); expect(handledErr.statusMessage).to.eql(statusText); expect(handledErr.headers).to.eql({}); expect(handledErr.body).to.eql('Bad stuff'); expect(handledErr).to.have.property('cause'); expect(handledErr.cause).to.be.an.instanceof(Error); expect(handledErr.cause.message).to.eql(err.message); }); it(`should return a 'RequestError' error`, () => { const err = new Error('Oops, something happened'); err.config = {}; err.response = undefined; // Create the error. const handledErr = client._handleError(err); expect(handledErr).to.be.an.instanceof(Error); expect(handledErr.name).to.eql('RequestError'); expect(handledErr.message).to.eql(String(err)); expect(handledErr).to.have.property('cause'); expect(handledErr.cause).to.be.an.instanceof(Error); expect(handledErr.cause.message).to.eql(err.message); }); it(`should return an unmodified error`, () => { const err = new Error('Oops, something happened'); // Create the error. const handledErr = client._handleError(err); expect(handledErr).to.be.an.instanceof(Error); expect(handledErr).to.eql(err); }); }); context('#getApiPrefix()', () => { let apiPrefix; it('should return the regular API prefix without a path', () => { // Get the prefix. apiPrefix = client.getApiPrefix(); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiPublic}/v1`); // Get the prefix with version. apiPrefix = client.getApiPrefix(undefined, 2); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiPublic}/v2`); }); it('should return the regular API prefix with a path', () => { // Get the prefix. apiPrefix = client.getApiPrefix('alerts'); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiPublic}/v1/alerts`); // Get the prefix with version. apiPrefix = client.getApiPrefix('alerts', 2); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiPublic}/v2/alerts`); }); it('should return the reporting API prefix without a path', () => { // Get the prefix. apiPrefix = client.getApiPrefix(undefined, undefined, true); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiReporting}/v1`); // Get the prefix with version. apiPrefix = client.getApiPrefix(undefined, 2, true); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiReporting}/v2`); }); it('should return the reporting API prefix with a path', () => { // Get the prefix. apiPrefix = client.getApiPrefix('team/myteam', undefined, true); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiReporting}/v1/team/myteam`); // Get the prefix with version. apiPrefix = client.getApiPrefix('team/myteam', 2, true); expect(apiPrefix).to.be.a('string'); expect(apiPrefix).to.eql(`${apiReporting}/v2/team/myteam`); }); }); });