diff --git a/api/src/errors.js b/api/src/errors.js new file mode 100644 index 00000000000..70a3de8f368 --- /dev/null +++ b/api/src/errors.js @@ -0,0 +1,19 @@ +class PublicError extends Error { + constructor(publicMessage, ...args) { + super(publicMessage, ...args); + this.publicMessage = publicMessage; + } +} + +class NotFoundError extends Error { + constructor(message, ...args) { + super(message, ...args); + this.status = 404; // simulate PouchDb error + this.statusCode = 404; // simulate Request error + } +} + +module.exports = { + PublicError, + NotFoundError, +}; diff --git a/api/src/public-error.js b/api/src/public-error.js deleted file mode 100644 index 3d207200c7b..00000000000 --- a/api/src/public-error.js +++ /dev/null @@ -1,8 +0,0 @@ -class PublicError extends Error { - constructor(publicMessage, ...args) { - super(publicMessage, ...args); - this.publicMessage = publicMessage; - } -} - -module.exports = PublicError; diff --git a/api/src/services/privacy-policy.js b/api/src/services/privacy-policy.js index ec1d6dd5e3c..4555195757d 100644 --- a/api/src/services/privacy-policy.js +++ b/api/src/services/privacy-policy.js @@ -2,6 +2,7 @@ const sanitizeHtml = require('sanitize-html'); const db = require('../db'); const logger = require('@medic/logger'); const config = require('../config'); +const { NotFoundError } = require('../errors'); const PRIVACY_POLICY_DOC_ID = 'privacy-policies'; @@ -22,7 +23,7 @@ const getDoc = (options=({})) => { .then(doc => { const policies = doc.privacy_policies; if (!policies || !Object.keys(policies).length) { // invalid doc - throw new Error(`Invalid ${PRIVACY_POLICY_DOC_ID} doc: missing required "privacy_policies" property`); + throw new NotFoundError(`Invalid ${PRIVACY_POLICY_DOC_ID} doc: missing required "privacy_policies" property`); } return doc; }) diff --git a/api/src/services/records.js b/api/src/services/records.js index b6edb7d15a7..625994975a6 100644 --- a/api/src/services/records.js +++ b/api/src/services/records.js @@ -3,7 +3,7 @@ const phoneNumber = require('@medic/phone-number'); const config = require('../config'); const smsparser = require('./report/smsparser'); const validate = require('./report/validate'); -const PublicError = require('../public-error'); +const { PublicError } = require('../errors'); const DATE_NUMBER_STRING = /(\d{13,})/; // matches invisible characters that can mess up our parsing diff --git a/api/tests/mocha/services/privacy-policy.spec.js b/api/tests/mocha/services/privacy-policy.spec.js index 6bc4315ff4e..6aecab9956d 100644 --- a/api/tests/mocha/services/privacy-policy.spec.js +++ b/api/tests/mocha/services/privacy-policy.spec.js @@ -3,6 +3,7 @@ const sinon = require('sinon'); const service = require('../../../src/services/privacy-policy'); const db = require('../../../src/db'); const config = require('../../../src/config'); +const logger = require('@medic/logger'); describe('Privacy Policy service', () => { @@ -123,6 +124,27 @@ describe('Privacy Policy service', () => { }); }); + it('should throw error when doc does not exist', async () => { + sinon.spy(logger, 'error'); + sinon.stub(db.medic, 'get').rejects({ status: 404 }); + await chai.expect(service.get('sw')).to.be.rejected.and.eventually.deep.equal({ status: 404 }); + chai.expect(logger.error.called).to.equal(false); + }); + + it('should throw error when doc has no policies', async () => { + sinon.stub(db.medic, 'get').resolves({ privacy_policies: {} }); + sinon.spy(logger, 'error'); + await chai.expect(service.get('sw')).to.be.rejected.and.eventually.deep.include({ status: 404 }); + chai.expect(logger.error.called).to.equal(false); + }); + + it('should throw error on misconfigured doc', async () => { + sinon.stub(db.medic, 'get').resolves({ }); + sinon.spy(logger, 'error'); + await chai.expect(service.get('sw')).to.be.rejected.and.eventually.deep.include({ status: 404 }); + chai.expect(logger.error.called).to.equal(false); + }); + }); });