mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
289 lines
8.8 KiB
TypeScript
289 lines
8.8 KiB
TypeScript
import { expect } from 'chai';
|
|
import * as sinon from 'sinon';
|
|
import { NO_MESSAGE_HANDLER } from '../../constants';
|
|
import { BaseRpcContext } from '../../ctx-host/base-rpc.context';
|
|
import { ServerRedis } from '../../server/server-redis';
|
|
import { objectToMap } from './utils/object-to-map';
|
|
|
|
describe('ServerRedis', () => {
|
|
let server: ServerRedis;
|
|
let untypedServer: any;
|
|
|
|
beforeEach(() => {
|
|
server = new ServerRedis({});
|
|
untypedServer = server as any;
|
|
});
|
|
describe('listen', () => {
|
|
let onSpy: sinon.SinonSpy;
|
|
let connectSpy: sinon.SinonSpy;
|
|
let client: any;
|
|
let callbackSpy: sinon.SinonSpy;
|
|
|
|
beforeEach(() => {
|
|
onSpy = sinon.spy();
|
|
connectSpy = sinon.spy();
|
|
|
|
client = {
|
|
on: onSpy,
|
|
connect: connectSpy,
|
|
};
|
|
sinon.stub(server, 'createRedisClient').callsFake(() => client);
|
|
|
|
callbackSpy = sinon.spy();
|
|
});
|
|
it('should bind "error" event to handler', () => {
|
|
server.listen(callbackSpy);
|
|
expect(onSpy.getCall(0).args[0]).to.be.equal('error');
|
|
});
|
|
it('should call "RedisClient#connect()"', () => {
|
|
server.listen(callbackSpy);
|
|
expect(connectSpy.called).to.be.true;
|
|
});
|
|
describe('when "start" throws an exception', () => {
|
|
it('should call callback with a thrown error as an argument', () => {
|
|
const error = new Error('random error');
|
|
|
|
const callbackSpy = sinon.spy();
|
|
sinon.stub(server, 'start').callsFake(() => {
|
|
throw error;
|
|
});
|
|
server.listen(callbackSpy);
|
|
expect(callbackSpy.calledWith(error)).to.be.true;
|
|
});
|
|
});
|
|
});
|
|
describe('close', () => {
|
|
const pub = { quit: sinon.spy() };
|
|
const sub = { quit: sinon.spy() };
|
|
beforeEach(() => {
|
|
untypedServer.pubClient = pub;
|
|
untypedServer.subClient = sub;
|
|
});
|
|
it('should close pub & sub server', () => {
|
|
server.close();
|
|
|
|
expect(pub.quit.called).to.be.true;
|
|
expect(sub.quit.called).to.be.true;
|
|
});
|
|
});
|
|
describe('handleConnection', () => {
|
|
let onSpy: sinon.SinonSpy, subscribeSpy: sinon.SinonSpy, sub, psub;
|
|
|
|
beforeEach(() => {
|
|
onSpy = sinon.spy();
|
|
subscribeSpy = sinon.spy();
|
|
sub = {
|
|
on: onSpy,
|
|
subscribe: subscribeSpy,
|
|
};
|
|
psub = {
|
|
on: onSpy,
|
|
psubscribe: subscribeSpy,
|
|
};
|
|
});
|
|
it('should bind "message" event to handler if wildcards are disabled', () => {
|
|
server.bindEvents(sub, null);
|
|
expect(onSpy.getCall(0).args[0]).to.be.equal('message');
|
|
});
|
|
it('should bind "pmessage" event to handler if wildcards are enabled', () => {
|
|
untypedServer.options = {};
|
|
untypedServer.options.wildcards = true;
|
|
|
|
server.bindEvents(psub, null);
|
|
expect(onSpy.getCall(0).args[0]).to.be.equal('pmessage');
|
|
});
|
|
|
|
it('should "subscribe" to each pattern if wildcards are disabled', () => {
|
|
const pattern = 'test';
|
|
const handler = sinon.spy();
|
|
untypedServer.messageHandlers = objectToMap({
|
|
[pattern]: handler,
|
|
});
|
|
server.bindEvents(sub, null);
|
|
expect(subscribeSpy.calledWith(pattern)).to.be.true;
|
|
});
|
|
|
|
it('should "psubscribe" to each pattern if wildcards are enabled', () => {
|
|
untypedServer.options = {};
|
|
untypedServer.options.wildcards = true;
|
|
|
|
const pattern = 'test';
|
|
const handler = sinon.spy();
|
|
untypedServer.messageHandlers = objectToMap({
|
|
[pattern]: handler,
|
|
});
|
|
server.bindEvents(psub, null);
|
|
expect(subscribeSpy.calledWith(pattern)).to.be.true;
|
|
});
|
|
});
|
|
describe('getMessageHandler', () => {
|
|
it(`should return function`, () => {
|
|
expect(typeof server.getMessageHandler(null)).to.be.eql('function');
|
|
});
|
|
});
|
|
describe('handleMessage', () => {
|
|
let getPublisherSpy: sinon.SinonSpy;
|
|
|
|
const channel = 'test';
|
|
const data = 'test';
|
|
const id = '3';
|
|
|
|
beforeEach(() => {
|
|
getPublisherSpy = sinon.spy();
|
|
sinon.stub(server, 'getPublisher').callsFake(() => getPublisherSpy);
|
|
});
|
|
it('should call "handleEvent" if identifier is not present', async () => {
|
|
const handleEventSpy = sinon.spy(server, 'handleEvent');
|
|
sinon.stub(server, 'parseMessage').callsFake(() => ({ data }) as any);
|
|
|
|
await server.handleMessage(channel, JSON.stringify({}), null, channel);
|
|
expect(handleEventSpy.called).to.be.true;
|
|
});
|
|
it(`should publish NO_MESSAGE_HANDLER if pattern not exists in messageHandlers object`, async () => {
|
|
sinon.stub(server, 'parseMessage').callsFake(() => ({ id, data }) as any);
|
|
await server.handleMessage(
|
|
channel,
|
|
JSON.stringify({ id }),
|
|
null,
|
|
channel,
|
|
);
|
|
expect(
|
|
getPublisherSpy.calledWith({
|
|
id,
|
|
status: 'error',
|
|
err: NO_MESSAGE_HANDLER,
|
|
}),
|
|
).to.be.true;
|
|
});
|
|
it(`should call handler with expected arguments`, async () => {
|
|
const handler = sinon.spy();
|
|
untypedServer.messageHandlers = objectToMap({
|
|
[channel]: handler,
|
|
});
|
|
sinon.stub(server, 'parseMessage').callsFake(() => ({ id, data }) as any);
|
|
|
|
await server.handleMessage(channel, '', null, channel);
|
|
expect(handler.calledWith(data)).to.be.true;
|
|
});
|
|
});
|
|
describe('getPublisher', () => {
|
|
let publisherSpy: sinon.SinonSpy;
|
|
let pub, publisher;
|
|
|
|
const id = '1';
|
|
const pattern = 'test';
|
|
|
|
beforeEach(() => {
|
|
publisherSpy = sinon.spy();
|
|
pub = {
|
|
publish: publisherSpy,
|
|
};
|
|
publisher = server.getPublisher(pub, pattern, id);
|
|
});
|
|
it(`should return function`, () => {
|
|
expect(typeof server.getPublisher(null, null, id)).to.be.eql('function');
|
|
});
|
|
it(`should call "publish" with expected arguments`, () => {
|
|
const respond = 'test';
|
|
publisher({ respond, id });
|
|
expect(
|
|
publisherSpy.calledWith(
|
|
`${pattern}.reply`,
|
|
JSON.stringify({ respond, id }),
|
|
),
|
|
).to.be.true;
|
|
});
|
|
});
|
|
describe('parseMessage', () => {
|
|
it(`should return parsed json`, () => {
|
|
const obj = { test: 'test' };
|
|
expect(server.parseMessage(obj)).to.deep.equal(
|
|
JSON.parse(JSON.stringify(obj)),
|
|
);
|
|
});
|
|
it(`should not parse argument if it is not an object`, () => {
|
|
const content = 'test';
|
|
expect(server.parseMessage(content)).to.equal(content);
|
|
});
|
|
});
|
|
describe('getRequestPattern', () => {
|
|
const test = 'test';
|
|
it(`should leave pattern as it is`, () => {
|
|
const expectedResult = test;
|
|
expect(server.getRequestPattern(test)).to.equal(expectedResult);
|
|
});
|
|
});
|
|
describe('getReplyPattern', () => {
|
|
const test = 'test';
|
|
it(`should append ".reply" to string`, () => {
|
|
const expectedResult = test + '.reply';
|
|
expect(server.getReplyPattern(test)).to.equal(expectedResult);
|
|
});
|
|
});
|
|
describe('getClientOptions', () => {
|
|
it('should return options object with "retryStrategy" and call "createRetryStrategy"', () => {
|
|
const createSpy = sinon.spy(server, 'createRetryStrategy');
|
|
const { retryStrategy } = server.getClientOptions()!;
|
|
try {
|
|
retryStrategy!(0);
|
|
} catch {
|
|
// Ignore
|
|
}
|
|
expect(createSpy.called).to.be.true;
|
|
});
|
|
});
|
|
describe('createRetryStrategy', () => {
|
|
describe('when is terminated', () => {
|
|
it('should return undefined', () => {
|
|
untypedServer.isManuallyClosed = true;
|
|
const result = server.createRetryStrategy(0);
|
|
expect(result).to.be.undefined;
|
|
});
|
|
});
|
|
describe('when "retryAttempts" does not exist', () => {
|
|
it('should return undefined', () => {
|
|
untypedServer.options.options = {};
|
|
untypedServer.options.options.retryAttempts = undefined;
|
|
|
|
expect(server.createRetryStrategy(4)).to.be.undefined;
|
|
});
|
|
});
|
|
describe('when "attempts" count is max', () => {
|
|
it('should return undefined', () => {
|
|
untypedServer.options.options = {};
|
|
untypedServer.options.options.retryAttempts = 3;
|
|
|
|
expect(server.createRetryStrategy(4)).to.be.undefined;
|
|
});
|
|
});
|
|
describe('otherwise', () => {
|
|
it('should return delay (ms)', () => {
|
|
untypedServer.options = {};
|
|
untypedServer.isManuallyClosed = false;
|
|
untypedServer.options.retryAttempts = 3;
|
|
untypedServer.options.retryDelay = 3;
|
|
const result = server.createRetryStrategy(2);
|
|
expect(result).to.be.eql(untypedServer.options.retryDelay);
|
|
});
|
|
});
|
|
});
|
|
describe('handleEvent', () => {
|
|
const channel = 'test';
|
|
const data = 'test';
|
|
|
|
it('should call handler with expected arguments', async () => {
|
|
const handler = sinon.spy();
|
|
untypedServer.messageHandlers = objectToMap({
|
|
[channel]: handler,
|
|
});
|
|
|
|
await server.handleEvent(
|
|
channel,
|
|
{ pattern: '', data },
|
|
new BaseRpcContext([]),
|
|
);
|
|
expect(handler.calledWith(data)).to.be.true;
|
|
});
|
|
});
|
|
});
|