UNPKG

@kth/api-call

Version:

Node.js module to make JSON calls against APIs.

221 lines (201 loc) 8.23 kB
/* eslint-disable no-console */ const BasicAPI = require('./basic') const logConsole = false const mockLogger = { debug: logConsole ? console.log : () => {}, error: logConsole ? console.log : () => {}, warn: logConsole ? console.log : () => {}, info: logConsole ? console.log : () => {}, } // Mock for redis, to test caching const redisGet = jest.fn().mockImplementation((key, callback) => { if (key === 'mocktest:get:/api/test/cached') { return callback(undefined, '{ "body": "from cache", "statusCode": 200 }') } return callback(undefined, undefined) }) const redisSet = jest.fn().mockImplementation((key, value, callback) => { callback(undefined, 'OK') }) const opts = { hostname: '127.0.0.1', host: 'localhost:3210', https: false, json: true, defaultTimeout: 50, retryOnESOCKETTIMEDOUT: true, maxNumberOfRetries: 2, basePath: '/api/test', log: mockLogger, redis: { getClient: async () => ({ set: redisSet, get: redisGet, expire: (key, limit, callback) => { callback(undefined, 'OK') }, }), prefix: 'mocktest', expire: undefined, }, } const api = BasicAPI(opts) opts.retryOnESOCKETTIMEDOUT = false opts.host = 'localhost' opts.port = '666' const noRetryApi = BasicAPI(opts) describe('basic calls works as expected', () => { // Test callback based functions it('performs a successful get request when calling get', done => { api.get('/method', (error, response, body) => { expect(body.method).toBe('get') expect(response.statusCode).toBe(200) done() }) }) it('performs a successful post request when calling post', done => { api.post({ uri: '/method', body: { test: true } }, (error, response, body) => { expect(body).toStrictEqual({ postdata: { test: true }, method: 'post' }) expect(response.statusCode).toBe(200) done() }) }) it('performs a successful post request with formData when calling post', done => { api.post({ uri: '/method', formData: { test: 'formData' } }, (error, response, body) => { expect(body).toStrictEqual({ postdata: { test: 'formData' }, method: 'post' }) expect(response.statusCode).toBe(200) done() }) }) it('performs a successful put request when calling put', done => { api.put('/method', (error, response, body) => { expect(body.method).toBe('put') expect(response.statusCode).toBe(200) done() }) }) it('performs a successful delete request when calling del', done => { api.del('/method', (error, response, body) => { expect(body.method).toBe('del') expect(response.statusCode).toBe(200) done() }) }) it('performs a successful patch request when calling patch', done => { api.patch('/method', (error, response, body) => { expect(body.method).toBe('patch') expect(response.statusCode).toBe(200) done() }) }) it('performs a successful head request when calling head', done => { api.head('/method', (error, response, body) => { expect(body).toBeUndefined() expect(response.statusCode).toBe(200) done() }) }) it('performs a successful get request when calling get with option encoding utf8', done => { api.get({ uri: '/options', encoding: 'utf8' }, (error, response, body) => { expect(body).toBeInstanceOf(Object) expect(response.statusCode).toBe(200) done() }) }) it('performs a successful get request when calling get with option encoding null', done => { api.get({ uri: '/options', encoding: null }, (error, response, body) => { expect(body).toBeInstanceOf(Buffer) expect(response.statusCode).toBe(200) done() }) }) // Test promise based functions it('performs a successful get request when calling getAsync', async () => { const result = await api.getAsync({ uri: '/method', qs: { param: 'query string' } }) expect(result.body).toMatchObject({ method: 'get', query: { param: 'query string' } }) expect(result.statusCode).toBe(200) }) it('performs a successful post request when calling postAsync', async () => { const result = await api.postAsync({ uri: '/method', body: { test: true } }) expect(result.body).toStrictEqual({ postdata: { test: true }, method: 'post' }) expect(result.statusCode).toBe(200) }) it('performs a successful post request with formData when calling postAsync', async () => { const result = await api.postAsync({ uri: '/method', formData: { test: 'formData' } }) expect(result.body).toStrictEqual({ postdata: { test: 'formData' }, method: 'post' }) expect(result.statusCode).toBe(200) }) it('performs a successful put request when calling putAsync', async () => { const result = await api.putAsync('/method') expect(result.body.method).toBe('put') expect(result.statusCode).toBe(200) }) it('performs a successful delete request when calling delAsync', async () => { const result = await api.delAsync('/method') expect(result.body.method).toBe('del') expect(result.statusCode).toBe(200) }) it('performs a successful patch request when calling patchAsync', async () => { const result = await api.patchAsync('/method') expect(result.body.method).toBe('patch') expect(result.statusCode).toBe(200) }) it('performs a successful head request when calling headAsync', async () => { const result = await api.headAsync('/method') expect(result.body).toBeUndefined() expect(result.statusCode).toBe(200) }) // Test promise based functions with options it('performs a successful get request when calling getAsync with option encoding utf8', async () => { const result = await api.getAsync({ uri: '/options', encoding: 'utf8' }) expect(result.body).toBeInstanceOf(Object) expect(result.statusCode).toBe(200) }) // Test promise based functions with options it('performs a successful get request when calling getAsync with option encoding null', async () => { const result = await api.getAsync({ uri: '/options', encoding: null }) expect(result.body).toBeInstanceOf(Buffer) expect(result.statusCode).toBe(200) }) // Test Redis caching it('should pick value from cache if enabled and key exists when calling getAsync', async () => { const result = await api.getAsync({ uri: '/cached', useCache: true }) expect(result.body).toBe('from cache') expect(result.statusCode).toBe(200) expect(redisGet).toHaveBeenCalledWith('mocktest:get:/api/test/cached', expect.anything()) }) it('should cache value if cache is enabled when calling getAsync', async () => { const result = await api.getAsync({ uri: '/method', useCache: true, qs: { param: 'test' } }) expect(result.body.method).toBe('get') expect(result.statusCode).toBe(200) expect(redisGet).toHaveBeenCalledWith('mocktest:get:/api/test/method?param=test', expect.anything()) expect(redisSet).toHaveBeenCalledWith( 'mocktest:get:/api/test/method?param=test', '{"size":0,"timeout":50,"statusCode":200,"body":{"method":"get","query":{"param":"test"}}}', expect.anything() ) }) // Test retries on timeout it('should retry on timeout', async () => { api._request.post = jest.fn().mockImplementation(async (options, callback) => { callback(new Error('ESOCKETTIMEDOUT')) }) await api.postAsync('/timeout').catch(e => { expect(e.message).toContain('timed out after 2 retries. The connection to the API seems to be overloaded.') expect(api._request.post).toHaveBeenCalledTimes(3) }) }) it('should not retry on timeout', async () => { noRetryApi._request.post = jest.fn().mockImplementation(async (options, callback) => { callback(new Error('ESOCKETTIMEDOUT')) }) await noRetryApi.postAsync('/timeout').catch(e => { expect(e.message).toContain('ESOCKETTIMEDOUT') expect(noRetryApi._request.post).toHaveBeenCalledTimes(1) }) }) it('should return a resolved path then calling resolve', () => { const result = api.resolve('/api/test/:name/:task/', { name: 'Ingemar Andersson', task: 'pruttrace' }) expect(result).toBe('/api/test/Ingemar%20Andersson/pruttrace/') }) })