From 0c7b94d34e4851c63aab0579bda007c380d0a435 Mon Sep 17 00:00:00 2001 From: Seongjee Kim Date: Mon, 18 Aug 2025 19:13:55 +0900 Subject: [PATCH] feat(ws): add integration for manually ack --- .../websockets/e2e/gateway-ack.spec.ts | 33 +++++++++++++++++++ integration/websockets/src/ack.gateway.ts | 22 ++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/integration/websockets/e2e/gateway-ack.spec.ts b/integration/websockets/e2e/gateway-ack.spec.ts index 034a7ae29..6ae5658b5 100644 --- a/integration/websockets/e2e/gateway-ack.spec.ts +++ b/integration/websockets/e2e/gateway-ack.spec.ts @@ -41,5 +41,38 @@ describe('WebSocketGateway (ack)', () => { ); }); + it('should handle manual ack for async operations when @Ack() is used (success case)', async () => { + app = await createNestApp(AckGateway); + await app.listen(3000); + + ws = io('http://localhost:8080'); + const payload = { shouldSucceed: true }; + + await new Promise(resolve => + ws.emit('manual-ack', payload, response => { + expect(response).to.eql({ status: 'success', data: payload }); + resolve(); + }), + ); + }); + + it('should handle manual ack for async operations when @Ack() is used (error case)', async () => { + app = await createNestApp(AckGateway); + await app.listen(3000); + + ws = io('http://localhost:8080'); + const payload = { shouldSucceed: false }; + + await new Promise(resolve => + ws.emit('manual-ack', payload, response => { + expect(response).to.eql({ + status: 'error', + message: 'Operation failed', + }); + resolve(); + }), + ); + }); + afterEach(() => app.close()); }); diff --git a/integration/websockets/src/ack.gateway.ts b/integration/websockets/src/ack.gateway.ts index d1855058d..54942d74d 100644 --- a/integration/websockets/src/ack.gateway.ts +++ b/integration/websockets/src/ack.gateway.ts @@ -1,4 +1,9 @@ -import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'; +import { + Ack, + MessageBody, + SubscribeMessage, + WebSocketGateway, +} from '@nestjs/websockets'; @WebSocketGateway(8080) export class AckGateway { @@ -6,4 +11,19 @@ export class AckGateway { onPush() { return 'pong'; } + + @SubscribeMessage('manual-ack') + async handleManualAck( + @MessageBody() data: any, + @Ack() ack: (response: any) => void, + ) { + await new Promise(resolve => setTimeout(resolve, 20)); + + if (data.shouldSucceed) { + ack({ status: 'success', data }); + } else { + ack({ status: 'error', message: 'Operation failed' }); + } + return { status: 'ignored' }; + } }