nestjs-google-pubsub-microservice
Version:
NestJS Google Cloud Pub/Sub Microservice Transport
446 lines • 20 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const sinon = require("sinon");
const gc_pubsub_constants_1 = require("./gc-pubsub.constants");
const gc_pubsub_client_1 = require("./gc-pubsub.client");
describe('GCPubSubClient', () => {
let client;
let pubsub;
let topicMock;
let subscriptionMock;
let createClient;
let sandbox;
beforeEach(() => {
sandbox = sinon.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
describe('constructor', () => {
describe('when the scopedEnvKey is defined', () => {
beforeEach(() => {
client = getInstance({
topic: 'topic',
replyTopic: 'replyTopic',
replySubscription: 'replySubscription',
scopedEnvKey: 'my-key',
});
});
it('should set the scopedEnvKey on topics and subscriptions', () => {
(0, chai_1.expect)(client['topicName']).to.be.eq('my-keytopic');
(0, chai_1.expect)(client['replyTopicName']).to.be.eq('my-keyreplyTopic');
(0, chai_1.expect)(client['replySubscriptionName']).to.be.eq('my-keyreplySubscription');
});
});
describe('when the replyTopic and the replySubscription are not defined', () => {
beforeEach(() => {
client = getInstance({
topic: 'topic',
scopedEnvKey: 'my-key',
});
});
it('should set the scopedEnvKey on topics and subscriptions', () => {
(0, chai_1.expect)(client['topicName']).to.be.eq('my-keytopic');
(0, chai_1.expect)(client['replyTopicName']).to.be.eq(undefined);
(0, chai_1.expect)(client['replySubscriptionName']).to.be.eq(undefined);
});
});
});
describe('connect', () => {
describe('when is not connected', () => {
describe('when init is true', () => {
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
});
try {
client['client'] = null;
await client.connect();
}
catch { }
});
it('should call "createClient" once', async () => {
(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.exists" once', async () => {
(0, chai_1.expect)(topicMock.exists.called).to.be.false;
});
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 init is false', () => {
describe('when check existence is true', () => {
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
init: false,
});
try {
client['client'] = null;
await client.connect();
}
catch { }
});
it('should call "createClient" once', async () => {
(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.exists" once', async () => {
(0, chai_1.expect)(topicMock.exists.called).to.be.true;
});
it('should call "topic.create" once', async () => {
(0, chai_1.expect)(topicMock.create.called).to.be.false;
});
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.false;
});
it('should call "subscription.on" twice', async () => {
(0, chai_1.expect)(subscriptionMock.on.callCount).to.eq(2);
});
});
describe('when check existence is false', () => {
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubscription',
init: false,
checkExistence: false,
});
try {
client['client'] = null;
await client.connect();
}
catch { }
});
it('should call "createClient" once', () => {
(0, chai_1.expect)(createClient.called).to.be.true;
});
it('should call "client.topic" once', () => {
(0, chai_1.expect)(pubsub.topic.called).to.be.true;
});
it('should not call "topic.exists" once', () => {
(0, chai_1.expect)(topicMock.exists.called).to.be.false;
});
it('should not call "topic.create" once', () => {
(0, chai_1.expect)(topicMock.create.called).to.be.false;
});
it('should call "topic.subscription" once', () => {
(0, chai_1.expect)(topicMock.subscription.called).to.be.true;
});
it('should not call "subscription.exists" once', () => {
(0, chai_1.expect)(subscriptionMock.exists.called).to.be.false;
});
it('should call "subscription.on" twice', () => {
(0, chai_1.expect)(subscriptionMock.on.callCount).to.eq(2);
});
});
});
});
describe('when is connected', () => {
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
});
try {
client['client'] = pubsub;
await client.connect();
}
catch { }
});
it('should not call "createClient"', async () => {
(0, chai_1.expect)(createClient.called).to.be.false;
});
it('should not call "client.topic"', async () => {
(0, chai_1.expect)(pubsub.topic.called).to.be.false;
});
it('should not call "topic.create"', async () => {
(0, chai_1.expect)(topicMock.create.called).to.be.false;
});
it('should not call "topic.subscription"', async () => {
(0, chai_1.expect)(topicMock.subscription.called).to.be.false;
});
it('should not call "subscription.create"', async () => {
(0, chai_1.expect)(subscriptionMock.create.called).to.be.false;
});
it('should not call "subscription.on"', async () => {
(0, chai_1.expect)(subscriptionMock.on.callCount).to.eq(0);
});
});
describe('when replySubscriptionFilter is provided', () => {
const filter = 'attributes.type = "reply"';
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubscription',
replySubscriptionFilter: filter,
});
try {
client['client'] = null;
await client.connect();
}
catch { }
});
it('should call "pubsub.createSubscription" with the filter', () => {
(0, chai_1.expect)(pubsub.createSubscription.called).to.be.true;
const args = pubsub.createSubscription.getCall(0).args;
(0, chai_1.expect)(args[2]).to.deep.include({ filter });
});
it('should not call "subscription.create"', () => {
(0, chai_1.expect)(subscriptionMock.create.called).to.be.false;
});
});
describe('when replySubscriptionFilter is not provided', () => {
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubscription',
});
try {
client['client'] = null;
await client.connect();
}
catch { }
});
it('should call "subscription.create" without filter', () => {
(0, chai_1.expect)(subscriptionMock.create.called).to.be.true;
});
it('should not call "pubsub.createSubscription"', () => {
(0, chai_1.expect)(pubsub.createSubscription.called).to.be.false;
});
});
});
describe('publish', () => {
describe('useAttributes=false', () => {
const pattern = 'test';
const msg = { pattern, data: 'data' };
beforeEach(() => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
});
client.topic = topicMock;
});
it('should send message to a proper topic', () => {
client['publish'](msg, () => {
(0, chai_1.expect)(topicMock.publishMessage.called).to.be.true;
(0, chai_1.expect)(topicMock.publishMessage.getCall(0).args[0].json).to.be.eql(msg);
});
});
it('should remove listener from routing map on dispose', () => {
client['publish'](msg, () => ({}))();
(0, chai_1.expect)(client['routingMap'].size).to.be.eq(0);
});
it('should call callback on error', () => {
const callback = sandbox.spy();
sinon.stub(client, 'assignPacketId').callsFake(() => {
throw new Error();
});
client['publish'](msg, callback);
(0, chai_1.expect)(callback.called).to.be.true;
(0, chai_1.expect)(callback.getCall(0).args[0].err).to.be.instanceof(Error);
});
});
describe('useAttributes=true', () => {
const pattern = 'test';
const msg = { pattern, data: 'data' };
beforeEach(() => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
useAttributes: true,
});
client.topic = topicMock;
});
it('should send message to a proper topic', () => {
client['publish'](msg, () => { });
(0, chai_1.expect)(topicMock.publishMessage.called).to.be.true;
const message = topicMock.publishMessage.getCall(0).args[0];
(0, chai_1.expect)(message.json).to.be.eql(msg.data);
(0, chai_1.expect)(message.attributes.pattern).to.be.eql(pattern);
(0, chai_1.expect)(message.attributes.id).to.be.not.empty;
});
});
});
describe('handleResponse', () => {
let callback;
const id = '1';
beforeEach(() => {
callback = sandbox.spy();
});
describe('when disposed', () => {
beforeEach(() => {
client['routingMap'].set(id, callback);
client.handleResponse({
data: Buffer.from(JSON.stringify({ id, isDisposed: true })),
attributes: {},
});
});
it('should emit disposed callback', () => {
(0, chai_1.expect)(callback.called).to.be.true;
(0, chai_1.expect)(callback.calledWith({
err: undefined,
response: undefined,
isDisposed: true,
})).to.be.true;
});
});
describe('when not disposed', () => {
let buffer;
beforeEach(() => {
buffer = { id, err: undefined, response: 'res' };
client['routingMap'].set(id, callback);
client.handleResponse({
data: Buffer.from(JSON.stringify(buffer)),
attributes: {},
});
});
it('should not close server', () => {
(0, chai_1.expect)(pubsub.close.called).to.be.false;
});
it('should call callback with error and response data', () => {
(0, chai_1.expect)(callback.called).to.be.true;
(0, chai_1.expect)(callback.calledWith({
err: buffer.err,
response: buffer.response,
})).to.be.true;
});
});
});
describe('close', () => {
beforeEach(async () => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
});
await client.connect();
await client.close();
});
it('should call "replySubscription.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;
});
it('should set "client" to null', () => {
(0, chai_1.expect)(client.client).to.be.null;
});
it('should set "topic" to null', () => {
(0, chai_1.expect)(client.topic).to.be.null;
});
it('should set "replySubscription" to null', () => {
(0, chai_1.expect)(client.replySubscription).to.be.null;
});
});
describe('dispatchEvent', () => {
describe('useAttributes=false', () => {
const msg = { pattern: 'pattern', data: 'data' };
beforeEach(() => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
});
client.topic = topicMock;
});
it('should publish packet', async () => {
await client['dispatchEvent'](msg);
(0, chai_1.expect)(topicMock.publishMessage.called).to.be.true;
});
it('should publish packet with proper data', async () => {
await client['dispatchEvent'](msg);
(0, chai_1.expect)(topicMock.publishMessage.getCall(0).args[0].json).to.be.eql(msg);
});
it('should throw error', async () => {
topicMock.publishMessage.callsFake((a, b, c, d) => d(new Error()));
client['dispatchEvent'](msg).catch((err) => (0, chai_1.expect)(err).to.be.instanceOf(Error));
});
});
describe('useAttributes=true', () => {
const msg = { pattern: 'pattern', data: 'data' };
beforeEach(() => {
client = getInstance({
replyTopic: 'replyTopic',
replySubscription: 'replySubcription',
useAttributes: true,
});
client.topic = topicMock;
});
it('should publish packet', async () => {
await client['dispatchEvent'](msg);
(0, chai_1.expect)(topicMock.publishMessage.called).to.be.true;
});
it('should publish packet with proper data', async () => {
await client['dispatchEvent'](msg);
const message = topicMock.publishMessage.getCall(0).args[0];
(0, chai_1.expect)(message.json).to.be.eql(msg.data);
(0, chai_1.expect)(message.attributes.pattern).to.be.eql(msg.pattern);
});
it('should throw error', async () => {
topicMock.publishMessage.callsFake((a, b, c, d) => d(new Error()));
client['dispatchEvent'](msg).catch((err) => (0, chai_1.expect)(err).to.be.instanceOf(Error));
});
});
});
describe('createIfNotExists', () => {
it('should throw error', async () => {
const create = sandbox.stub().rejects({ code: 7 });
try {
await client['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 client['createIfNotExists'](create);
(0, chai_1.expect)(create.called).to.be.true;
});
});
function getInstance(options) {
const client = new gc_pubsub_client_1.GCPubSubClient(options);
subscriptionMock = {
create: sandbox.stub().resolves(),
close: sandbox.stub().callsFake((callback) => callback()),
on: sandbox.stub().returnsThis(),
exists: sandbox.stub().resolves([true]),
};
topicMock = {
create: sandbox.stub().resolves(),
flush: sandbox.stub().callsFake((callback) => callback()),
publishMessage: sandbox.stub().resolves(),
exists: sandbox.stub().resolves([true]),
subscription: sandbox.stub().returns(subscriptionMock),
};
pubsub = {
topic: sandbox.stub().callsFake(() => topicMock),
close: sandbox.stub().callsFake((callback) => callback()),
createSubscription: sandbox.stub().resolves([subscriptionMock]),
};
createClient = sandbox.stub(client, 'createClient').callsFake(() => pubsub);
return client;
}
});
//# sourceMappingURL=gc-pubsub.client.spec.js.map