473 lines
22 KiB
TypeScript
473 lines
22 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import NetInfo from '@react-native-community/netinfo';
|
|
import {AppState} from 'react-native';
|
|
import {Subscription} from 'rxjs';
|
|
|
|
import {subscribeActiveServers} from '@database/subscription/servers';
|
|
|
|
import NetworkConnectivityManager from './network_connectivity_manager';
|
|
import {
|
|
startNetworkConnectivitySubscriptions,
|
|
stopNetworkConnectivitySubscriptions,
|
|
shutdownNetworkConnectivitySubscriptions,
|
|
} from './network_connectivity_subscription_manager';
|
|
import NetworkPerformanceManager from './network_performance_manager';
|
|
import WebsocketManager from './websocket_manager';
|
|
|
|
type MockServer = {
|
|
url: string;
|
|
lastActiveAt: number;
|
|
};
|
|
|
|
type MockNetInfoState = {
|
|
isInternetReachable: boolean | null;
|
|
};
|
|
|
|
// Mock dependencies
|
|
jest.mock('@react-native-community/netinfo', () => ({
|
|
addEventListener: jest.fn(),
|
|
}));
|
|
jest.mock('react-native', () => ({
|
|
AppState: {
|
|
addEventListener: jest.fn(),
|
|
},
|
|
}));
|
|
jest.mock('@database/subscription/servers', () => ({
|
|
subscribeActiveServers: jest.fn(),
|
|
}));
|
|
jest.mock('@utils/general', () => ({
|
|
getIntlShape: jest.fn(() => ({
|
|
formatMessage: jest.fn((descriptor) => descriptor.defaultMessage),
|
|
})),
|
|
}));
|
|
jest.mock('./network_connectivity_manager', () => ({
|
|
setServerConnectionStatus: jest.fn(),
|
|
updateState: jest.fn(),
|
|
updatePerformanceState: jest.fn(),
|
|
shutdown: jest.fn(),
|
|
reset: jest.fn(),
|
|
}));
|
|
jest.mock('./websocket_manager', () => ({
|
|
observeWebsocketState: jest.fn(),
|
|
}));
|
|
jest.mock('./network_performance_manager', () => ({
|
|
observePerformanceState: jest.fn(),
|
|
}));
|
|
|
|
const mockAppState = AppState as jest.Mocked<typeof AppState>;
|
|
const mockNetInfo = NetInfo as jest.Mocked<typeof NetInfo>;
|
|
const mockSubscribeActiveServers = subscribeActiveServers as jest.MockedFunction<typeof subscribeActiveServers>;
|
|
const mockNetworkConnectivityManager = NetworkConnectivityManager as jest.Mocked<typeof NetworkConnectivityManager>;
|
|
const mockNetworkPerformanceManager = NetworkPerformanceManager as jest.Mocked<typeof NetworkPerformanceManager>;
|
|
const mockWebsocketManager = WebsocketManager as jest.Mocked<typeof WebsocketManager>;
|
|
|
|
describe('NetworkConnectivitySubscriptionManager', () => {
|
|
const mockWebsocketSubscription = {
|
|
unsubscribe: jest.fn(),
|
|
} as unknown as Subscription;
|
|
|
|
const mockPerformanceSubscription = {
|
|
unsubscribe: jest.fn(),
|
|
} as unknown as Subscription;
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
|
|
mockAppState.addEventListener.mockReturnValue({
|
|
remove: jest.fn(),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
mockNetInfo.addEventListener.mockReturnValue(jest.fn());
|
|
|
|
mockWebsocketManager.observeWebsocketState.mockReturnValue({
|
|
subscribe: jest.fn(() => mockWebsocketSubscription),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
mockNetworkPerformanceManager.observePerformanceState.mockReturnValue({
|
|
subscribe: jest.fn(() => mockPerformanceSubscription),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
});
|
|
|
|
afterEach(() => {
|
|
shutdownNetworkConnectivitySubscriptions();
|
|
});
|
|
|
|
describe('startNetworkConnectivitySubscriptions', () => {
|
|
it('should set up app state listener on first call', () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
expect(mockAppState.addEventListener).toHaveBeenCalledWith('change', expect.any(Function));
|
|
});
|
|
|
|
it('should not recreate app state listener on subsequent calls', () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
mockAppState.addEventListener.mockClear();
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
expect(mockAppState.addEventListener).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should set up net info listener', () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
expect(mockNetInfo.addEventListener).toHaveBeenCalledWith(expect.any(Function));
|
|
});
|
|
|
|
it('should set up active servers subscription', () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
expect(mockSubscribeActiveServers).toHaveBeenCalledWith(expect.any(Function));
|
|
});
|
|
|
|
it('should stop subscriptions when going to background and restart when returning to active', () => {
|
|
const mockAppStateListener = {remove: jest.fn()};
|
|
const mockNetInfoUnsubscriber = jest.fn();
|
|
const mockActiveServersUnsubscriber = {unsubscribe: jest.fn()};
|
|
|
|
mockAppState.addEventListener.mockReturnValue(mockAppStateListener as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockNetInfo.addEventListener.mockReturnValue(mockNetInfoUnsubscriber);
|
|
mockSubscribeActiveServers.mockReturnValue(mockActiveServersUnsubscriber as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const appStateCallback = mockAppState.addEventListener.mock.calls[0][1];
|
|
|
|
appStateCallback('background');
|
|
|
|
expect(mockNetInfoUnsubscriber).toHaveBeenCalled();
|
|
expect(mockActiveServersUnsubscriber.unsubscribe).toHaveBeenCalled();
|
|
expect(mockAppStateListener.remove).not.toHaveBeenCalled();
|
|
|
|
mockNetInfo.addEventListener.mockClear();
|
|
mockSubscribeActiveServers.mockClear();
|
|
|
|
appStateCallback('active');
|
|
|
|
expect(mockNetInfo.addEventListener).toHaveBeenCalled();
|
|
expect(mockSubscribeActiveServers).toHaveBeenCalled();
|
|
expect(mockAppStateListener.remove).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not restart subscriptions when app state does not change', () => {
|
|
const mockNetInfoUnsubscriber = jest.fn();
|
|
const mockActiveServersUnsubscriber = {unsubscribe: jest.fn()};
|
|
|
|
mockNetInfo.addEventListener.mockReturnValue(mockNetInfoUnsubscriber);
|
|
mockSubscribeActiveServers.mockReturnValue(mockActiveServersUnsubscriber as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const appStateCallback = mockAppState.addEventListener.mock.calls[0][1];
|
|
|
|
mockNetInfo.addEventListener.mockClear();
|
|
mockSubscribeActiveServers.mockClear();
|
|
|
|
appStateCallback('active');
|
|
|
|
expect(mockNetInfo.addEventListener).not.toHaveBeenCalled();
|
|
expect(mockSubscribeActiveServers).not.toHaveBeenCalled();
|
|
expect(mockNetInfoUnsubscriber).not.toHaveBeenCalled();
|
|
expect(mockActiveServersUnsubscriber.unsubscribe).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle net info changes', () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const netInfoCallback = mockNetInfo.addEventListener.mock.calls[0][0];
|
|
const mockNetInfoState: MockNetInfoState = {isInternetReachable: true};
|
|
netInfoCallback(mockNetInfoState as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockNetInfo.addEventListener).toHaveBeenCalledWith(expect.any(Function));
|
|
});
|
|
|
|
it('should handle active servers change with no servers', async () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback([] as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockNetworkConnectivityManager.setServerConnectionStatus).toHaveBeenCalledWith(false, null);
|
|
expect(mockNetworkConnectivityManager.shutdown).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle active servers change with servers', async () => {
|
|
const mockServers: MockServer[] = [
|
|
{url: 'https://server1.com', lastActiveAt: 1000},
|
|
{url: 'https://server2.com', lastActiveAt: 2000},
|
|
];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback(mockServers as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockNetworkConnectivityManager.setServerConnectionStatus).toHaveBeenCalledWith(true, 'https://server2.com');
|
|
expect(mockWebsocketManager.observeWebsocketState).toHaveBeenCalledWith('https://server2.com');
|
|
expect(mockNetworkPerformanceManager.observePerformanceState).toHaveBeenCalledWith('https://server2.com');
|
|
});
|
|
|
|
});
|
|
|
|
describe('stopNetworkConnectivitySubscriptions', () => {
|
|
it('should clean up subscriptions but preserve AppState listener', async () => {
|
|
const mockAppStateListener = {remove: jest.fn()};
|
|
const mockNetInfoUnsubscriber = jest.fn();
|
|
const mockActiveServersUnsubscriber = {unsubscribe: jest.fn()};
|
|
const mockWebsocketSubscriptionForCleanup = {unsubscribe: jest.fn()};
|
|
const mockPerformanceSubscriptionForCleanup = {unsubscribe: jest.fn()};
|
|
|
|
mockAppState.addEventListener.mockReturnValue(mockAppStateListener as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockNetInfo.addEventListener.mockReturnValue(mockNetInfoUnsubscriber);
|
|
mockSubscribeActiveServers.mockReturnValue(mockActiveServersUnsubscriber as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockWebsocketManager.observeWebsocketState.mockReturnValue({
|
|
subscribe: jest.fn(() => mockWebsocketSubscriptionForCleanup),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockNetworkPerformanceManager.observePerformanceState.mockReturnValue({
|
|
subscribe: jest.fn(() => mockPerformanceSubscriptionForCleanup),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
// Simulate active servers to create websocket subscription
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback([{url: 'https://test.com', lastActiveAt: 1000}] as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
stopNetworkConnectivitySubscriptions();
|
|
|
|
expect(mockAppStateListener.remove).not.toHaveBeenCalled();
|
|
expect(mockNetInfoUnsubscriber).toHaveBeenCalled();
|
|
expect(mockActiveServersUnsubscriber.unsubscribe).toHaveBeenCalled();
|
|
expect(mockWebsocketSubscriptionForCleanup.unsubscribe).toHaveBeenCalled();
|
|
expect(mockPerformanceSubscriptionForCleanup.unsubscribe).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should be safe to call multiple times', () => {
|
|
const mockAppStateListener = {remove: jest.fn()};
|
|
const mockNetInfoUnsubscriber = jest.fn();
|
|
const mockActiveServersUnsubscriber = {unsubscribe: jest.fn()};
|
|
|
|
mockAppState.addEventListener.mockReturnValue(mockAppStateListener as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockNetInfo.addEventListener.mockReturnValue(mockNetInfoUnsubscriber);
|
|
mockSubscribeActiveServers.mockReturnValue(mockActiveServersUnsubscriber as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
stopNetworkConnectivitySubscriptions();
|
|
|
|
// Clear mock call counts
|
|
mockAppStateListener.remove.mockClear();
|
|
mockNetInfoUnsubscriber.mockClear();
|
|
mockActiveServersUnsubscriber.unsubscribe.mockClear();
|
|
|
|
// Call stop again - should not throw and should handle gracefully
|
|
expect(() => stopNetworkConnectivitySubscriptions()).not.toThrow();
|
|
|
|
// Verify cleanup methods are not called again (they should be no-ops)
|
|
expect(mockAppStateListener.remove).not.toHaveBeenCalled();
|
|
expect(mockNetInfoUnsubscriber).not.toHaveBeenCalled();
|
|
expect(mockActiveServersUnsubscriber.unsubscribe).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('websocket subscription handling', () => {
|
|
it('should subscribe to websocket state changes', async () => {
|
|
const mockServers: MockServer[] = [{url: 'https://test.com', lastActiveAt: 1000}];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback(mockServers as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockWebsocketManager.observeWebsocketState).toHaveBeenCalledWith('https://test.com');
|
|
});
|
|
|
|
it('should call updateState when websocket state changes', async () => {
|
|
let websocketCallback: ((state: string) => void) | undefined;
|
|
mockWebsocketManager.observeWebsocketState.mockReturnValue({
|
|
subscribe: jest.fn((callback: (state: string) => void) => {
|
|
websocketCallback = callback;
|
|
return mockWebsocketSubscription;
|
|
}),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
const mockServers: MockServer[] = [{url: 'https://test.com', lastActiveAt: 1000}];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback(mockServers as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(websocketCallback).toBeDefined();
|
|
websocketCallback!('connected');
|
|
|
|
expect(mockNetworkConnectivityManager.updateState).toHaveBeenCalledWith(
|
|
'connected',
|
|
{isInternetReachable: null},
|
|
'active',
|
|
);
|
|
});
|
|
|
|
it('should unsubscribe from previous websocket subscription when servers change', async () => {
|
|
const mockServers1: MockServer[] = [{url: 'https://server1.com', lastActiveAt: 1000}];
|
|
const mockServers2: MockServer[] = [{url: 'https://server2.com', lastActiveAt: 2000}];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
|
|
await serversCallback(mockServers1 as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
expect(mockWebsocketManager.observeWebsocketState).toHaveBeenCalledWith('https://server1.com');
|
|
|
|
await serversCallback(mockServers2 as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
expect(mockWebsocketSubscription.unsubscribe).toHaveBeenCalled();
|
|
expect(mockWebsocketManager.observeWebsocketState).toHaveBeenCalledWith('https://server2.com');
|
|
});
|
|
});
|
|
|
|
describe('performance subscription handling', () => {
|
|
it('should subscribe to performance state changes', async () => {
|
|
const mockServers: MockServer[] = [{url: 'https://test.com', lastActiveAt: 1000}];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback(mockServers as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockNetworkPerformanceManager.observePerformanceState).toHaveBeenCalledWith('https://test.com');
|
|
});
|
|
|
|
it('should call updatePerformanceState when performance state changes', async () => {
|
|
let performanceCallback: ((state: string) => void) | undefined;
|
|
mockNetworkPerformanceManager.observePerformanceState.mockReturnValue({
|
|
subscribe: jest.fn((callback: (state: string) => void) => {
|
|
performanceCallback = callback;
|
|
return mockPerformanceSubscription;
|
|
}),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
const mockServers: MockServer[] = [{url: 'https://test.com', lastActiveAt: 1000}];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback(mockServers as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(performanceCallback).toBeDefined();
|
|
performanceCallback!('slow');
|
|
|
|
expect(mockNetworkConnectivityManager.updatePerformanceState).toHaveBeenCalledWith('slow');
|
|
});
|
|
});
|
|
|
|
describe('edge cases', () => {
|
|
it('should find most recent server when first server is more recent', async () => {
|
|
const mockServers: MockServer[] = [
|
|
{url: 'https://server1.com', lastActiveAt: 2000},
|
|
{url: 'https://server2.com', lastActiveAt: 1000},
|
|
];
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback(mockServers as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockNetworkConnectivityManager.setServerConnectionStatus).toHaveBeenCalledWith(true, 'https://server1.com');
|
|
expect(mockWebsocketManager.observeWebsocketState).toHaveBeenCalledWith('https://server1.com');
|
|
});
|
|
|
|
it('should reinitialize when app becomes active after subscriptions were cleared', () => {
|
|
const mockAppStateListener = {remove: jest.fn()};
|
|
const mockNetInfoUnsubscriber = jest.fn();
|
|
const mockActiveServersUnsubscriber = {unsubscribe: jest.fn()};
|
|
|
|
mockAppState.addEventListener.mockReturnValue(mockAppStateListener as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockNetInfo.addEventListener.mockReturnValue(mockNetInfoUnsubscriber);
|
|
mockSubscribeActiveServers.mockReturnValue(mockActiveServersUnsubscriber as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const appStateCallback = mockAppState.addEventListener.mock.calls[0][1];
|
|
|
|
mockNetInfo.addEventListener.mockClear();
|
|
mockSubscribeActiveServers.mockClear();
|
|
|
|
appStateCallback('background');
|
|
|
|
expect(mockNetInfoUnsubscriber).toHaveBeenCalled();
|
|
expect(mockActiveServersUnsubscriber.unsubscribe).toHaveBeenCalled();
|
|
|
|
mockNetInfo.addEventListener.mockClear();
|
|
mockSubscribeActiveServers.mockClear();
|
|
|
|
appStateCallback('active');
|
|
|
|
expect(mockNetInfo.addEventListener).toHaveBeenCalled();
|
|
expect(mockSubscribeActiveServers).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not reinitialize when transitioning to active if subscriptions exist', async () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const appStateCallback = mockAppState.addEventListener.mock.calls[0][1];
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
|
|
await serversCallback([{url: 'https://test.com', lastActiveAt: 1000}] as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
mockNetInfo.addEventListener.mockClear();
|
|
mockSubscribeActiveServers.mockClear();
|
|
|
|
appStateCallback('active');
|
|
|
|
expect(mockNetInfo.addEventListener).not.toHaveBeenCalled();
|
|
expect(mockSubscribeActiveServers).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle netInfo with undefined isInternetReachable', () => {
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
const netInfoCallback = mockNetInfo.addEventListener.mock.calls[0][0];
|
|
const mockNetInfoState = {} as MockNetInfoState;
|
|
netInfoCallback(mockNetInfoState as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
expect(mockNetInfo.addEventListener).toHaveBeenCalledWith(expect.any(Function));
|
|
});
|
|
});
|
|
|
|
describe('shutdownNetworkConnectivitySubscriptions', () => {
|
|
it('should clean up all subscriptions including AppState listener', async () => {
|
|
const mockAppStateListener = {remove: jest.fn()};
|
|
const mockNetInfoUnsubscriber = jest.fn();
|
|
const mockActiveServersUnsubscriber = {unsubscribe: jest.fn()};
|
|
const mockWebsocketSubscriptionForCleanup = {unsubscribe: jest.fn()};
|
|
const mockPerformanceSubscriptionForCleanup = {unsubscribe: jest.fn()};
|
|
|
|
mockAppState.addEventListener.mockReturnValue(mockAppStateListener as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
mockNetInfo.addEventListener.mockReturnValue(mockNetInfoUnsubscriber);
|
|
mockSubscribeActiveServers.mockReturnValue(mockActiveServersUnsubscriber as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
mockWebsocketManager.observeWebsocketState.mockReturnValue({
|
|
subscribe: jest.fn(() => mockWebsocketSubscriptionForCleanup),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
mockNetworkPerformanceManager.observePerformanceState.mockReturnValue({
|
|
subscribe: jest.fn(() => mockPerformanceSubscriptionForCleanup),
|
|
} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
startNetworkConnectivitySubscriptions();
|
|
|
|
// Simulate active servers to create websocket subscription
|
|
const serversCallback = mockSubscribeActiveServers.mock.calls[0][0];
|
|
await serversCallback([{url: 'https://test.com', lastActiveAt: 1000}] as any); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
|
|
shutdownNetworkConnectivitySubscriptions();
|
|
|
|
expect(mockAppStateListener.remove).toHaveBeenCalled();
|
|
expect(mockNetInfoUnsubscriber).toHaveBeenCalled();
|
|
expect(mockActiveServersUnsubscriber.unsubscribe).toHaveBeenCalled();
|
|
expect(mockWebsocketSubscriptionForCleanup.unsubscribe).toHaveBeenCalled();
|
|
expect(mockPerformanceSubscriptionForCleanup.unsubscribe).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|