diff --git a/src/lib/api.js b/src/lib/api.js index 4260d88d2..3807d5d5c 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -11,12 +11,8 @@ const cache = new Map(); const _request = (method) => (...args) => retry(() => rpn[method](...args), { retries: 0 }); const request = { get: _request('get'), - head: _request('head'), - options: _request('options'), post: _request('post'), put: _request('put'), - patch: _request('patch'), - delete: _request('delete'), }; const logDeprecatedTransitions = (settings) => { diff --git a/test/lib/api.spec.js b/test/lib/api.spec.js index 0e9026199..02b13e762 100644 --- a/test/lib/api.spec.js +++ b/test/lib/api.spec.js @@ -9,7 +9,11 @@ const log = require('../../src/lib/log'); describe('api', () => { let mockRequest; beforeEach(() => { - mockRequest = sinon.stub().resolves(); + mockRequest = { + get: sinon.stub().resolves(), + post: sinon.stub().resolves(), + put: sinon.stub().resolves(), + }; api.__set__('request', mockRequest); sinon.stub(environment, 'apiUrl').get(() => 'http://example.com/db-name'); }); @@ -21,15 +25,14 @@ describe('api', () => { it('defaults to live requests', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); await api().version(); - expect(mockRequest.callCount).to.eq(1); + expect(mockRequest.get.callCount).to.eq(1); }); describe('formsValidate', async () => { it('should fail if validate endpoint returns invalid JSON', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); - mockRequest = sinon.stub().resolves('--NOT JSON--'); - api.__set__('request', mockRequest); + mockRequest.post.resolves('--NOT JSON--'); try { await api().formsValidate(''); assert.fail('Expected assertion'); @@ -41,28 +44,25 @@ describe('api', () => { it('should not fail if validate endpoint does not exist', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); - mockRequest = sinon.stub().rejects({name: 'StatusCodeError', statusCode: 404}); - api.__set__('request', mockRequest); + mockRequest.post.rejects({name: 'StatusCodeError', statusCode: 404}); let result = await api().formsValidate(''); expect(result).to.deep.eq({ok: true, formsValidateEndpointFound: false}); - expect(mockRequest.callCount).to.eq(1); + expect(mockRequest.post.callCount).to.eq(1); // second call result = await api().formsValidate('Another XML'); expect(result).to.deep.eq({ok: true, formsValidateEndpointFound: false}); - expect(mockRequest.callCount).to.eq(1); // still HTTP client called only once + expect(mockRequest.post.callCount).to.eq(1); // still HTTP client called only once }); it('should not call API when --archive mode and response still ok', async () => { - mockRequest = sinon.spy(); - api.__set__('request', mockRequest); api.__set__('environment', sinon.stub({ isArchiveMode: true })); let result = await api().formsValidate(''); expect(result).to.deep.eq({ok: true}); - expect(mockRequest.callCount).to.eq(0); + expect(mockRequest.post.callCount).to.eq(0); // second call result = await api().formsValidate('Another XML'); expect(result).to.deep.eq({ok: true}); - expect(mockRequest.callCount).to.eq(0); // still HTTP not called even once + expect(mockRequest.post.callCount).to.eq(0); // still HTTP not called even once }); }); @@ -71,7 +71,7 @@ describe('api', () => { it('does not initiate requests to api', async () => { await api().version(); - expect(mockRequest.callCount).to.eq(0); + expect(mockRequest.get.callCount).to.eq(0); }); it('throws not supported for undefined interfaces', () => { @@ -83,38 +83,42 @@ describe('api', () => { it('changes settings on server', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); - mockRequest.onCall(0).resolves([]); - mockRequest.onCall(1).resolves({ ok: true }); + // GET /api/v1/settings/deprecated-transitions from logDeprecatedTransitions() + mockRequest.get.onCall(0).resolves([]); + // PUT /_design/medic/_rewrite/update_settings/medic?replace=1 from updateAppSettings() + mockRequest.put.onCall(0).resolves({ ok: true }); const response = await api().updateAppSettings(JSON.stringify({ transitions: [ 'test' ] })); expect(response.ok).to.equal(true); - expect(mockRequest.callCount).to.equal(2); - expect(mockRequest.args[1][0].body).to.equal('{"transitions":["test"]}'); + expect(mockRequest.get.callCount).to.equal(1); + expect(mockRequest.put.callCount).to.equal(1); + expect(mockRequest.put.args[0][0].body).to.equal('{"transitions":["test"]}'); }); it('throws error when server throws', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); - mockRequest.onCall(0).resolves([]); - mockRequest.onCall(1).rejects({ error: 'random' }); + mockRequest.get.onCall(0).resolves([]); + mockRequest.put.onCall(0).resolves({ ok: true }); try { await api().updateAppSettings(JSON.stringify({})); } catch(err) { expect(err.error).to.equal('random'); - expect(mockRequest.callCount).to.equal(1); + expect(mockRequest.get.callCount).to.equal(0); + expect(mockRequest.put.callCount).to.equal(1); } }); it('logs and continues when using deprecated transitions', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); sinon.stub(log, 'warn'); - mockRequest.onCall(0).resolves([ { + mockRequest.get.onCall(0).resolves([ { name: 'go', deprecated: true, deprecatedIn: '3.10.0', deprecationMessage: 'Use go2 instead' } ]); - mockRequest.onCall(1).resolves({ ok: true }); + mockRequest.put.onCall(0).resolves({ ok: true }); await api().updateAppSettings(JSON.stringify({ transitions: { go: { disable: false } } })); @@ -125,8 +129,8 @@ describe('api', () => { it('continues when deprecated transitions call throws', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); sinon.stub(log, 'warn'); - mockRequest.onCall(0).rejects({ statusCode: 500, message: 'some error' }); - mockRequest.onCall(1).resolves({ ok: true }); + mockRequest.get.onCall(0).rejects({ statusCode: 500, message: 'some error' }); + mockRequest.put.onCall(0).resolves({ ok: true }); await api().updateAppSettings(JSON.stringify({ transitions: [ 'test' ] })); @@ -139,45 +143,45 @@ describe('api', () => { it('call the API and parse types from string correctly', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); sinon.stub(environment, 'force').get(() => false); - mockRequest.resolves({'compressible_types':'text/*, application/*', 'compression_level':'8'}); + mockRequest.get.resolves({'compressible_types':'text/*, application/*', 'compression_level':'8'}); const cacheSpy = new Map(); const cacheGetSpy = sinon.spy(cacheSpy, 'get'); api.__set__('cache', cacheSpy); let compressibleTypes = await api().getCompressibleTypes(); expect(compressibleTypes).to.deep.eq(['text/*', 'application/*']); - assert.equal(mockRequest.callCount, 1); + assert.equal(mockRequest.get.callCount, 1); assert.equal(cacheGetSpy.callCount, 0); // second time the cache is used compressibleTypes = await api().getCompressibleTypes(); expect(compressibleTypes).to.deep.eq(['text/*', 'application/*']); // same values from cache - assert.equal(mockRequest.callCount, 1); // still 1 request + assert.equal(mockRequest.get.callCount, 1); // still 1 request assert.equal(cacheGetSpy.callCount, 1); }); it('returns empty if API returns 404', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); sinon.stub(environment, 'force').get(() => false); - mockRequest.rejects({statusCode:404}); + mockRequest.get.rejects({statusCode:404}); const cacheSpy = new Map(); const cacheGetSpy = sinon.spy(cacheSpy, 'get'); api.__set__('cache', cacheSpy); let compressibleTypes = await api().getCompressibleTypes(); expect(compressibleTypes).to.deep.eq([]); - assert.equal(mockRequest.callCount, 1); + assert.equal(mockRequest.get.callCount, 1); assert.equal(cacheGetSpy.callCount, 0); // second time the cache is used compressibleTypes = await api().getCompressibleTypes(); expect(compressibleTypes).to.deep.eq([]); // same values from cache - assert.equal(mockRequest.callCount, 1); // still 1 request + assert.equal(mockRequest.get.callCount, 1); // still 1 request assert.equal(cacheGetSpy.callCount, 1); }); it('returns empty if API returns error and without caching result', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); sinon.stub(environment, 'force').get(() => false); - const getReqStub = mockRequest; + const getReqStub = mockRequest.get; getReqStub.onCall(0).rejects('The error'); getReqStub.onCall(1).resolves({'compressible_types':'text/*, application/*', 'compression_level':'8'}); const cacheSpy = new Map(); @@ -185,13 +189,13 @@ describe('api', () => { api.__set__('cache', cacheSpy); let compressibleTypes = await api().getCompressibleTypes(); expect(compressibleTypes).to.deep.eq([]); - assert.equal(mockRequest.callCount, 1); + assert.equal(mockRequest.get.callCount, 1); assert.equal(cacheGetSpy.callCount, 0); // second time cache is NOT used and value from API is returned compressibleTypes = await api().getCompressibleTypes(); expect(compressibleTypes).to.deep.eq(['text/*', 'application/*']); // values from API second call - assert.equal(mockRequest.callCount, 2); // 2 requests total + assert.equal(mockRequest.get.callCount, 2); // 2 requests total assert.equal(cacheGetSpy.callCount, 0); // cache not used }); }); @@ -202,7 +206,7 @@ describe('api', () => { async function testAvailableError(response, expected) { sinon.stub(environment, 'isArchiveMode').get(() => false); - mockRequest.rejects(response); + mockRequest.get.rejects(response); try { await api().available(); assert.fail('Expected error to be thrown'); @@ -213,7 +217,7 @@ describe('api', () => { it('should not throw if no error found in request', async () => { sinon.stub(environment, 'isArchiveMode').get(() => false); - sinon.stub(mockRequest).resolves('okey dokey'); + mockRequest.get.resolves('okey dokey'); await api().available(); }); @@ -251,9 +255,9 @@ describe('api', () => { it('should return if archive mode is enabled even when api is not available', async () => { sinon.stub(environment, 'isArchiveMode').get(() => true); - sinon.stub(mockRequest).rejects('Ups'); + mockRequest.get.rejects('Ups'); await api().available(); - expect(mockRequest.callCount).to.eq(0); // api is not called + expect(mockRequest.get.callCount).to.eq(0); // api is not called }); }); });