From 7e1fde877e550c7d6dd28a9e09a86614b2e7979d Mon Sep 17 00:00:00 2001 From: Rohit <40559587+Rohit3523@users.noreply.github.com> Date: Thu, 1 Oct 2026 12:34:08 +0530 Subject: [PATCH] fix: stay on WorkspaceView when retrying connect without credentials --- .../__tests__/selectServer.sdkHost.test.ts | 28 +++++++++++++++++++ app/sagas/selectServer.ts | 11 ++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/sagas/__tests__/selectServer.sdkHost.test.ts b/app/sagas/__tests__/selectServer.sdkHost.test.ts index 04d21332fd3..3bed59b6766 100644 --- a/app/sagas/__tests__/selectServer.sdkHost.test.ts +++ b/app/sagas/__tests__/selectServer.sdkHost.test.ts @@ -38,23 +38,34 @@ import { APP, SERVER } from '~/actions/actionsTypes'; import { RootEnum } from '~/definitions'; import sdk from '~/lib/services/sdk'; import { connect } from '~/lib/services/connect'; +import UserPreferences from '~/lib/methods/userPreferences'; +import { getServerUserIdKey, getUserTokenKey } from '~/lib/constants/keys'; import type { MockConnection } from '~/lib/testUtils/sdkIntegration'; import type * as SdkIntegration from '~/lib/testUtils/sdkIntegration'; import { cancelSagaTasks, createRecordingStore, flushSagaMicrotasks } from '~/lib/testUtils/sagaStore'; const HOST = 'https://open.rocket.chat'; +const USER_ID = 'user-open'; +const TOKEN = 'token-open'; describe('selectServer saga — redundant select for the live SDK host', () => { beforeEach(() => { mockConnections.length = 0; + jest.clearAllMocks(); + UserPreferences.removeItem(getServerUserIdKey(HOST)); + UserPreferences.removeItem(getUserTokenKey(HOST, USER_ID)); }); afterEach(() => { cancelSagaTasks(); sdk.disconnect(); + UserPreferences.removeItem(getServerUserIdKey(HOST)); + UserPreferences.removeItem(getUserTokenKey(HOST, USER_ID)); }); it('reads the live host off the real SDK client and cancels the select without reconnecting', async () => { + UserPreferences.setString(getServerUserIdKey(HOST), USER_ID); + UserPreferences.setString(getUserTokenKey(HOST, USER_ID), TOKEN); sdk.initialize(HOST); expect(sdk.host).toBe(HOST); @@ -70,4 +81,21 @@ describe('selectServer saga — redundant select for the live SDK host', () => { expect(cancelIndex).toBeGreaterThan(insideIndex); expect(connect).not.toHaveBeenCalled(); }); + + it('reconnects and stays outside when the same host has no stored credentials (workspace retry)', async () => { + sdk.initialize(HOST); + expect(sdk.host).toBe(HOST); + + const { store, dispatchedActions } = createRecordingStore(selectServerRoot); + + store.dispatch(selectServerRequest(HOST, '7.0.0', false)); + await flushSagaMicrotasks(); + + expect(connect).toHaveBeenCalledWith({ server: HOST }); + const outsideIndex = dispatchedActions.findIndex( + action => action.type === APP.START && action.root === RootEnum.ROOT_OUTSIDE + ); + expect(outsideIndex).toBeGreaterThanOrEqual(0); + expect(dispatchedActions.map(action => action.type)).not.toContain(SERVER.SELECT_CANCEL); + }); }); diff --git a/app/sagas/selectServer.ts b/app/sagas/selectServer.ts index 1c13d6abf84..98f5ec5c749 100644 --- a/app/sagas/selectServer.ts +++ b/app/sagas/selectServer.ts @@ -139,9 +139,14 @@ const getServerInfoSaga = function* getServerInfoSaga({ server, raiseError = tru const handleSelectServer = function* handleSelectServer({ server, version, fetchVersion }: ISelectServerAction) { try { if (sdk.host === server) { - yield put(appStart({ root: RootEnum.ROOT_INSIDE })); - yield put(selectServerCancel()); - return; + // Skip fast-path for unauthenticated retries so they stay OUTSIDE on WorkspaceView. + const storedUserId = UserPreferences.getString(getServerUserIdKey(server)); + const storedToken = storedUserId ? UserPreferences.getString(getUserTokenKey(server, storedUserId)) : null; + if (storedUserId && storedToken) { + yield put(appStart({ root: RootEnum.ROOT_INSIDE })); + yield put(selectServerCancel()); + return; + } } // SSL Pinning - Read certificate alias and set it to be used by network requests const certificate = UserPreferences.getString(`${CERTIFICATE_KEY}-${server}`);