UNPKG

@tawk.to/nestjs-google-pubsub-microservice

Version:
308 lines 12.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const sinon = require("sinon"); const gc_pubsub_server_1 = require("./gc-pubsub.server"); const constants_1 = require("@nestjs/microservices/constants"); const base_rpc_context_1 = require("@nestjs/microservices/ctx-host/base-rpc.context"); const gc_pubsub_constants_1 = require("./gc-pubsub.constants"); describe('GCPubSubServer', () => { let server; let pubsub; let topicMock; let subscriptionMock; let createClient; let sandbox; const objectToMap = (obj) => new Map(Object.keys(obj).map((key) => [key, obj[key]])); afterEach(() => { sandbox.restore(); }); describe('listen', () => { describe('when is check existence is true', () => { beforeEach(async () => { server = getInstance({}); await server.listen(() => { }); }); it('should call "createClient"', () => { (0, chai_1.expect)(createClient.called).to.be.true; }); it('should call "client.topic" once', async () => { (0, chai_1.expect)(pubsub.topic.called).to.be.true; }); it('should call "topic.create" once', async () => { (0, chai_1.expect)(topicMock.create.called).to.be.true; }); it('should call "topic.subscription" once', async () => { (0, chai_1.expect)(topicMock.subscription.called).to.be.true; }); it('should call "subscription.create" once', async () => { (0, chai_1.expect)(subscriptionMock.create.called).to.be.true; }); it('should call "subscription.on" twice', async () => { (0, chai_1.expect)(subscriptionMock.on.callCount).to.eq(2); }); }); describe('when createSubscriptionOptions is provided', () => { const mockCreateSubscriptionOptions = { messageRetentionDuration: { seconds: 604800, }, pushEndpoint: 'https://example.com/push', oidcToken: { serviceAccountEmail: 'example@example.com', audience: 'https://example.com', }, topic: 'projects/my-project/topics/my-topic', pushConfig: { pushEndpoint: 'https://example.com/push', }, ackDeadlineSeconds: 60, retainAckedMessages: true, labels: { env: 'dev', version: '1.0.0', }, enableMessageOrdering: false, expirationPolicy: { ttl: { seconds: 86400, }, }, filter: 'attribute.type = "order"', deadLetterPolicy: { deadLetterTopic: 'projects/my-project/topics/my-dead-letter-topic', maxDeliveryAttempts: 5, }, retryPolicy: { minimumBackoff: { seconds: 10, }, maximumBackoff: { seconds: 300, }, }, detached: false, enableExactlyOnceDelivery: true, topicMessageRetentionDuration: { seconds: 2592000, }, state: 'ACTIVE', }; beforeEach(async () => { server = getInstance({ createSubscriptionOptions: mockCreateSubscriptionOptions, }); await server.listen(() => { }); }); it('should call "subscription.create" with argument', async () => { (0, chai_1.expect)(subscriptionMock.create.calledOnce).to.be.true; (0, chai_1.expect)(subscriptionMock.create.calledWith(mockCreateSubscriptionOptions)).to.be.true; }); }); describe('when is check existence is false', () => { beforeEach(async () => { server = getInstance({ init: false, checkExistence: false, }); await server.listen(() => { }); }); it('should call "createClient"', () => { (0, chai_1.expect)(createClient.called).to.be.true; }); it('should call "client.topic" once', async () => { (0, chai_1.expect)(pubsub.topic.called).to.be.true; }); it('should not call "topic.exists" once', async () => { (0, chai_1.expect)(topicMock.exists.called).to.be.false; }); it('should call "topic.subscription" once', async () => { (0, chai_1.expect)(topicMock.subscription.called).to.be.true; }); it('should not call "subscription.exists" once', async () => { (0, chai_1.expect)(subscriptionMock.exists.called).to.be.false; }); it('should call "subscription.on" twice', async () => { (0, chai_1.expect)(subscriptionMock.on.callCount).to.eq(2); }); }); }); describe('close', () => { beforeEach(async () => { server = getInstance({}); await server.listen(() => { }); await server.close(); }); it('should call "subscription.close"', function () { (0, chai_1.expect)(subscriptionMock.close.called).to.be.true; }); it('should close() pubsub', () => { (0, chai_1.expect)(pubsub.close.called).to.be.true; }); }); describe('handleMessage', () => { const msg = { data: 'tests', }; const messageOptions = { ackId: 'id', publishTime: new Date(), attributes: { _replyTo: 'replyTo', _id: '3', _pattern: 'test', _clientId: '4', }, id: 'id', received: 0, deliveryAttempt: 1, ack: () => { }, modAck: () => { }, nack: () => { }, data: Buffer.from(JSON.stringify(msg)), }; beforeEach(async () => { server = getInstance({}); await server.listen(() => { }); }); it('should send NO_MESSAGE_HANDLER error if key does not exists in handlers object', async () => { await server.handleMessage(messageOptions); (0, chai_1.expect)(topicMock.publishMessage.calledWith({ data: Buffer.from(JSON.stringify({ id: messageOptions.attributes._id, status: 'error', err: constants_1.NO_MESSAGE_HANDLER, })), attributes: Object.assign({ id: messageOptions.attributes._id }, messageOptions.attributes), })).to.be.true; }); it('should send TIMEOUT_ERROR_HANDLER if the message is timed out', async () => { server = getInstance({ noAck: false }); await server.listen(() => { }); const timeoutMessageOptions = { ackId: 'id', publishTime: new Date(Date.now() - 5000), attributes: { _replyTo: 'replyTo', _id: '3', _pattern: 'test', _clientId: '4', _timeout: '4000', }, id: 'id', received: 0, deliveryAttempt: 1, ack: sinon.stub(), modAck: () => { }, nack: () => { }, data: Buffer.from(JSON.stringify(msg)), }; await server.handleMessage(timeoutMessageOptions); (0, chai_1.expect)(topicMock.publishMessage.calledWith({ data: Buffer.from(JSON.stringify({ id: timeoutMessageOptions.attributes._id, status: 'error', err: 'Message Timeout', })), attributes: Object.assign({ id: timeoutMessageOptions.attributes._id }, timeoutMessageOptions.attributes), })).to.be.true; (0, chai_1.expect)(timeoutMessageOptions.ack.calledOnce).to.be .true; }); it('should call handler if exists in handlers object', async () => { const handler = sinon.spy(); server.messageHandlers = objectToMap({ [messageOptions.attributes._pattern]: handler, }); await server.handleMessage(messageOptions); (0, chai_1.expect)(handler.calledOnce).to.be.true; }); it('should ack after response if ackAfterResponse is true', async () => { server = getInstance({ ackAfterResponse: true }); await server.listen(() => { }); await server.close(); const handler = sinon.spy(); server.messageHandlers = objectToMap({ [messageOptions.attributes._pattern]: handler, }); await server.handleMessage(messageOptions); (0, chai_1.expect)(handler.calledOnce).to.be.true; (0, chai_1.expect)(messageOptions.ack.calledOnce); }); }); describe('sendMessage', () => { beforeEach(async () => { server = getInstance({}); await server.listen(() => { }); }); it('should publish message to indicated topic', async () => { const message = { test: true }; const replyTo = 'test'; const correlationId = '0'; await server.sendMessage(message, replyTo, correlationId); (0, chai_1.expect)(topicMock.publishMessage.calledWith({ data: Buffer.from(JSON.stringify(Object.assign(Object.assign({}, message), { id: correlationId }))), attributes: { id: correlationId, }, })).to.be.true; }); }); describe('handleEvent', () => { const channel = 'test'; const data = 'test'; beforeEach(async () => { server = getInstance({}); }); it('should call handler with expected arguments', () => { const handler = sandbox.spy(); server.messageHandlers = objectToMap({ [channel]: handler, }); server.handleEvent(channel, { pattern: '', data }, new base_rpc_context_1.BaseRpcContext([])); (0, chai_1.expect)(handler.calledWith(data)).to.be.true; }); }); describe('createIfNotExists', () => { it('should throw error', async () => { const create = sandbox.stub().rejects({ code: 7 }); try { await server['createIfNotExists'](create); } catch (error) { (0, chai_1.expect)(error).to.include({ code: 7 }); } (0, chai_1.expect)(create.called).to.be.true; }); it('should skip error', async () => { const create = sandbox.stub().rejects({ code: gc_pubsub_constants_1.ALREADY_EXISTS }); await server['createIfNotExists'](create); (0, chai_1.expect)(create.called).to.be.true; }); }); function getInstance(options) { const server = new gc_pubsub_server_1.GCPubSubServer(options); sandbox = sinon.createSandbox(); subscriptionMock = { create: sandbox.stub().resolves(), close: sandbox.stub().callsFake((callback) => callback()), on: sandbox.stub().returnsThis(), exists: sandbox.stub().resolves([true]), delete: sandbox.stub().resolves(), }; topicMock = { create: sandbox.stub().resolves(), exists: sandbox.stub().resolves([true]), flush: sandbox.stub().callsFake((callback) => callback()), publishMessage: sandbox.stub().resolves(), subscription: sandbox.stub().returns(subscriptionMock), }; pubsub = { topic: sandbox.stub().returns(topicMock), close: sandbox.stub().callsFake((callback) => callback()), }; createClient = sandbox.stub(server, 'createClient').returns(pubsub); return server; } }); //# sourceMappingURL=gc-pubsub.server.spec.js.map