* fix: skip flaky playIncomingCallsRinging test in calls state Skip the playIncomingCallsRinging test that has been causing intermittent failures. Added TODO comment to track that the root cause still needs to be identified. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * add link to ticket that should fix the test --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1743 lines
64 KiB
TypeScript
1743 lines
64 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
/* eslint-disable max-lines */
|
|
|
|
import assert from 'assert';
|
|
|
|
import {act, renderHook} from '@testing-library/react-hooks'; // Use instead of react-native version due to different behavior. Consider migrating
|
|
import {AppState} from 'react-native';
|
|
|
|
import {needsRecordingAlert} from '@calls/alerts';
|
|
import {
|
|
newCurrentCall,
|
|
processIncomingCalls,
|
|
processMeanOpinionScore,
|
|
receivedCaption,
|
|
removeIncomingCall,
|
|
setAudioDeviceInfo,
|
|
setCallQualityAlertDismissed,
|
|
setCallsConfig,
|
|
setCallsState,
|
|
setChannelsWithCalls,
|
|
setCurrentCall,
|
|
setHost,
|
|
setIncomingCalls,
|
|
setJoiningChannelId,
|
|
setMicPermissionsErrorDismissed,
|
|
setMicPermissionsGranted,
|
|
setRecordingState,
|
|
useCallsConfig,
|
|
useCallsState,
|
|
useChannelsWithCalls,
|
|
setCurrentCallConnected,
|
|
useCurrentCall,
|
|
useGlobalCallsState,
|
|
useIncomingCalls,
|
|
userReacted,
|
|
setCallForChannel,
|
|
} from '@calls/state';
|
|
import {
|
|
callEnded,
|
|
callStarted,
|
|
myselfLeftCall,
|
|
setCalls,
|
|
setCallScreenOff,
|
|
setCallScreenOn,
|
|
setChannelEnabled,
|
|
setConfig,
|
|
setPluginEnabled,
|
|
setRaisedHand,
|
|
setScreenShareURL,
|
|
setSpeakerPhone,
|
|
setUserMuted,
|
|
setUserVoiceOn,
|
|
userJoinedCall,
|
|
userLeftCall,
|
|
callsOnAppStateChange,
|
|
playIncomingCallsRinging,
|
|
} from '@calls/state/actions';
|
|
import {
|
|
AudioDevice,
|
|
type Call,
|
|
type CallsState,
|
|
type CurrentCall,
|
|
DefaultCallsConfig,
|
|
DefaultCallsState,
|
|
DefaultCurrentCall,
|
|
DefaultGlobalCallsState,
|
|
DefaultIncomingCalls,
|
|
type GlobalCallsState,
|
|
type IncomingCalls,
|
|
} from '@calls/types/calls';
|
|
import {License} from '@constants';
|
|
import Calls from '@constants/calls';
|
|
import DatabaseManager from '@database/manager';
|
|
import {getUserById} from '@queries/servers/user';
|
|
import TestHelper from '@test/test_helper';
|
|
|
|
import type {CallJobState, LiveCaptionData} from '@mattermost/calls/lib/types';
|
|
|
|
jest.mock('@calls/alerts');
|
|
|
|
jest.mock('@constants/calls', () => ({
|
|
...jest.requireActual('@constants/calls'),
|
|
CALL_QUALITY_RESET_MS: 100,
|
|
}));
|
|
|
|
jest.mock('@actions/remote/thread', () => ({
|
|
updateThreadFollowing: jest.fn(() => Promise.resolve({})),
|
|
}));
|
|
|
|
jest.mock('@queries/servers/thread', () => ({
|
|
getThreadById: jest.fn(() => Promise.resolve({
|
|
isFollowing: false,
|
|
})),
|
|
}));
|
|
|
|
jest.mock('@queries/servers/channel', () => ({
|
|
getChannelById: jest.fn(() => Promise.resolve({
|
|
type: 'D',
|
|
})),
|
|
}));
|
|
|
|
jest.mock('@queries/servers/user', () => ({
|
|
getUserById: jest.fn(),
|
|
getCurrentUser: jest.fn(),
|
|
}));
|
|
|
|
const user5 = TestHelper.fakeUserModel({username: 'user-5'});
|
|
jest.mocked(getUserById).mockResolvedValue(user5);
|
|
|
|
jest.mock('react-native-navigation', () => ({
|
|
Navigation: {
|
|
pop: jest.fn(() => Promise.resolve({
|
|
catch: jest.fn(),
|
|
})),
|
|
setDefaultOptions: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
const call1: Call = {
|
|
id: 'call1',
|
|
sessions: {
|
|
session1: {sessionId: 'session1', userId: 'user-1', muted: false, raisedHand: 0},
|
|
session2: {sessionId: 'session2', userId: 'user-2', muted: true, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-1',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-1',
|
|
ownerId: 'user-1',
|
|
hostId: 'user-1',
|
|
dismissed: {},
|
|
};
|
|
const call2: Call = {
|
|
id: 'call2',
|
|
sessions: {
|
|
session3: {sessionId: 'session3', userId: 'user-3', muted: false, raisedHand: 0},
|
|
session4: {sessionId: 'session4', userId: 'user-4', muted: true, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-2',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-2',
|
|
ownerId: 'user-3',
|
|
hostId: 'user-3',
|
|
dismissed: {},
|
|
};
|
|
const call3: Call = {
|
|
id: 'call3',
|
|
sessions: {
|
|
session5: {sessionId: 'session5', userId: 'user-5', muted: false, raisedHand: 0},
|
|
session6: {sessionId: 'session6', userId: 'user-6', muted: true, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-3',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-3',
|
|
ownerId: 'user-5',
|
|
hostId: 'user-5',
|
|
dismissed: {},
|
|
};
|
|
const callDM: Call = {
|
|
id: 'callDM',
|
|
sessions: {
|
|
session5: {sessionId: 'session5', userId: 'user-5', muted: false, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-private',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-4',
|
|
ownerId: 'user-5',
|
|
hostId: 'user-5',
|
|
dismissed: {},
|
|
};
|
|
|
|
describe('useCallsState', () => {
|
|
const {updateThreadFollowing} = require('@actions/remote/thread');
|
|
|
|
beforeAll(() => {
|
|
// create subjects
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
|
});
|
|
|
|
assert.deepEqual(result.current[0], DefaultCallsState);
|
|
assert.deepEqual(result.current[1], {});
|
|
assert.deepEqual(result.current[2], null);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
// reset to default state for each test
|
|
updateThreadFollowing.mockClear();
|
|
|
|
act(() => {
|
|
setCallsState('server1', DefaultCallsState);
|
|
setChannelsWithCalls('server1', {});
|
|
setCurrentCall(null);
|
|
});
|
|
});
|
|
|
|
it('default state', () => {
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1')];
|
|
});
|
|
assert.deepEqual(result.current[0], DefaultCallsState);
|
|
assert.deepEqual(result.current[1], {});
|
|
});
|
|
|
|
it('setCalls, two callsState hooks, channelsWithCalls hook, ', async () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1},
|
|
enabled: {'channel-1': true},
|
|
};
|
|
const initialChannelsWithCallsState = {
|
|
'channel-1': true,
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const testNewCall1 = {
|
|
...call1,
|
|
sessions: {
|
|
session1: {sessionId: 'session1', userId: 'user-1', muted: false, raisedHand: 0},
|
|
session2: {sessionId: 'session2', userId: 'user-2', muted: true, raisedHand: 0},
|
|
session3: {sessionId: 'session3', userId: 'user-3', muted: false, raisedHand: 123},
|
|
},
|
|
};
|
|
const test = {
|
|
calls: {'channel-1': testNewCall1, 'channel-2': call2, 'channel-3': call3},
|
|
enabled: {'channel-2': true},
|
|
};
|
|
|
|
const expectedCallsState = {
|
|
...initialCallsState,
|
|
myUserId: 'myId',
|
|
calls: {'channel-1': testNewCall1, 'channel-2': call2, 'channel-3': call3},
|
|
enabled: {'channel-2': true},
|
|
};
|
|
const expectedChannelsWithCallsState = {
|
|
...initialChannelsWithCallsState,
|
|
'channel-2': true,
|
|
'channel-3': true,
|
|
};
|
|
const expectedCurrentCallState = {
|
|
...initialCurrentCallState,
|
|
...testNewCall1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [
|
|
useCallsState('server1'),
|
|
useCallsState('server1'),
|
|
useChannelsWithCalls('server1'),
|
|
useCurrentCall(),
|
|
];
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCallsState);
|
|
assert.deepEqual(result.current[2], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[3], initialCurrentCallState);
|
|
|
|
// test
|
|
await act(async () => setCalls('server1', 'myId', test.calls, test.enabled));
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedCallsState);
|
|
assert.deepEqual(result.current[2], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[3], expectedCurrentCallState);
|
|
});
|
|
|
|
it('joinedCall', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1},
|
|
};
|
|
const initialChannelsWithCallsState = {
|
|
'channel-1': true,
|
|
};
|
|
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const expectedCallsState = {
|
|
'channel-1': {
|
|
id: 'call1',
|
|
sessions: {
|
|
session1: {sessionId: 'session1', userId: 'user-1', muted: false, raisedHand: 0},
|
|
session2: {sessionId: 'session2', userId: 'user-2', muted: true, raisedHand: 0},
|
|
session3: {sessionId: 'session3', userId: 'user-3', muted: true, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-1',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-1',
|
|
ownerId: 'user-1',
|
|
hostId: 'user-1',
|
|
dismissed: {},
|
|
},
|
|
};
|
|
const expectedChannelsWithCallsState = initialChannelsWithCallsState;
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...initialCurrentCallState,
|
|
...expectedCallsState['channel-1'],
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => userJoinedCall('server1', 'channel-1', 'user-3', 'session3'));
|
|
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
|
act(() => userJoinedCall('server1', 'invalid-channel', 'user-1', 'session1'));
|
|
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
|
});
|
|
|
|
it('leftCall', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1},
|
|
};
|
|
const initialChannelsWithCallsState = {
|
|
'channel-1': true,
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const expectedCallsState = {
|
|
'channel-1': {
|
|
id: 'call1',
|
|
sessions: {
|
|
session2: {sessionId: 'session2', userId: 'user-2', muted: true, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-1',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-1',
|
|
ownerId: 'user-1',
|
|
hostId: 'user-1',
|
|
dismissed: {},
|
|
},
|
|
};
|
|
const expectedChannelsWithCallsState = initialChannelsWithCallsState;
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...initialCurrentCallState,
|
|
...expectedCallsState['channel-1'],
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => userLeftCall('server1', 'channel-1', 'session1'));
|
|
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
|
act(() => userLeftCall('server1', 'invalid-channel', 'session2'));
|
|
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
|
});
|
|
|
|
it('leftCall with screensharing on', () => {
|
|
const initialCallsState: CallsState = {
|
|
...DefaultCallsState,
|
|
calls: {
|
|
'channel-1': {
|
|
...call1,
|
|
screenOn: 'session1',
|
|
},
|
|
},
|
|
};
|
|
const initialChannelsWithCallsState = {
|
|
'channel-1': true,
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
screenOn: 'session1',
|
|
};
|
|
const expectedCallsState = {
|
|
'channel-1': {
|
|
id: 'call1',
|
|
sessions: {
|
|
session2: {sessionId: 'session2', userId: 'user-2', muted: true, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-1',
|
|
startTime: 123,
|
|
threadId: 'thread-1',
|
|
ownerId: 'user-1',
|
|
hostId: 'user-1',
|
|
screenOn: '',
|
|
dismissed: {},
|
|
},
|
|
};
|
|
const expectedChannelsWithCallsState = initialChannelsWithCallsState;
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...initialCurrentCallState,
|
|
...expectedCallsState['channel-1'],
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => userLeftCall('server1', 'channel-1', 'session1'));
|
|
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
|
});
|
|
|
|
it('callStarted', async () => {
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: false,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
|
|
// setup
|
|
await DatabaseManager.init(['server1']);
|
|
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
assert.deepEqual(result.current[0], DefaultCallsState);
|
|
assert.deepEqual(result.current[1], {});
|
|
assert.deepEqual(result.current[2], null);
|
|
|
|
// test
|
|
await act(async () => {
|
|
setCurrentCall(initialCurrentCallState);
|
|
await callStarted('server1', call1);
|
|
});
|
|
assert.deepEqual(result.current[0].calls, {'channel-1': call1});
|
|
assert.deepEqual(result.current[1], {'channel-1': true});
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
expect(updateThreadFollowing).toBeCalled();
|
|
});
|
|
|
|
it('callEnded', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialChannelsWithCallsState = {'channel-1': true, 'channel-2': true};
|
|
const expectedCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-2': call2},
|
|
};
|
|
const expectedChannelsWithCallsState = {'channel-2': true};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], null);
|
|
|
|
// test
|
|
act(() => callEnded('server1', 'channel-1'));
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], null);
|
|
});
|
|
|
|
it('setUserMuted', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialChannelsWithCallsState = {'channel-1': true, 'channel-2': true};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setUserMuted('server1', 'channel-1', 'session1', true));
|
|
assert.deepEqual((result.current[0]).calls['channel-1'].sessions.session1.muted, true);
|
|
assert.deepEqual((result.current[2])?.sessions.session1.muted, true);
|
|
act(() => {
|
|
setUserMuted('server1', 'channel-1', 'session1', false);
|
|
setUserMuted('server1', 'channel-1', 'session2', false);
|
|
});
|
|
assert.deepEqual((result.current[0]).calls['channel-1'].sessions.session1.muted, false);
|
|
assert.deepEqual((result.current[0]).calls['channel-1'].sessions.session2.muted, false);
|
|
assert.deepEqual((result.current[2])?.sessions.session1.muted, false);
|
|
assert.deepEqual((result.current[2])?.sessions.session2.muted, false);
|
|
act(() => setUserMuted('server1', 'channel-1', 'session2', true));
|
|
assert.deepEqual((result.current[0]).calls['channel-1'].sessions.session2.muted, true);
|
|
assert.deepEqual((result.current[2])?.sessions.session2.muted, true);
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
act(() => setUserMuted('server1', 'invalid-channel', 'session1', true));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
});
|
|
|
|
it('setCallScreenOn/Off', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialChannelsWithCallsState = {'channel-1': true, 'channel-2': true};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setChannelsWithCalls('server1', initialChannelsWithCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setCallScreenOn('server1', 'channel-1', 'session1'));
|
|
assert.deepEqual((result.current[0]).calls['channel-1'].screenOn, 'session1');
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual((result.current[2])?.screenOn, 'session1');
|
|
act(() => setCallScreenOff('server1', 'channel-1', 'session1'));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
act(() => setCallScreenOn('server1', 'channel-1', 'invalid-user'));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
act(() => setCallScreenOff('server1', 'invalid-channel', 'session1'));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
});
|
|
|
|
it('setRaisedHand', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1},
|
|
};
|
|
const expectedCalls = {
|
|
'channel-1': {
|
|
id: 'call1',
|
|
sessions: {
|
|
session1: {sessionId: 'session1', userId: 'user-1', muted: false, raisedHand: 0},
|
|
session2: {sessionId: 'session2', userId: 'user-2', muted: true, raisedHand: 345},
|
|
},
|
|
channelId: 'channel-1',
|
|
startTime: 123,
|
|
screenOn: false,
|
|
threadId: 'thread-1',
|
|
ownerId: 'user-1',
|
|
hostId: 'user-1',
|
|
dismissed: {},
|
|
},
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const expectedCurrentCallState = {
|
|
...initialCurrentCallState,
|
|
...expectedCalls['channel-1'],
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setRaisedHand('server1', 'channel-1', 'session2', 345));
|
|
assert.deepEqual((result.current[0]).calls, expectedCalls);
|
|
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
|
|
|
act(() => setRaisedHand('server1', 'invalid-channel', 'session1', 345));
|
|
assert.deepEqual((result.current[0]).calls, expectedCalls);
|
|
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
|
|
|
// unraise hand:
|
|
act(() => setRaisedHand('server1', 'channel-1', 'session2', 0));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
});
|
|
|
|
it('myselfJoinedCall / LeftCall', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const newCall1 = {
|
|
...call1,
|
|
sessions: {
|
|
...call1.sessions,
|
|
mySessionId: {sessionId: 'mySessionId', userId: 'myUserId', muted: true, raisedHand: 0},
|
|
},
|
|
};
|
|
const expectedCallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': newCall1,
|
|
},
|
|
};
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
mySessionId: 'mySessionId',
|
|
...newCall1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()];
|
|
});
|
|
act(() => setCallsState('server1', initialCallsState));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
|
|
// test
|
|
act(() => {
|
|
newCurrentCall('server1', 'channel-1', 'myUserId');
|
|
userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId');
|
|
});
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedCurrentCallState);
|
|
|
|
act(() => {
|
|
myselfLeftCall();
|
|
userLeftCall('server1', 'channel-1', 'mySessionId');
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
});
|
|
|
|
it('setChannelEnabled', async () => {
|
|
const initialState = {
|
|
...DefaultCallsState,
|
|
enabled: {'channel-1': true, 'channel-2': false},
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => useCallsState('server1'));
|
|
await act(async () => setCallsState('server1', initialState));
|
|
assert.deepEqual(result.current, initialState);
|
|
|
|
// test setCalls affects enabled:
|
|
await act(async () => setCalls('server1', 'myUserId', {}, {'channel-1': true}));
|
|
assert.deepEqual(result.current.enabled, {'channel-1': true});
|
|
|
|
// re-setup:
|
|
await act(async () => setCallsState('server1', initialState));
|
|
assert.deepEqual(result.current, initialState);
|
|
|
|
// test setChannelEnabled affects enabled:
|
|
await act(async () => setChannelEnabled('server1', 'channel-3', true));
|
|
assert.deepEqual(result.current.enabled, {'channel-1': true, 'channel-2': false, 'channel-3': true});
|
|
await act(async () => setChannelEnabled('server1', 'channel-3', false));
|
|
assert.deepEqual(result.current.enabled, {
|
|
'channel-1': true,
|
|
'channel-2': false,
|
|
'channel-3': false,
|
|
});
|
|
await act(async () => setChannelEnabled('server1', 'channel-1', true));
|
|
assert.deepEqual(result.current.enabled, {
|
|
'channel-1': true,
|
|
'channel-2': false,
|
|
'channel-3': false,
|
|
});
|
|
await act(async () => setChannelEnabled('server1', 'channel-1', false));
|
|
assert.deepEqual(result.current.enabled, {
|
|
'channel-1': false,
|
|
'channel-2': false,
|
|
'channel-3': false,
|
|
});
|
|
});
|
|
|
|
it('setScreenShareURL', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => setCallsState('server1', initialCallsState));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
|
|
// test joining a call and setting url:
|
|
act(() => newCurrentCall('server1', 'channel-1', 'myUserId'));
|
|
act(() => userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId'));
|
|
assert.deepEqual((result.current[1])?.screenShareURL, '');
|
|
act(() => setScreenShareURL('testUrl'));
|
|
assert.deepEqual((result.current[1])?.screenShareURL, 'testUrl');
|
|
|
|
act(() => {
|
|
myselfLeftCall();
|
|
userLeftCall('server1', 'channel-1', 'mySessionId');
|
|
setScreenShareURL('test');
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
});
|
|
|
|
it('setSpeakerPhoneOn', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const newCall1 = {
|
|
...call1,
|
|
sessions: {
|
|
...call1.sessions,
|
|
mySessionId: {sessionId: 'mySessionId', userId: 'myUserId', muted: true, raisedHand: 0},
|
|
},
|
|
};
|
|
const expectedCallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': newCall1,
|
|
},
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => setCallsState('server1', initialCallsState));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
|
|
// test
|
|
act(() => newCurrentCall('server1', 'channel-1', 'myUserId'));
|
|
act(() => userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId'));
|
|
assert.deepEqual((result.current[1])?.speakerphoneOn, false);
|
|
act(() => setSpeakerPhone(true));
|
|
assert.deepEqual((result.current[1])?.speakerphoneOn, true);
|
|
act(() => setSpeakerPhone(false));
|
|
assert.deepEqual((result.current[1])?.speakerphoneOn, false);
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
act(() => {
|
|
myselfLeftCall();
|
|
setSpeakerPhone(true);
|
|
});
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
});
|
|
|
|
it('setAudioDeviceInfo', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const newCall1 = {
|
|
...call1,
|
|
sessions: {
|
|
...call1.sessions,
|
|
mySessionId: {sessionId: 'mySessionId', userId: 'myUserId', muted: true, raisedHand: 0},
|
|
},
|
|
};
|
|
const expectedCallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': newCall1,
|
|
},
|
|
};
|
|
|
|
const defaultAudioDeviceInfo = {
|
|
availableAudioDeviceList: [],
|
|
selectedAudioDevice: AudioDevice.None,
|
|
};
|
|
const newAudioDeviceInfo = {
|
|
availableAudioDeviceList: [AudioDevice.Speakerphone, AudioDevice.Earpiece],
|
|
selectedAudioDevice: AudioDevice.Speakerphone,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => setCallsState('server1', initialCallsState));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
|
|
// test
|
|
act(() => newCurrentCall('server1', 'channel-1', 'myUserId'));
|
|
act(() => userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId'));
|
|
assert.deepEqual((result.current[1])?.audioDeviceInfo, defaultAudioDeviceInfo);
|
|
act(() => setAudioDeviceInfo(newAudioDeviceInfo));
|
|
assert.deepEqual((result.current[1])?.audioDeviceInfo, newAudioDeviceInfo);
|
|
assert.deepEqual((result.current[1])?.speakerphoneOn, false);
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
act(() => {
|
|
myselfLeftCall();
|
|
});
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
});
|
|
|
|
it('MicPermissions', () => {
|
|
const initialGlobalState = DefaultGlobalCallsState;
|
|
const initialCallsState: CallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const newCall1: Call = {
|
|
...call1,
|
|
sessions: {
|
|
...call1.sessions,
|
|
mySessionId: {sessionId: 'mySessionId', userId: 'myUserId', muted: true, raisedHand: 0},
|
|
},
|
|
};
|
|
const expectedCallsState: CallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': newCall1,
|
|
},
|
|
};
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
mySessionId: 'mySessionId',
|
|
connected: true,
|
|
...newCall1,
|
|
};
|
|
const secondExpectedCurrentCallState: CurrentCall = {
|
|
...expectedCurrentCallState,
|
|
micPermissionsErrorDismissed: true,
|
|
};
|
|
const expectedGlobalState: GlobalCallsState = {
|
|
micPermissionsGranted: true,
|
|
joiningChannelId: null,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall(), useGlobalCallsState()];
|
|
});
|
|
act(() => setCallsState('server1', initialCallsState));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
assert.deepEqual(result.current[2], initialGlobalState);
|
|
|
|
// join call
|
|
act(() => {
|
|
setMicPermissionsGranted(false);
|
|
newCurrentCall('server1', 'channel-1', 'myUserId');
|
|
userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId');
|
|
});
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], expectedCurrentCallState);
|
|
assert.deepEqual(result.current[2], initialGlobalState);
|
|
|
|
// dismiss mic error
|
|
act(() => setMicPermissionsErrorDismissed());
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], secondExpectedCurrentCallState);
|
|
assert.deepEqual(result.current[2], initialGlobalState);
|
|
|
|
// grant permissions
|
|
act(() => setMicPermissionsGranted(true));
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], secondExpectedCurrentCallState);
|
|
assert.deepEqual(result.current[2], expectedGlobalState);
|
|
|
|
act(() => {
|
|
myselfLeftCall();
|
|
userLeftCall('server1', 'channel-1', 'mySessionId');
|
|
|
|
// reset state to default
|
|
setMicPermissionsGranted(false);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
});
|
|
|
|
it('joining call', () => {
|
|
const initialGlobalState = DefaultGlobalCallsState;
|
|
const expectedGlobalState: GlobalCallsState = {
|
|
...DefaultGlobalCallsState,
|
|
joiningChannelId: 'channel-1',
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useGlobalCallsState()];
|
|
});
|
|
|
|
// start joining call
|
|
act(() => setJoiningChannelId('channel-1'));
|
|
assert.deepEqual(result.current[0], expectedGlobalState);
|
|
|
|
// end joining call
|
|
act(() => setJoiningChannelId(null));
|
|
assert.deepEqual(result.current[0], initialGlobalState);
|
|
});
|
|
|
|
it('CallQuality', async () => {
|
|
const initialCallsState: CallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const newCall1: Call = {
|
|
...call1,
|
|
sessions: {
|
|
...call1.sessions,
|
|
mySessionId: {sessionId: 'mySessionId', userId: 'myUserId', muted: true, raisedHand: 0},
|
|
},
|
|
};
|
|
const expectedCallsState: CallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': newCall1,
|
|
},
|
|
};
|
|
const currentCallNoAlertNoDismissed: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
mySessionId: 'mySessionId',
|
|
connected: true,
|
|
...newCall1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => setCallsState('server1', initialCallsState));
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], null);
|
|
|
|
// join call
|
|
act(() => {
|
|
newCurrentCall('server1', 'channel-1', 'myUserId');
|
|
userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId');
|
|
});
|
|
assert.deepEqual(result.current[0], expectedCallsState);
|
|
assert.deepEqual(result.current[1], currentCallNoAlertNoDismissed);
|
|
|
|
// call quality goes bad
|
|
act(() => processMeanOpinionScore(3.4999));
|
|
assert.deepEqual((result.current[1])?.callQualityAlert, true);
|
|
assert.equal((result.current[1])?.callQualityAlertDismissed, 0);
|
|
|
|
// call quality goes good
|
|
act(() => processMeanOpinionScore(4));
|
|
assert.deepEqual(result.current[1], currentCallNoAlertNoDismissed);
|
|
|
|
// call quality goes bad
|
|
act(() => processMeanOpinionScore(3.499));
|
|
assert.deepEqual((result.current[1])?.callQualityAlert, true);
|
|
assert.equal((result.current[1])?.callQualityAlertDismissed, 0);
|
|
|
|
// dismiss call quality alert
|
|
const timeNow = Date.now();
|
|
act(() => setCallQualityAlertDismissed());
|
|
assert.deepEqual((result.current[1])?.callQualityAlert, false);
|
|
assert.equal((result.current[1]!).callQualityAlertDismissed >= timeNow &&
|
|
(result.current[1]!).callQualityAlertDismissed <= Date.now(), true);
|
|
|
|
// call quality goes bad, but we're not past the dismissed limit
|
|
act(() => processMeanOpinionScore(3.4999));
|
|
assert.deepEqual((result.current[1])?.callQualityAlert, false);
|
|
|
|
// test that the dismiss expired
|
|
await act(async () => {
|
|
await new Promise((r) => setTimeout(r, 101));
|
|
processMeanOpinionScore(3.499);
|
|
});
|
|
assert.deepEqual((result.current[1])?.callQualityAlert, true);
|
|
});
|
|
|
|
it('voiceOn and Off', async () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()];
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setUserVoiceOn('channel-1', 'session1', true));
|
|
assert.deepEqual(result.current[1], {...initialCurrentCallState, voiceOn: {session1: true}});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
act(() => setUserVoiceOn('channel-1', 'session2', true));
|
|
assert.deepEqual(result.current[1], {...initialCurrentCallState, voiceOn: {session1: true, session2: true}});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
act(() => setUserVoiceOn('channel-1', 'session1', false));
|
|
assert.deepEqual(result.current[1], {...initialCurrentCallState, voiceOn: {session2: true}});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
|
|
// test that voice state is cleared on reconnect
|
|
await act(() => setCalls('server1', 'myUserId', initialCallsState.calls, {}));
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
});
|
|
|
|
it('config', () => {
|
|
const newConfig = {
|
|
...DefaultCallsConfig,
|
|
ICEServers: [],
|
|
ICEServersConfigs: [
|
|
{
|
|
urls: ['stun:stun.example.com:3478'],
|
|
},
|
|
{
|
|
urls: ['turn:turn.example.com:3478'],
|
|
},
|
|
],
|
|
AllowEnableCalls: true,
|
|
DefaultEnabled: true,
|
|
NeedsTURNCredentials: false,
|
|
last_retrieved_at: 123,
|
|
sku_short_name: License.SKU_SHORT_NAME.Professional,
|
|
MaxCallParticipants: 8,
|
|
EnableRecordings: true,
|
|
bot_user_id: '',
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => useCallsConfig('server1'));
|
|
assert.deepEqual(result.current, DefaultCallsConfig);
|
|
|
|
// test
|
|
act(() => setConfig('server1', newConfig));
|
|
assert.deepEqual(result.current, {...newConfig, pluginEnabled: false});
|
|
act(() => setPluginEnabled('server1', true));
|
|
assert.deepEqual(result.current, {...newConfig, pluginEnabled: true});
|
|
act(() => setPluginEnabled('server1', false));
|
|
assert.deepEqual(result.current, {...newConfig, pluginEnabled: false});
|
|
});
|
|
|
|
it('user reactions', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...initialCurrentCallState,
|
|
reactionStream: [
|
|
{name: 'smile', latestTimestamp: 202, count: 1, literal: undefined},
|
|
{name: '+1', latestTimestamp: 145, count: 2, literal: undefined},
|
|
],
|
|
sessions: {
|
|
...initialCurrentCallState.sessions,
|
|
session1: {
|
|
...initialCurrentCallState.sessions.session1,
|
|
reaction: {
|
|
user_id: 'user-1',
|
|
session_id: 'session1',
|
|
emoji: {name: 'smile', unified: 'something'},
|
|
timestamp: 202,
|
|
},
|
|
},
|
|
session2: {
|
|
...initialCurrentCallState.sessions.session2,
|
|
reaction: {
|
|
user_id: 'user-2',
|
|
session_id: 'session2',
|
|
emoji: {name: '+1', unified: 'something'},
|
|
timestamp: 145,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()];
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => {
|
|
userReacted('server1', 'channel-1', {
|
|
user_id: 'user-2',
|
|
session_id: 'session2',
|
|
emoji: {name: '+1', unified: 'something'},
|
|
timestamp: 123,
|
|
});
|
|
userReacted('server1', 'channel-1', {
|
|
user_id: 'user-2',
|
|
session_id: 'session2',
|
|
emoji: {name: '+1', unified: 'something'},
|
|
timestamp: 145,
|
|
});
|
|
userReacted('server1', 'channel-1', {
|
|
user_id: 'user-1',
|
|
session_id: 'session1',
|
|
emoji: {name: 'smile', unified: 'something'},
|
|
timestamp: 202,
|
|
});
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], expectedCurrentCallState);
|
|
});
|
|
|
|
it('setRecordingState', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const recState: CallJobState = {
|
|
type: Calls.JOB_TYPE_RECORDING,
|
|
init_at: 123,
|
|
start_at: 231,
|
|
end_at: 345,
|
|
};
|
|
const expectedCallsState: CallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': {
|
|
...call1,
|
|
recState,
|
|
},
|
|
},
|
|
};
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
recState,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setRecordingState('server1', 'channel-1', recState));
|
|
assert.deepEqual((result.current[0]), expectedCallsState);
|
|
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
|
act(() => setRecordingState('server1', 'channel-2', recState));
|
|
assert.deepEqual((result.current[0]).calls['channel-2'], {...call2, recState});
|
|
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
|
act(() => setRecordingState('server1', 'channel-1', {...recState, start_at: recState.start_at + 1}));
|
|
expect(needsRecordingAlert).toBeCalled();
|
|
});
|
|
|
|
it('setHost', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const expectedCallsState: CallsState = {
|
|
...initialCallsState,
|
|
calls: {
|
|
...initialCallsState.calls,
|
|
'channel-1': {
|
|
...call1,
|
|
hostId: 'user-52',
|
|
},
|
|
},
|
|
};
|
|
const expectedCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
connected: true,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
hostId: 'user-52',
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setHost('server1', 'channel-1', 'user-52'));
|
|
assert.deepEqual((result.current[0]), expectedCallsState);
|
|
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
|
act(() => setHost('server1', 'channel-2', 'user-1923'));
|
|
assert.deepEqual((result.current[0]).calls['channel-2'], {...call2, hostId: 'user-1923'});
|
|
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
|
act(() => setHost('server1', 'channel-1', 'myUserId'));
|
|
expect(needsRecordingAlert).toBeCalled();
|
|
});
|
|
|
|
it('incoming calls', async () => {
|
|
const calls = {'channel-dm': callDM};
|
|
const afterLoadCallsState: CallsState = {
|
|
myUserId: 'myId',
|
|
calls,
|
|
enabled: {},
|
|
};
|
|
const initialCurrentCallState: CurrentCall | null = null;
|
|
const initialIncomingCalls = DefaultIncomingCalls;
|
|
const expectedIncomingCalls: IncomingCalls = {
|
|
...DefaultIncomingCalls,
|
|
incomingCalls: [{
|
|
callID: 'callDM',
|
|
callerID: 'user-5',
|
|
callerModel: user5,
|
|
channelID: 'channel-private',
|
|
myUserId: 'myId',
|
|
serverUrl: 'server1',
|
|
startAt: 123,
|
|
type: 0,
|
|
}],
|
|
};
|
|
const dismissedCalls = {
|
|
'channel-dm': {...callDM, dismissed: {myId: true}},
|
|
};
|
|
const callIStarted: Call = {
|
|
id: 'callIStartedid',
|
|
sessions: {
|
|
session5: {sessionId: 'session5', userId: 'user-5', muted: false, raisedHand: 0},
|
|
},
|
|
channelId: 'channel-private2',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-4',
|
|
ownerId: 'myId',
|
|
hostId: 'user-5',
|
|
dismissed: {},
|
|
};
|
|
const callImIn: Call = {
|
|
id: 'callImInId',
|
|
sessions: {},
|
|
channelId: 'channel-private2',
|
|
startTime: 123,
|
|
screenOn: '',
|
|
threadId: 'thread-4',
|
|
ownerId: 'user-5',
|
|
hostId: 'user-5',
|
|
dismissed: {},
|
|
};
|
|
const currentCallStateImIn: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myId',
|
|
...callImIn,
|
|
};
|
|
|
|
// setup
|
|
await DatabaseManager.init(['server1']);
|
|
const {result} = renderHook(() => {
|
|
return [
|
|
useCallsState('server1'),
|
|
useCurrentCall(),
|
|
useIncomingCalls(),
|
|
];
|
|
});
|
|
act(() => {
|
|
setCallsConfig('server1', {...DefaultCallsConfig, EnableRinging: true});
|
|
});
|
|
assert.deepEqual(result.current[0], DefaultCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
assert.deepEqual(result.current[2], initialIncomingCalls);
|
|
|
|
// test incoming call on load
|
|
await act(async () => setCalls('server1', 'myId', afterLoadCallsState.calls, {}));
|
|
assert.deepEqual(result.current[0], afterLoadCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
assert.deepEqual(result.current[2], expectedIncomingCalls);
|
|
|
|
// test dismissing (same path for manually dismissing, joining that call,
|
|
// or receiving ws event from dismissing/joining from another client)
|
|
act(() => removeIncomingCall('server1', 'callDM'));
|
|
assert.deepEqual(result.current[0], afterLoadCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
assert.deepEqual(result.current[2], DefaultIncomingCalls);
|
|
|
|
// test load call, but call has been dismissed
|
|
await act(async () => setCalls('server1', 'myId', dismissedCalls, {}));
|
|
assert.deepEqual(result.current[2], DefaultIncomingCalls);
|
|
|
|
// test load call, then load same call again (eg from ws event): should only have one notification
|
|
await act(async () => setCalls('server1', 'myId', afterLoadCallsState.calls, {}));
|
|
assert.deepEqual(result.current[2], expectedIncomingCalls);
|
|
await act(async () => processIncomingCalls('server1', [calls['channel-dm']]));
|
|
assert.deepEqual(result.current[2], expectedIncomingCalls);
|
|
|
|
// test received ws event for a call I started
|
|
await act(async () => processIncomingCalls('server1', [callIStarted]));
|
|
assert.deepEqual(result.current[2], expectedIncomingCalls);
|
|
|
|
// test received ws event for a call I am in
|
|
await act(async () => {
|
|
setCurrentCall(currentCallStateImIn);
|
|
await processIncomingCalls('server1', [callImIn]);
|
|
});
|
|
assert.deepEqual(result.current[1], currentCallStateImIn);
|
|
assert.deepEqual(result.current[2], expectedIncomingCalls);
|
|
});
|
|
|
|
// TODO: Flaky test - disabled until root cause is identified
|
|
// See https://mattermost.atlassian.net/browse/MM-67173
|
|
it.skip('playIncomingCallsRinging', async () => {
|
|
const initialIncomingCalls = {
|
|
...DefaultIncomingCalls,
|
|
incomingCalls: [{
|
|
callID: 'callDM',
|
|
callerID: 'user-5',
|
|
callerModel: TestHelper.fakeUserModel({username: 'user-5'}),
|
|
channelID: 'channel-private',
|
|
myUserId: 'myId',
|
|
serverUrl: 'server1',
|
|
startAt: 123,
|
|
type: 0,
|
|
}],
|
|
currentRingingCallId: undefined,
|
|
};
|
|
|
|
// setup
|
|
await DatabaseManager.init(['server1']);
|
|
const {result} = renderHook(() => useIncomingCalls());
|
|
await act(async () => {
|
|
await setIncomingCalls(initialIncomingCalls);
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
AppState.currentState = 'active';
|
|
|
|
const getCurrentUser = require('@queries/servers/user').getCurrentUser;
|
|
getCurrentUser.mockResolvedValueOnce({
|
|
id: 'user-5',
|
|
roles: 'user',
|
|
notifyProps: {
|
|
calls_mobile_sound: 'true',
|
|
calls_mobile_notification_sound: 'Calm',
|
|
},
|
|
});
|
|
|
|
// test: should not ring when in DND
|
|
await act(async () => {
|
|
await playIncomingCallsRinging('server1', 'call1', 'dnd');
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
|
|
// test: should not ring when in OOO
|
|
await act(async () => {
|
|
await playIncomingCallsRinging('server1', 'call1', 'ooo');
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
|
|
// test: should ring when online
|
|
await act(async () => {
|
|
await playIncomingCallsRinging('server1', 'call1', 'online');
|
|
});
|
|
assert.deepEqual(result.current, {
|
|
...initialIncomingCalls,
|
|
currentRingingCallId: 'call1',
|
|
callIdHasRung: {call1: true},
|
|
});
|
|
|
|
// test: should not ring for same call again
|
|
await act(async () => {
|
|
setIncomingCalls(initialIncomingCalls);
|
|
await playIncomingCallsRinging('server1', 'call1', 'online');
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
|
|
// test: should not ring when already ringing
|
|
await act(async () => {
|
|
setIncomingCalls({
|
|
...initialIncomingCalls,
|
|
currentRingingCallId: 'call2',
|
|
});
|
|
await playIncomingCallsRinging('server1', 'call3', 'online');
|
|
});
|
|
assert.deepEqual(result.current.currentRingingCallId, 'call2');
|
|
});
|
|
|
|
it('callsOnAppStateChange', async () => {
|
|
const initialIncomingCalls = {
|
|
...DefaultIncomingCalls,
|
|
currentRingingCallId: 'call1',
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => useIncomingCalls());
|
|
act(() => {
|
|
setIncomingCalls(initialIncomingCalls);
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
|
|
// test going to background
|
|
await act(async () => {
|
|
await callsOnAppStateChange('background');
|
|
});
|
|
assert.deepEqual(result.current, {...initialIncomingCalls, currentRingingCallId: undefined});
|
|
|
|
// test going to inactive
|
|
await act(async () => {
|
|
setIncomingCalls(initialIncomingCalls);
|
|
await callsOnAppStateChange('inactive');
|
|
await TestHelper.wait(100);
|
|
});
|
|
assert.deepEqual(result.current, {...initialIncomingCalls, currentRingingCallId: undefined});
|
|
|
|
// test going to active (should not change state)
|
|
await act(async () => {
|
|
setIncomingCalls(initialIncomingCalls);
|
|
await callsOnAppStateChange('active');
|
|
await TestHelper.wait(100);
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
|
|
// test previous state
|
|
await act(async () => {
|
|
setIncomingCalls(initialIncomingCalls);
|
|
await callsOnAppStateChange('active');
|
|
await TestHelper.wait(100);
|
|
});
|
|
assert.deepEqual(result.current, initialIncomingCalls);
|
|
});
|
|
|
|
it('setCallForChannel', async () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
calls: {'channel-1': call1},
|
|
enabled: {'channel-1': true},
|
|
};
|
|
const initialChannelsWithCalls = {'channel-1': true};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
|
});
|
|
await act(async () => {
|
|
await setCallsState('server1', initialCallsState);
|
|
await setChannelsWithCalls('server1', initialChannelsWithCalls);
|
|
await setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialChannelsWithCalls);
|
|
assert.deepEqual(result.current[2], initialCurrentCallState);
|
|
|
|
// test: add new call
|
|
await act(async () => setCallForChannel('server1', 'channel-2', call2, true));
|
|
assert.deepEqual(result.current[0], {
|
|
...initialCallsState,
|
|
calls: {...initialCallsState.calls, 'channel-2': call2},
|
|
enabled: {...initialCallsState.enabled, 'channel-2': true},
|
|
});
|
|
assert.deepEqual(result.current[1], {...initialChannelsWithCalls, 'channel-2': true});
|
|
|
|
// test: update existing call
|
|
const updatedCall1 = {...call1, screenOn: 'newScreen'};
|
|
await act(async () => setCallForChannel('server1', 'channel-1', updatedCall1));
|
|
assert.deepEqual(result.current[0].calls['channel-1'], updatedCall1);
|
|
assert.deepEqual(result.current[2], {...initialCurrentCallState, screenOn: 'newScreen'});
|
|
|
|
// test: remove call
|
|
await act(async () => setCallForChannel('server1', 'channel-1', undefined));
|
|
assert.deepEqual(result.current[0], {
|
|
...initialCallsState,
|
|
calls: {'channel-2': call2},
|
|
enabled: {'channel-1': true, 'channel-2': true},
|
|
});
|
|
assert.deepEqual(result.current[1], {'channel-2': true});
|
|
|
|
// test: just update enabled state
|
|
await act(async () => setCallForChannel('server1', 'channel-3', undefined, true));
|
|
assert.deepEqual(result.current[0].enabled['channel-3'], true);
|
|
assert.deepEqual(result.current[1], {'channel-2': true});
|
|
});
|
|
|
|
it('setCurrentCallConnected', () => {
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
connected: false,
|
|
mySessionId: '',
|
|
...call1,
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => useCurrentCall());
|
|
act(() => {
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current, initialCurrentCallState);
|
|
|
|
// test
|
|
act(() => setCurrentCallConnected('channel-1', 'session-test-id'));
|
|
assert.deepEqual(result.current, {
|
|
...initialCurrentCallState,
|
|
connected: true,
|
|
mySessionId: 'session-test-id',
|
|
});
|
|
|
|
// test with wrong channel ID (should not change state)
|
|
act(() => {
|
|
setCurrentCall(initialCurrentCallState);
|
|
setCurrentCallConnected('wrong-channel', 'session-test-id');
|
|
});
|
|
assert.deepEqual(result.current, initialCurrentCallState);
|
|
});
|
|
|
|
it('captions', () => {
|
|
const initialCallsState = {
|
|
...DefaultCallsState,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
calls: {'channel-1': call1, 'channel-2': call2},
|
|
};
|
|
const initialCurrentCallState: CurrentCall = {
|
|
...DefaultCurrentCall,
|
|
serverUrl: 'server1',
|
|
myUserId: 'myUserId',
|
|
...call1,
|
|
};
|
|
const caption1user1Data: LiveCaptionData = {
|
|
session_id: 'session1',
|
|
user_id: 'user-1',
|
|
channel_id: 'channel-1',
|
|
text: 'caption 1',
|
|
};
|
|
const caption2user1Data: LiveCaptionData = {
|
|
session_id: 'session1',
|
|
user_id: 'user-1',
|
|
channel_id: 'channel-1',
|
|
text: 'caption 2',
|
|
};
|
|
const caption3user1Data: LiveCaptionData = {
|
|
session_id: 'session1',
|
|
user_id: 'user-1',
|
|
channel_id: 'channel-1',
|
|
text: 'caption 3',
|
|
};
|
|
const caption1user2Data: LiveCaptionData = {
|
|
session_id: 'session2',
|
|
user_id: 'user-2',
|
|
channel_id: 'channel-1',
|
|
text: 'caption 1 user 2',
|
|
};
|
|
const caption2user2Data: LiveCaptionData = {
|
|
session_id: 'session2',
|
|
user_id: 'user-2',
|
|
channel_id: 'channel-1',
|
|
text: 'caption 2 user 2',
|
|
};
|
|
|
|
// setup
|
|
const {result} = renderHook(() => {
|
|
return [useCallsState('server1'), useCurrentCall()] as const;
|
|
});
|
|
act(() => {
|
|
setCallsState('server1', initialCallsState);
|
|
setCurrentCall(initialCurrentCallState);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
assert.deepEqual(result.current[1], initialCurrentCallState);
|
|
|
|
// test sending the first 2 captions for user 1, 1 caption for user 2
|
|
act(() => {
|
|
receivedCaption('server1', caption1user1Data);
|
|
receivedCaption('server1', caption2user1Data);
|
|
receivedCaption('server1', caption1user2Data);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
let currentCall = result.current[1];
|
|
assert.equal(currentCall?.captions.session1.text, 'caption 2');
|
|
assert.equal(currentCall?.captions.session2.text, 'caption 1 user 2');
|
|
|
|
// test sending the next captions for users 1 and 2
|
|
act(() => {
|
|
receivedCaption('server1', caption3user1Data);
|
|
receivedCaption('server1', caption2user2Data);
|
|
});
|
|
assert.deepEqual(result.current[0], initialCallsState);
|
|
currentCall = result.current[1];
|
|
assert.equal(currentCall?.captions.session1.text, 'caption 3');
|
|
assert.equal(currentCall?.captions.session2.text, 'caption 2 user 2');
|
|
});
|
|
});
|