feat(ws): add unit tests for manually ack

This commit is contained in:
Seongjee Kim
2025-08-18 18:34:19 +09:00
parent 6559c97d12
commit 92372ae978
3 changed files with 80 additions and 3 deletions

View File

@@ -0,0 +1,28 @@
import 'reflect-metadata';
import { expect } from 'chai';
import { PARAM_ARGS_METADATA } from '../../constants';
import { Ack } from '../../decorators/ack.decorator';
import { WsParamtype } from '../../enums/ws-paramtype.enum';
class AckTest {
public test(@Ack() ack: Function) {}
}
describe('@Ack', () => {
it('should enhance class with expected request metadata', () => {
const argsMetadata = Reflect.getMetadata(
PARAM_ARGS_METADATA,
AckTest,
'test',
);
const expectedMetadata = {
[`${WsParamtype.ACK}:0`]: {
index: 0,
data: undefined,
pipes: [],
},
};
expect(argsMetadata).to.be.eql(expectedMetadata);
});
});

View File

@@ -4,11 +4,13 @@ import { MetadataScanner } from '../../core/metadata-scanner';
import { WebSocketServer } from '../decorators/gateway-server.decorator';
import { WebSocketGateway } from '../decorators/socket-gateway.decorator';
import { SubscribeMessage } from '../decorators/subscribe-message.decorator';
import { Ack } from '../decorators/ack.decorator';
import { GatewayMetadataExplorer } from '../gateway-metadata-explorer';
describe('GatewayMetadataExplorer', () => {
const message = 'test';
const secMessage = 'test2';
const ackMessage = 'ack-test';
@WebSocketGateway()
class Test {
@@ -28,6 +30,9 @@ describe('GatewayMetadataExplorer', () => {
@SubscribeMessage(secMessage)
public testSec() {}
@SubscribeMessage(ackMessage)
public testWithAck(@Ack() ack: Function) {}
public noMessage() {}
}
let instance: GatewayMetadataExplorer;
@@ -61,9 +66,22 @@ describe('GatewayMetadataExplorer', () => {
});
it(`should return message mapping properties when "isMessageMapping" metadata is not undefined`, () => {
const metadata = instance.exploreMethodMetadata(test, 'test')!;
expect(metadata).to.have.keys(['callback', 'message', 'methodName']);
expect(metadata).to.have.keys([
'callback',
'message',
'methodName',
'isAckHandledManually',
]);
expect(metadata.message).to.eql(message);
});
it('should set "isAckHandledManually" property to true when @Ack decorator is used', () => {
const metadata = instance.exploreMethodMetadata(test, 'testWithAck')!;
expect(metadata.isAckHandledManually).to.be.true;
});
it('should set "isAckHandledManually" property to false when @Ack decorator is not used', () => {
const metadata = instance.exploreMethodMetadata(test, 'test')!;
expect(metadata.isAckHandledManually).to.be.false;
});
});
describe('scanForServerHooks', () => {
it(`should return properties with @Client decorator`, () => {

View File

@@ -135,6 +135,7 @@ describe('WebSocketsController', () => {
message: 'message',
methodName: 'methodName',
callback: handlerCallback,
isAckHandledManually: false,
},
];
server = { server: 'test' };
@@ -173,6 +174,7 @@ describe('WebSocketsController', () => {
message: 'message',
methodName: 'methodName',
callback: messageHandlerCallback,
isAckHandledManually: false,
},
]);
});
@@ -188,11 +190,13 @@ describe('WebSocketsController', () => {
methodName: 'findOne',
message: 'find',
callback: null!,
isAckHandledManually: false,
},
{
methodName: 'create',
message: 'insert',
callback: null!,
isAckHandledManually: false,
},
];
const insertEntrypointDefinitionSpy = sinon.spy(
@@ -413,6 +417,7 @@ describe('WebSocketsController', () => {
expect(subscribe.called).to.be.true;
});
});
describe('subscribeMessages', () => {
const gateway = new Test();
@@ -423,14 +428,40 @@ describe('WebSocketsController', () => {
client = { on: onSpy, off: onSpy };
handlers = [
{ message: 'test', callback: { bind: () => 'testCallback' } },
{ message: 'test2', callback: { bind: () => 'testCallback2' } },
{
message: 'test',
callback: { bind: () => 'testCallback' },
isAckHandledManually: true,
},
{
message: 'test2',
callback: { bind: () => 'testCallback2' },
isAckHandledManually: false,
},
];
});
it('should bind each handler to client', () => {
instance.subscribeMessages(handlers, client, gateway);
expect(onSpy.calledTwice).to.be.true;
});
it('should pass "isAckHandledManually" flag to the adapter', () => {
const adapter = config.getIoAdapter();
const bindMessageHandlersSpy = sinon.spy(adapter, 'bindMessageHandlers');
instance.subscribeMessages(handlers, client, gateway);
const handlersPassedToAdapter = bindMessageHandlersSpy.firstCall.args[1];
expect(handlersPassedToAdapter[0].message).to.equal(handlers[0].message);
expect(handlersPassedToAdapter[0].isAckHandledManually).to.equal(
handlers[0].isAckHandledManually,
);
expect(handlersPassedToAdapter[1].message).to.equal(handlers[1].message);
expect(handlersPassedToAdapter[1].isAckHandledManually).to.equal(
handlers[1].isAckHandledManually,
);
});
});
describe('pickResult', () => {
describe('when deferredResult contains value which', () => {