Skip to content

Commit 67633f8

Browse files
committed
fix(core-backend): control randomness to fix flaky test
1 parent 796d640 commit 67633f8

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

packages/core-backend/src/BackendWebSocketService.test.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -817,14 +817,17 @@ describe('BackendWebSocketService', () => {
817817
it('should skip connect when reconnect timer is already scheduled', async () => {
818818
await withService(
819819
async ({ service, getMockWebSocket, completeAsyncOperations }) => {
820+
// Mock Math.random to make Cockatiel's jitter deterministic
821+
jest.spyOn(Math, 'random').mockReturnValue(0);
822+
820823
// Connect successfully first
821824
await service.connect();
822825

823826
const mockWs = getMockWebSocket();
824827

825828
// Simulate unexpected close to trigger scheduleReconnect
826829
mockWs.simulateClose(1006, 'Abnormal closure');
827-
await completeAsyncOperations(10);
830+
await completeAsyncOperations(0);
828831

829832
// Verify reconnect timer is scheduled
830833
const attemptsBefore = service.getConnectionInfo().reconnectAttempts;
@@ -894,14 +897,22 @@ describe('BackendWebSocketService', () => {
894897
await withService(
895898
{ mockWebSocketOptions: { autoConnect: false } },
896899
async ({ service, getMockWebSocket, completeAsyncOperations }) => {
900+
// Mock Math.random to make Cockatiel's jitter deterministic
901+
jest.spyOn(Math, 'random').mockReturnValue(0);
902+
897903
// eslint-disable-next-line @typescript-eslint/no-floating-promises
898904
service.connect();
899905
await completeAsyncOperations(10);
900906

901-
// Close during connection phase
907+
// Verify we're in CONNECTING state
902908
const mockWs = getMockWebSocket();
909+
expect(service.getConnectionInfo().state).toBe(
910+
WebSocketState.CONNECTING,
911+
);
912+
913+
// Close during connection phase
903914
mockWs.simulateClose(1006, 'Connection failed');
904-
await completeAsyncOperations(10);
915+
await completeAsyncOperations(0);
905916

906917
// Should schedule reconnect and be in ERROR state
907918
expect(service.getConnectionInfo().state).toBe(WebSocketState.ERROR);
@@ -916,6 +927,9 @@ describe('BackendWebSocketService', () => {
916927
mockWebSocketOptions: { autoConnect: false },
917928
},
918929
async ({ service, getMockWebSocket, completeAsyncOperations }) => {
930+
// Mock Math.random to make Cockatiel's jitter deterministic
931+
jest.spyOn(Math, 'random').mockReturnValue(0);
932+
919933
// Start connection (this sets connectionTimeout)
920934
// eslint-disable-next-line @typescript-eslint/no-floating-promises
921935
service.connect();
@@ -939,7 +953,7 @@ describe('BackendWebSocketService', () => {
939953
// Since state is ERROR (not CONNECTING), onclose will call handleClose
940954
// which will clear connectionTimeout
941955
mockWs.simulateClose(1006, 'Close after timeout');
942-
await completeAsyncOperations(10);
956+
await completeAsyncOperations(0);
943957

944958
// State should still be ERROR or DISCONNECTED
945959
expect([WebSocketState.ERROR, WebSocketState.DISCONNECTED]).toContain(
@@ -952,6 +966,9 @@ describe('BackendWebSocketService', () => {
952966
it('should not schedule multiple reconnects when scheduleReconnect called multiple times', async () => {
953967
await withService(
954968
async ({ service, getMockWebSocket, completeAsyncOperations }) => {
969+
// Mock Math.random to make Cockatiel's jitter deterministic
970+
jest.spyOn(Math, 'random').mockReturnValue(0);
971+
955972
await service.connect();
956973
expect(service.getConnectionInfo().state).toBe(
957974
WebSocketState.CONNECTED,
@@ -961,15 +978,15 @@ describe('BackendWebSocketService', () => {
961978

962979
// First close to trigger scheduleReconnect
963980
mockWs.simulateClose(1006, 'Connection lost');
964-
await completeAsyncOperations(10);
981+
await completeAsyncOperations(0);
965982

966983
const attemptsBefore = service.getConnectionInfo().reconnectAttempts;
967984
expect(attemptsBefore).toBeGreaterThan(0);
968985

969986
// Second close should trigger scheduleReconnect again,
970987
// but it should return early since timer already exists
971988
mockWs.simulateClose(1006, 'Connection lost again');
972-
await completeAsyncOperations(10);
989+
await completeAsyncOperations(0);
973990

974991
// Attempts should not have increased again due to idempotency
975992
expect(service.getConnectionInfo().reconnectAttempts).toBe(
@@ -987,6 +1004,9 @@ describe('BackendWebSocketService', () => {
9871004
it('should force reconnection and schedule connect', async () => {
9881005
await withService(
9891006
async ({ service, getMockWebSocket, completeAsyncOperations }) => {
1007+
// Mock Math.random to make Cockatiel's jitter deterministic
1008+
jest.spyOn(Math, 'random').mockReturnValue(0);
1009+
9901010
await service.connect();
9911011
expect(service.getConnectionInfo().state).toBe(
9921012
WebSocketState.CONNECTED,
@@ -1001,7 +1021,7 @@ describe('BackendWebSocketService', () => {
10011021

10021022
// Force reconnection
10031023
await service.forceReconnection();
1004-
await completeAsyncOperations(10);
1024+
await completeAsyncOperations(0);
10051025

10061026
// Should be disconnected after forceReconnection
10071027
expect(service.getConnectionInfo().state).toBe(
@@ -1018,14 +1038,17 @@ describe('BackendWebSocketService', () => {
10181038
await withService(
10191039
{ mockWebSocketOptions: { autoConnect: false } },
10201040
async ({ service, getMockWebSocket, completeAsyncOperations }) => {
1041+
// Mock Math.random to make Cockatiel's jitter deterministic
1042+
jest.spyOn(Math, 'random').mockReturnValue(0);
1043+
10211044
// Trigger a connection failure to schedule a reconnect
10221045
// eslint-disable-next-line @typescript-eslint/no-floating-promises
10231046
service.connect();
10241047
await completeAsyncOperations(10);
10251048

10261049
const mockWs = getMockWebSocket();
10271050
mockWs.simulateError();
1028-
await completeAsyncOperations(10);
1051+
await completeAsyncOperations(0);
10291052

10301053
const attemptsBefore = service.getConnectionInfo().reconnectAttempts;
10311054

0 commit comments

Comments
 (0)