Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .github/cht-11192-e2e-verification.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 15 additions & 11 deletions admin/src/js/services/message-queue.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const lineageFactory = require('@medic/lineage');
const messageUtils = require('@medic/message-utils');
const registrationUtils = require('@medic/registration-utils');
const extensionLibs = require('@medic/extension-libs');
const constants = require('@medic/constants');
const DOC_TYPES = constants.DOC_TYPES;

Expand All @@ -15,6 +16,7 @@ angular.module('services').factory('MessageQueueUtils',

return {
lineage: lineageFactory($q, DB({ remote: true })),
loadExtensionLibs: () => extensionLibs.load(DB({ remote: true })),
messages: messageUtils,
registrations: registrationUtils
};
Expand Down Expand Up @@ -47,7 +49,7 @@ angular.module('services').factory('MessageQueue',

const findIdByKey = (contactsByReference, key) => {
const row = contactsByReference.rows.find((row) => row.key[1] === key);
return row && row.id;
return row && row.id; // NOSONAR: browserify-ngannotate does not support optional chaining.
};

const findPatientUuid = (contactsByReference, message) => {
Expand Down Expand Up @@ -184,7 +186,7 @@ angular.module('services').factory('MessageQueue',
});
};

const generateScheduledMessages = function(messages, settings) {
const generateScheduledMessages = function(messages, settings, extensionLibs) {
const translate = function(key, locale) {
return $translate.instant(key, null, 'no-interpolation', locale, null);
};
Expand All @@ -199,14 +201,15 @@ angular.module('services').factory('MessageQueue',
message: message.scheduled_sms.content
};

message.sms = MessageQueueUtils.messages.generate(
settings,
message.sms = MessageQueueUtils.messages.generate({
config: settings,
translate,
message.doc,
doc: message.doc,
content,
message.scheduled_sms.recipient,
message.context
)[0];
recipient: message.scheduled_sms.recipient,
extraContext: message.context,
extensionLibs,
})[0];
});

return messages;
Expand Down Expand Up @@ -314,9 +317,10 @@ angular.module('services').factory('MessageQueue',
.all([
Settings(),
DB({ remote: true }).query('medic-admin/message_queue', params.list),
DB({ remote: true }).query('medic-admin/message_queue', params.count)
DB({ remote: true }).query('medic-admin/message_queue', params.count),
MessageQueueUtils.loadExtensionLibs(),
])
.then(([settings, messagesList, messagesCount]) => {
.then(([settings, messagesList, messagesCount, extensionLibs]) => {
const messages = messagesList.rows.map((row) => {
const extras = {
doc: row.doc,
Expand All @@ -331,7 +335,7 @@ angular.module('services').factory('MessageQueue',

return getSubjectsAndRegistrations(messages, settings)
.then(hydrateContacts)
.then((messages) => generateScheduledMessages(messages, settings))
.then((messages) => generateScheduledMessages(messages, settings, extensionLibs))
.then(getRecipients)
.then((messages) => {
return {
Expand Down
36 changes: 26 additions & 10 deletions admin/tests/unit/services/message-queue.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('MessageQueue service', function() {
translate.preferredLanguage = sinon.stub();
clock = sinon.useFakeTimers();
utils = {
loadExtensionLibs: sinon.stub().resolves({}),
messages: {
generate: sinon.stub()
},
Expand Down Expand Up @@ -92,13 +93,24 @@ describe('MessageQueue service', function() {

return service.query('tab', 10, 5, false).then(result => {
chai.expect(result).to.deep.equal({ messages: [], total: 0 });
chai.expect(utils.loadExtensionLibs.calledOnceWithExactly()).to.equal(true);
chai.expect(query.callCount).to.equal(2);
chai.expect(query.args[0])
.to.deep.equal(['medic-admin/message_queue', { limit: 5, skip: 10, reduce: false, include_docs: true }]);
chai.expect(query.args[1]).to.deep.equal(['medic-admin/message_queue', { reduce: true, group_level: 1 }]);
});
});

it('rejects when extension-libs cannot be loaded', () => {
const error = new Error('extension-libs unavailable');
utils.loadExtensionLibs.rejects(error);
query.resolves({ rows: [] });

return service.query('tab')
.then(() => chai.expect.fail('Expected query to reject'))
.catch(err => chai.expect(err).to.equal(error));
});

it('should query the message_queue view with correct default params', () => {
query
.withArgs('medic-admin/message_queue', sinon.match({ reduce: false })).resolves({ rows: [] })
Expand Down Expand Up @@ -298,7 +310,7 @@ describe('MessageQueue service', function() {

translate.instant.withArgs('task1').returns('task 1 translation');

utils.messages.generate.callsFake((settings, translate, doc, content, recipient) => ([{
utils.messages.generate.callsFake(({ doc, content, recipient }) => ([{
message: content.translationKey || content.message,
to: recipient,
error: doc.error
Expand Down Expand Up @@ -579,7 +591,7 @@ describe('MessageQueue service', function() {
]);
utils.lineage.fillParentsInDocs.callsFake(doc => doc);

utils.messages.generate.callsFake((settings, translate, doc, content, recipient) => ([{
utils.messages.generate.callsFake(({ content, recipient }) => ([{
message: content.translation_key,
to: recipient
}]));
Expand Down Expand Up @@ -740,7 +752,7 @@ describe('MessageQueue service', function() {
]);
utils.lineage.fillParentsInDocs.callsFake(doc => doc);

utils.messages.generate.callsFake((settings, translate, doc, content, recipient) => ([{
utils.messages.generate.callsFake(({ content, recipient }) => ([{
message: content.translationKey || content.message,
to: recipient
}]));
Expand All @@ -765,8 +777,12 @@ describe('MessageQueue service', function() {
return service.query('tab').then((result) => {
chai.expect(utils.registrations.isValidRegistration.callCount).to.equal(13);
chai.expect(utils.messages.generate.callCount).to.equal(6);
const getGenerateArgs = index => {
const options = utils.messages.generate.args[index][0];
return [ options.doc, options.content, options.recipient, options.extraContext ];
};

chai.expect(utils.messages.generate.args[0].slice(2)).to.deep.equal([
chai.expect(getGenerateArgs(0)).to.deep.equal([
{
_id: 'report_id1',
reported_date: 100,
Expand Down Expand Up @@ -794,7 +810,7 @@ describe('MessageQueue service', function() {
}
]);

chai.expect(utils.messages.generate.args[1].slice(2)).to.deep.equal([
chai.expect(getGenerateArgs(1)).to.deep.equal([
{
_id: 'report_id2',
reported_date: 200,
Expand All @@ -818,7 +834,7 @@ describe('MessageQueue service', function() {
}
]);

chai.expect(utils.messages.generate.args[2].slice(2)).to.deep.equal([
chai.expect(getGenerateArgs(2)).to.deep.equal([
{
_id: 'report_id3',
reported_date: 200,
Expand All @@ -842,7 +858,7 @@ describe('MessageQueue service', function() {
}
]);

chai.expect(utils.messages.generate.args[3].slice(2)).to.deep.equal([
chai.expect(getGenerateArgs(3)).to.deep.equal([
{
_id: 'report_id4',
reported_date: 200,
Expand All @@ -868,7 +884,7 @@ describe('MessageQueue service', function() {
}
]);

chai.expect(utils.messages.generate.args[4].slice(2)).to.deep.equal([
chai.expect(getGenerateArgs(4)).to.deep.equal([
{
_id: 'report_id5',
reported_date: 200,
Expand Down Expand Up @@ -897,7 +913,7 @@ describe('MessageQueue service', function() {
}
]);

chai.expect(utils.messages.generate.args[5].slice(2)).to.deep.equal([
chai.expect(getGenerateArgs(5)).to.deep.equal([
{
_id: 'report_id6',
reported_date: 200,
Expand Down Expand Up @@ -1059,7 +1075,7 @@ describe('MessageQueue service', function() {
]);
utils.lineage.fillParentsInDocs.callsFake(doc => doc);

utils.messages.generate.callsFake((settings, translate, doc, content, recipient) => ([{
utils.messages.generate.callsFake(({ doc, content, recipient }) => ([{
message: content.translationKey || content.message,
to: recipient,
error: doc.error
Expand Down
3 changes: 3 additions & 0 deletions api/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const _ = require('lodash');
let translationCache = {};
let settings = {};
let transitionsLib;
let extensionLibs = {};

_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

Expand Down Expand Up @@ -52,9 +53,11 @@ module.exports = {
set: (newSettings) => settings = newSettings,
setTranslationCache: (newTranslations) => translationCache = newTranslations,
setTransitionsLib: (newTransitionsLib) => transitionsLib = newTransitionsLib,
setExtensionLibs: (newExtensionLibs) => extensionLibs = newExtensionLibs,

get: key => (key ? settings[key] : settings),
getAll: () => settings,
getExtensionLibs: () => extensionLibs,
getTranslations: keys => {
if (!keys) {
return translationCache;
Expand Down
19 changes: 19 additions & 0 deletions api/src/services/config-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const config = require('../config');
const environment = require('@medic/environment');
const dataContext = require('./data-context');
const deployInfo = require('./deploy-info');
const extensionLibs = require('@medic/extension-libs');

const MEDIC_DDOC_ID = '_design/medic';

Expand Down Expand Up @@ -76,6 +77,13 @@ const loadSettings = () => {
.then(settings => config.set(settings));
};

const loadExtensionLibs = () => extensionLibs
.load(db.medic)
.then(config.setExtensionLibs)
.catch(err => {
logger.error('Error loading extension libs - starting up anyway: %o', err);
});


const handleDdocChange = () => {
logger.info('Detected ddoc change - reloading');
Expand Down Expand Up @@ -110,6 +118,11 @@ const handleTranslationsChange = () => {
.then(() => updateServiceWorker());
};

const handleExtensionLibsChange = () => {
logger.info('Detected extension-libs change - reloading');
return loadExtensionLibs();
};

const handleFormChange = (change) => {
logger.info('Detected form change for %s', change.id);
if (change.deleted) {
Expand Down Expand Up @@ -142,6 +155,7 @@ const updateServiceWorker = () => {
const load = () => {
loadViewMaps();
return loadTranslations()
.then(() => loadExtensionLibs())
.then(() => loadSettings())
.then(() => addUserRolesToDb())
.then(() => initTransitionLib())
Expand All @@ -168,6 +182,10 @@ const listen = () => {
return handleTranslationsChange();
}

if (change.id === DOC_IDS.EXTENSION_LIBS) {
return handleExtensionLibsChange();
}

if (change.id.startsWith('form:')) {
return handleFormChange(change);
}
Expand Down Expand Up @@ -198,6 +216,7 @@ module.exports = {
listen,
updateServiceWorker,
loadTranslations,
loadExtensionLibs,
watch,
addUserRolesToDb,
};
15 changes: 8 additions & 7 deletions api/src/services/export/message-mapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,15 @@ module.exports = {
translationKey: task.message_key,
message: task.message
};
task.messages = messageUtils.generate(
config.get(),
config.translate,
record,
task.messages = messageUtils.generate({
config: config.get(),
translate: config.translate,
doc: record,
content,
task.recipient,
context
);
recipient: task.recipient,
extraContext: context,
extensionLibs: config.getExtensionLibs(),
});
}

const taskType = (task.translation_key && config.translate(task.translation_key, { group: task.group })) ||
Expand Down
18 changes: 18 additions & 0 deletions api/tests/mocha/services/config-watcher.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const bootstrap = require('../../../src/services/config-watcher');
const manifest = require('../../../src/services/manifest');
const environment = require('@medic/environment');
const deployInfo = require('../../../src/services/deploy-info');
const extensionLibs = require('@medic/extension-libs');

describe('Configuration', () => {
beforeEach(() => {
Expand All @@ -29,10 +30,12 @@ describe('Configuration', () => {
sinon.spy(config, 'set');
sinon.spy(config, 'setTranslationCache');
sinon.spy(config, 'setTransitionsLib');
sinon.spy(config, 'setExtensionLibs');
sinon.stub(fs, 'watch');
sinon.stub(translations, 'getTranslationDocs');
sinon.stub(dbWatcher, 'listen');
sinon.stub(deployInfo, 'store');
sinon.stub(extensionLibs, 'load').resolves({});
});

afterEach(() => {
Expand All @@ -58,6 +61,7 @@ describe('Configuration', () => {
['docs_by_replication_key'],
]);
chai.expect(translations.getTranslationDocs.callCount).to.equal(1);
chai.expect(extensionLibs.load.calledOnceWithExactly(db.medic)).to.equal(true);

chai.expect(settingsService.update.callCount).to.equal(1);
chai.expect(settingsService.get.callCount).to.equal(1);
Expand Down Expand Up @@ -190,6 +194,20 @@ describe('Configuration', () => {
});
});

describe('extension-libs changes', () => {
it('reloads extension-libs', () => {
return dbWatcher.medic.args[0][0]({ id: DOC_IDS.EXTENSION_LIBS }).then(() => {
chai.expect(extensionLibs.load.calledOnceWithExactly(db.medic)).to.equal(true);
});
});

it('continues when extension-libs cannot be loaded', () => {
extensionLibs.load.rejects(new Error('failed to load'));

return dbWatcher.medic.args[0][0]({ id: DOC_IDS.EXTENSION_LIBS });
});
});

describe('branding changes', () => {
it('generates service worker when branding doc is updated', () => {
manifest.generate.resolves();
Expand Down
20 changes: 11 additions & 9 deletions api/tests/mocha/services/export/message-mapper.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('Message mapper', () => {
sinon.stub(messageUtils, 'generate');
sinon.stub(registrationUtils, 'isValidRegistration');
sinon.stub(config, 'get');
sinon.stub(config, 'getExtensionLibs').returns({});
sinon.stub(config, 'translate');
});

Expand Down Expand Up @@ -424,20 +425,21 @@ describe('Message mapper', () => {
chai.expect(config.translate.args[0]).to.deep.equal(['task-translation-key', { group: 'gr' }]);

chai.expect(messageUtils.generate.callCount).to.deep.equal(1);
chai.expect(messageUtils.generate.args[0]).to.deep.equal([
{ config: 1 },
config.translate,
record,
{
chai.expect(messageUtils.generate.args[0]).to.deep.equal([{
config: { config: 1 },
translate: config.translate,
doc: record,
content: {
translationKey: 'alpha',
message: undefined
},
'random recipient',
{
recipient: 'random recipient',
extraContext: {
patient: record.patient,
registrations: record.registrations
}
]);
},
extensionLibs: {},
}]);

chai.expect(result.length).to.equal(2);
chai.expect(result[0]).to.deep.equal([
Expand Down
Loading