From e038fb766680a766446420f44798c04e2b10709e Mon Sep 17 00:00:00 2001 From: nav Date: Thu, 9 Apr 2026 03:02:31 +0000 Subject: [PATCH] test: cover malformed hello runtime flow --- tests/runtime-flow.test.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/runtime-flow.test.ts b/tests/runtime-flow.test.ts index 76d13a3..82a0f75 100644 --- a/tests/runtime-flow.test.ts +++ b/tests/runtime-flow.test.ts @@ -287,6 +287,44 @@ describe("Yonexus.Server runtime flow", () => { expect(recordAfterHeartbeat?.lastHeartbeatAt).toBe(now); }); + it("returns MALFORMED_MESSAGE for hello without payload and keeps the connection open", async () => { + const store = createMockStore(); + const transportState = createMockTransport(); + const runtime = createYonexusServerRuntime({ + config: { + followerIdentifiers: ["client-a"], + notifyBotToken: "stub-token", + adminUserId: "admin-user", + listenHost: "127.0.0.1", + listenPort: 8787 + }, + store, + transport: transportState.transport, + now: () => 1_710_000_000 + }); + + await runtime.start(); + + const connection = createConnection(); + await runtime.handleMessage( + connection, + encodeBuiltin({ + type: "hello", + requestId: "req-bad-hello", + timestamp: 1_710_000_000 + }) + ); + + expect(transportState.sentToConnection).toHaveLength(1); + const errorResponse = decodeBuiltin(transportState.sentToConnection[0].message); + expect(errorResponse.type).toBe("error"); + expect(errorResponse.payload).toMatchObject({ + code: "MALFORMED_MESSAGE", + message: "hello payload is required" + }); + expect((connection.ws.close as ReturnType)).not.toHaveBeenCalled(); + }); + it("rejects unauthenticated rule messages by closing the connection", async () => { const store = createMockStore(); const transportState = createMockTransport();