Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions app/lib/services/connect.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { connect, determineAuthType, disconnect } from './connect';
import { mediaSessionInstance } from './voip/MediaSessionInstance';
import { pendingHangups } from './voip/pendingHangups';
import { unsubscribeRooms } from '../methods/subscribeRooms';

jest.mock('./voip/MediaSessionInstance', () => ({
mediaSessionInstance: { reset: jest.fn(), drainPendingHangups: jest.fn() }
Expand Down Expand Up @@ -481,4 +482,34 @@ describe('connect — pendingHangups drain on reconnect', () => {
});
});

describe('connect — rooms subscription guard reset on close', () => {
beforeEach(() => {
jest.clearAllMocks();
mockOnStreamDataStops.length = 0;
mockStoreGetState.mockReturnValue({
meteor: { connected: false },
login: { user: null, isAuthenticated: false },
settings: {}
});
});

// Regression: a long background marks the DDP socket stale, so foregrounding triggers
// `checkAndReopen` → `forceReopen`, which wipes the SDK subscriptions and emits 'close' while
// bypassing `connect()`. The rooms-list `stream-notify-user` feed only re-subscribes when the
// module-level guard in `subscribeRooms` is clear, and `unsubscribeRooms()` is what clears it.
// If the 'close' handler stops calling `unsubscribeRooms()`, the guard stays set after reconnect
// and the rooms list silently stops updating (subscriptions/favorites/reads).
it('calls unsubscribeRooms when the socket "close" fires', async () => {
await connect({ server: 'https://example.com' });

// connect() itself calls unsubscribeRooms() once while tearing down prior listeners; ignore it.
(unsubscribeRooms as jest.Mock).mockClear();

const closeHandler = getHandlersByEvent('close')[0];
closeHandler();

expect(unsubscribeRooms).toHaveBeenCalledTimes(1);
});
});

// Note: Apple authentication when isIOS is true is tested in connect.ios.test.ts
5 changes: 5 additions & 0 deletions app/lib/services/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ function connect({ server, logoutOnError = false }: { server: string; logoutOnEr
let pendingHangupsDrainArmed = false;

closeListener = sdk.current.onStreamData('close', () => {
// Reset the rooms-subscription guard on every socket close. `forceReopen` (triggered by
// `checkAndReopen` after a long background) wipes the SDK subscriptions and emits 'close'
// but bypasses `connect()`, so without this the guard in `subscribeRooms` stays set and
// `stream-notify-user` is never re-subscribed — the rooms list silently stops updating.
unsubscribeRooms();
pendingHangupsDrainArmed = true;
store.dispatch(disconnectAction());
});
Expand Down
Loading