UNPKG

mqrpc

Version:

💫 Easy RPC over RabbitMQ

98 lines (97 loc) • 4.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ava_1 = require("ava"); const sinon = require("sinon"); const _config_1 = require("../../_config"); const AmqpClient_1 = require("../../../lib/AmqpClient"); const comms_1 = require("../../../lib/RpcServer/comms"); const errors_1 = require("../../../lib/RpcServer/errors"); const sampleMessage = { fields: { deliveryTag: 1234567890987654321 }, properties: { replyTo: 'amqp.rabbitmq.reply-to', correlationId: '123456' } }; const amqpClient = new AmqpClient_1.default({ amqpUrl: _config_1.AMQP_URL }); ava_1.default.before(() => amqpClient.init()); ava_1.default.after.always(() => amqpClient.term()); ava_1.default.beforeEach(t => t.context.sandbox = sinon.sandbox.create()); ava_1.default.afterEach.always(t => t.context.sandbox.restore()); ava_1.default.serial('[unit] #reply acks the given message', async (t) => { const spy = t.context.sandbox.spy(amqpClient.channel, 'ack'); await comms_1.reply(amqpClient.channel, sampleMessage); sinon.assert.calledWith(spy, sampleMessage); t.pass(); }); ava_1.default.serial('[unit] #reply publishes to the given replyTo with the given correlationId', async (t) => { const spy = t.context.sandbox.spy(amqpClient.channel, 'publish'); await comms_1.reply(amqpClient.channel, sampleMessage); sinon.assert.calledWith(spy, '', 'amqp.rabbitmq.reply-to', sinon.match.any, { correlationId: '123456', deliveryMode: undefined }); t.pass(); }); ava_1.default.serial('[unit] #reply serializes the response as JSON', async (t) => { t.plan(5); const spy = t.context.sandbox.spy(amqpClient.channel, 'publish'); await comms_1.reply(amqpClient.channel, sampleMessage, { meaning: 42 }); const contentMatcher = sinon.match((content) => { t.true(content instanceof Buffer); const json = JSON.parse(content.toString()); t.is(json.type, 'reply'); t.truthy(json.reply); t.deepEqual(json.reply, { meaning: 42 }); t.is(json.error, undefined); return true; }); sinon.assert.calledWith(spy, sinon.match.string, sinon.match.string, contentMatcher, sinon.match.any); }); ava_1.default.serial('[unit] #reply handles undefined responses', async (t) => { const spy = t.context.sandbox.spy(amqpClient.channel, 'publish'); await comms_1.reply(amqpClient.channel, sampleMessage); sinon.assert.calledWith(spy, sinon.match.string, sinon.match.string, sinon.match({}), sinon.match.any); t.pass(); }); ava_1.default.serial('[unit] #reply handles null responses', async (t) => { t.plan(1); const spy = t.context.sandbox.spy(amqpClient.channel, 'publish'); await comms_1.reply(amqpClient.channel, sampleMessage, null); const contentMatcher = sinon.match((content) => { t.is(JSON.parse(content.toString()).reply, null); return true; }); sinon.assert.calledWith(spy, sinon.match.string, sinon.match.string, contentMatcher, sinon.match.any); }); ava_1.default.serial('[unit] #reply sends error responses under an error key', async (t) => { t.plan(4); const spy = t.context.sandbox.spy(amqpClient.channel, 'publish'); await comms_1.reply(amqpClient.channel, sampleMessage, new errors_1.NoSuchProcedure('oops')); const contentMatcher = sinon.match((content) => { const json = JSON.parse(content.toString()); t.is(json.reply, undefined); t.is(json.type, 'error'); t.truthy(json.error); t.deepEqual(json.error, { name: 'NoSuchProcedure', message: 'No procedure named "oops" has been registered' }); return true; }); sinon.assert.calledWith(spy, sinon.match.string, sinon.match.string, contentMatcher, sinon.match.any); }); ava_1.default.serial('[unit] #reply serializes errors according to their own implementation', async (t) => { t.plan(4); const spy = t.context.sandbox.spy(amqpClient.channel, 'publish'); const error = new Error('oops'); await comms_1.reply(amqpClient.channel, sampleMessage, new errors_1.ProcedureFailed(error)); const contentMatcher = sinon.match((content) => { const json = JSON.parse(content.toString()); t.is(json.reply, undefined); t.is(json.type, 'error'); t.truthy(json.error); t.deepEqual(json.error, { name: 'ProcedureFailed', message: 'Operation failed with error: oops', cause: { name: 'Error', message: 'oops', stack: error.stack } }); return true; }); sinon.assert.calledWith(spy, sinon.match.string, sinon.match.string, contentMatcher, sinon.match.any); });