mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
229 lines
6.9 KiB
TypeScript
229 lines
6.9 KiB
TypeScript
import { expect } from 'chai';
|
|
import { join } from 'path';
|
|
import { of } from 'rxjs';
|
|
import * as sinon from 'sinon';
|
|
import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.exception';
|
|
import { ServerGrpc } from '../../server/server-grpc';
|
|
|
|
describe('ServerGrpc', () => {
|
|
let server: ServerGrpc;
|
|
beforeEach(() => {
|
|
server = new ServerGrpc({
|
|
protoPath: join(__dirname, './test.proto'),
|
|
package: 'test',
|
|
} as any);
|
|
});
|
|
|
|
describe('listen', () => {
|
|
let callback: sinon.SinonSpy;
|
|
let bindEventsStub: sinon.SinonStub;
|
|
|
|
beforeEach(() => {
|
|
callback = sinon.spy();
|
|
bindEventsStub = sinon.stub(server, 'bindEvents').callsFake(() => ({}));
|
|
});
|
|
|
|
it('should call "bindEvents"', async () => {
|
|
await server.listen(callback);
|
|
expect(bindEventsStub.called).to.be.true;
|
|
});
|
|
it('should call "client.start"', async () => {
|
|
const client = { start: sinon.spy() };
|
|
sinon.stub(server, 'createClient').callsFake(() => client);
|
|
|
|
await server.listen(callback);
|
|
expect(client.start.called).to.be.true;
|
|
});
|
|
it('should call callback', async () => {
|
|
await server.listen(callback);
|
|
expect(callback.called).to.be.true;
|
|
});
|
|
});
|
|
|
|
describe('bindEvents', () => {
|
|
describe('when package does not exist', () => {
|
|
it('should throw "InvalidGrpcPackageException"', () => {
|
|
sinon.stub(server, 'lookupPackage').callsFake(() => null);
|
|
expect(server.bindEvents()).to.eventually.throws(
|
|
InvalidGrpcPackageException,
|
|
);
|
|
});
|
|
});
|
|
describe('when package exist', () => {
|
|
it('should call "addService"', async () => {
|
|
const serviceNames = ['test', 'test2'];
|
|
sinon.stub(server, 'lookupPackage').callsFake(() => ({
|
|
test: true,
|
|
test2: true,
|
|
}));
|
|
sinon.stub(server, 'getServiceNames').callsFake(() => serviceNames);
|
|
|
|
(server as any).grpcClient = { addService: sinon.spy() };
|
|
|
|
await server.bindEvents();
|
|
expect((server as any).grpcClient.addService.calledTwice).to.be.true;
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getServiceNames', () => {
|
|
it('should return filtered object keys', () => {
|
|
const obj = {
|
|
key: { service: true },
|
|
key2: { service: true },
|
|
key3: { service: false },
|
|
};
|
|
const expected = ['key', 'key2'];
|
|
expect(server.getServiceNames(obj)).to.be.eql(expected);
|
|
});
|
|
});
|
|
|
|
describe('createService', () => {
|
|
it('should call "createServiceMethod"', async () => {
|
|
const handlers = {
|
|
test: null,
|
|
test2: () => ({}),
|
|
};
|
|
sinon
|
|
.stub(server, 'createPattern')
|
|
.onFirstCall()
|
|
.returns('test')
|
|
.onSecondCall()
|
|
.returns('test2');
|
|
|
|
const spy = sinon
|
|
.stub(server, 'createServiceMethod')
|
|
.callsFake(() => ({}));
|
|
|
|
(server as any).messageHandlers = handlers;
|
|
await server.createService(
|
|
{
|
|
prototype: { test: true, test2: true },
|
|
},
|
|
'name',
|
|
);
|
|
expect(spy.calledOnce).to.be.true;
|
|
});
|
|
});
|
|
|
|
describe('createPattern', () => {
|
|
it('should return pattern', () => {
|
|
const service = 'test';
|
|
const method = 'method';
|
|
expect(server.createPattern(service, method)).to.be.eql(
|
|
JSON.stringify({
|
|
service,
|
|
rpc: method,
|
|
}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('createServiceMethod', () => {
|
|
describe('when method is a response stream', () => {
|
|
it('should call "createStreamServiceMethod"', () => {
|
|
const cln = sinon.spy();
|
|
const spy = sinon.spy(server, 'createStreamServiceMethod');
|
|
server.createServiceMethod(cln, { responseStream: true } as any);
|
|
|
|
expect(spy.called).to.be.true;
|
|
});
|
|
});
|
|
describe('when method is not a response stream', () => {
|
|
it('should call "createUnaryServiceMethod"', () => {
|
|
const cln = sinon.spy();
|
|
const spy = sinon.spy(server, 'createUnaryServiceMethod');
|
|
server.createServiceMethod(cln, { responseStream: false } as any);
|
|
|
|
expect(spy.called).to.be.true;
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('createStreamServiceMethod', () => {
|
|
it('should return function', () => {
|
|
const fn = server.createStreamServiceMethod(sinon.spy());
|
|
expect(fn).to.be.a('function');
|
|
});
|
|
describe('on call', () => {
|
|
it('should call native method', async () => {
|
|
const call = {
|
|
write: sinon.spy(),
|
|
end: sinon.spy(),
|
|
addListener: sinon.spy(),
|
|
removeListener: sinon.spy(),
|
|
};
|
|
const callback = sinon.spy();
|
|
const native = sinon.spy();
|
|
|
|
await server.createStreamServiceMethod(native)(call, callback);
|
|
expect(native.called).to.be.true;
|
|
expect(call.addListener.calledWith('cancelled')).to.be.true;
|
|
expect(call.removeListener.calledWith('cancelled')).to.be.true;
|
|
});
|
|
|
|
it(`should close the result observable when receiving an 'cancelled' event from the client`, async () => {
|
|
let cancelCb: () => void;
|
|
const call = {
|
|
write: sinon
|
|
.stub()
|
|
.onSecondCall()
|
|
.callsFake(() => cancelCb()),
|
|
end: sinon.spy(),
|
|
addListener: (name, cb) => (cancelCb = cb),
|
|
removeListener: sinon.spy(),
|
|
};
|
|
const result$ = of(1, 2, 3);
|
|
const callback = sinon.spy();
|
|
const native = sinon
|
|
.stub()
|
|
.returns(new Promise((resolve, reject) => resolve(result$)));
|
|
|
|
await server.createStreamServiceMethod(native)(call, callback);
|
|
expect(call.write.calledTwice).to.be.true;
|
|
expect(call.end.called).to.be.true;
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('createUnaryServiceMethod', () => {
|
|
it('should return observable', () => {
|
|
const fn = server.createUnaryServiceMethod(sinon.spy());
|
|
expect(fn).to.be.a('function');
|
|
});
|
|
describe('on call', () => {
|
|
it('should call native & callback methods', async () => {
|
|
const call = { write: sinon.spy(), end: sinon.spy() };
|
|
const callback = sinon.spy();
|
|
const native = sinon.spy();
|
|
|
|
await server.createUnaryServiceMethod(native)(call, callback);
|
|
expect(native.called).to.be.true;
|
|
expect(callback.called).to.be.true;
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('close', () => {
|
|
it('should call "forceShutdown"', () => {
|
|
const grpcClient = { forceShutdown: sinon.spy() };
|
|
(server as any).grpcClient = grpcClient;
|
|
server.close();
|
|
expect(grpcClient.forceShutdown.called).to.be.true;
|
|
});
|
|
});
|
|
|
|
describe('deserialize', () => {
|
|
it(`should return parsed json`, () => {
|
|
const obj = { test: 'test' };
|
|
expect(server.deserialize(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.deserialize(content)).to.equal(content);
|
|
});
|
|
});
|
|
});
|