mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-06 10:50:13 +00:00
733 lines
24 KiB
TypeScript
733 lines
24 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import assert from 'assert';
|
|
|
|
import {Alert} from 'react-native';
|
|
import {SelectedTrackType} from 'react-native-video';
|
|
|
|
import {CallCardState, CallPostStatus, type CallsConfigState, type CallSession, type CallsPostProps, DefaultCall, DefaultCallsConfig} from '@calls/types/calls';
|
|
import {License, Post, Preferences} from '@constants';
|
|
import {NOTIFICATION_SUB_TYPE} from '@constants/push_notification';
|
|
import TestHelper from '@test/test_helper';
|
|
|
|
import {
|
|
getICEServersConfigs,
|
|
getCallCardState,
|
|
getNumUsersInCall,
|
|
getCallPropsFromPost,
|
|
sortDMSessions,
|
|
sortSessions,
|
|
getHandsRaised,
|
|
getHandsRaisedNames,
|
|
hasOtherUserJoined,
|
|
getDMCalleeId,
|
|
isSupportedServerCalls,
|
|
isHostControlsAllowed,
|
|
areGroupCallsAllowed,
|
|
isCallsCustomMessage,
|
|
idsAreEqual,
|
|
errorAlert,
|
|
makeCallsTheme,
|
|
isCallsStartedMessage,
|
|
hasCaptions,
|
|
getTranscriptionUri,
|
|
} from './utils';
|
|
|
|
import type ChannelModel from '@typings/database/models/servers/channel';
|
|
import type {IntlShape} from 'react-intl';
|
|
|
|
describe('getICEServersConfigs', () => {
|
|
it('backwards compatible case, no ICEServersConfigs present', () => {
|
|
const config: CallsConfigState = {
|
|
...DefaultCallsConfig,
|
|
pluginEnabled: true,
|
|
ICEServers: ['stun:stun.example.com:3478'],
|
|
ICEServersConfigs: [],
|
|
AllowEnableCalls: true,
|
|
DefaultEnabled: true,
|
|
NeedsTURNCredentials: false,
|
|
last_retrieved_at: 0,
|
|
sku_short_name: License.SKU_SHORT_NAME.Professional,
|
|
MaxCallParticipants: 8,
|
|
EnableRecordings: true,
|
|
};
|
|
const iceConfigs = getICEServersConfigs(config);
|
|
|
|
assert.deepEqual(iceConfigs, [
|
|
{
|
|
urls: ['stun:stun.example.com:3478'],
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('ICEServersConfigs set', () => {
|
|
const config: CallsConfigState = {
|
|
...DefaultCallsConfig,
|
|
pluginEnabled: true,
|
|
ICEServersConfigs: [
|
|
{
|
|
urls: ['stun:stun.example.com:3478'],
|
|
},
|
|
{
|
|
urls: ['turn:turn.example.com:3478'],
|
|
},
|
|
],
|
|
AllowEnableCalls: true,
|
|
DefaultEnabled: true,
|
|
NeedsTURNCredentials: false,
|
|
last_retrieved_at: 0,
|
|
sku_short_name: License.SKU_SHORT_NAME.Professional,
|
|
MaxCallParticipants: 8,
|
|
EnableRecordings: true,
|
|
};
|
|
const iceConfigs = getICEServersConfigs(config);
|
|
|
|
assert.deepEqual(iceConfigs, [
|
|
{
|
|
urls: ['stun:stun.example.com:3478'],
|
|
},
|
|
{
|
|
urls: ['turn:turn.example.com:3478'],
|
|
},
|
|
]);
|
|
});
|
|
|
|
it('Both ICEServers and ICEServersConfigs set', () => {
|
|
const config: CallsConfigState = {
|
|
...DefaultCallsConfig,
|
|
pluginEnabled: true,
|
|
ICEServers: ['stun:stuna.example.com:3478'],
|
|
ICEServersConfigs: [
|
|
{
|
|
urls: ['stun:stunb.example.com:3478'],
|
|
},
|
|
{
|
|
urls: ['turn:turn.example.com:3478'],
|
|
},
|
|
],
|
|
AllowEnableCalls: true,
|
|
DefaultEnabled: true,
|
|
NeedsTURNCredentials: false,
|
|
last_retrieved_at: 0,
|
|
sku_short_name: License.SKU_SHORT_NAME.Professional,
|
|
MaxCallParticipants: 8,
|
|
EnableRecordings: true,
|
|
};
|
|
const iceConfigs = getICEServersConfigs(config);
|
|
|
|
assert.deepEqual(iceConfigs, [
|
|
{
|
|
urls: ['stun:stunb.example.com:3478'],
|
|
},
|
|
{
|
|
urls: ['turn:turn.example.com:3478'],
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('sortSessions', () => {
|
|
const locale = 'en';
|
|
const teammateNameDisplay = 'username';
|
|
|
|
it('returns empty array for undefined sessions', () => {
|
|
expect(sortSessions(locale, teammateNameDisplay, undefined)).toEqual([]);
|
|
});
|
|
|
|
it('sorts by name', () => {
|
|
const sessions = {
|
|
1: {
|
|
sessionId: '1',
|
|
userId: 'user1',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'charlie'}),
|
|
},
|
|
2: {
|
|
sessionId: '2',
|
|
userId: 'user2',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
|
},
|
|
3: {
|
|
sessionId: '3',
|
|
userId: 'user3',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'bob'}),
|
|
},
|
|
};
|
|
|
|
const sorted = sortSessions(locale, teammateNameDisplay, sessions);
|
|
expect(sorted.map((s) => s.userModel?.username)).toEqual(['alice', 'bob', 'charlie']);
|
|
});
|
|
|
|
it('sorts by state (presenter > raised hand > unmuted)', () => {
|
|
const sessions = {
|
|
1: {
|
|
sessionId: '1',
|
|
userId: 'user1',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'a'}),
|
|
},
|
|
2: {
|
|
sessionId: '2',
|
|
userId: 'user2',
|
|
muted: false,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'b'}),
|
|
},
|
|
3: {
|
|
sessionId: '3',
|
|
userId: 'user3',
|
|
muted: true,
|
|
raisedHand: 1000,
|
|
userModel: TestHelper.fakeUserModel({username: 'c'}),
|
|
},
|
|
};
|
|
|
|
const sorted = sortSessions(locale, teammateNameDisplay, sessions, '2');
|
|
expect(sorted.map((s) => s.userModel?.username)).toEqual(['b', 'c', 'a']);
|
|
});
|
|
|
|
it('sorts by raised hand timestamp when multiple hands are raised', () => {
|
|
const sessions = {
|
|
1: {
|
|
sessionId: '1',
|
|
userId: 'user1',
|
|
muted: true,
|
|
raisedHand: 2000, // Raised hand second
|
|
userModel: TestHelper.fakeUserModel({username: 'a'}),
|
|
},
|
|
2: {
|
|
sessionId: '2',
|
|
userId: 'user2',
|
|
muted: true,
|
|
raisedHand: 1000, // Raised hand first
|
|
userModel: TestHelper.fakeUserModel({username: 'b'}),
|
|
},
|
|
};
|
|
|
|
const sorted = sortSessions(locale, teammateNameDisplay, sessions);
|
|
expect(sorted.map((s) => s.userModel?.username)).toEqual(['b', 'a']);
|
|
});
|
|
});
|
|
|
|
describe('sortDMSessions', () => {
|
|
const locale = 'en';
|
|
const teammateNameDisplay = 'username';
|
|
|
|
it('should return an empty array for undefined sessions', () => {
|
|
expect(sortDMSessions(locale, teammateNameDisplay, 'my-id', undefined)).toEqual([]);
|
|
});
|
|
|
|
it('should keep the current user first even when activity state would reorder cards', () => {
|
|
const sessions = {
|
|
mySession: {
|
|
sessionId: 'my-session',
|
|
userId: 'my-id',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'me'}),
|
|
},
|
|
calleeSession: {
|
|
sessionId: 'callee-session',
|
|
userId: 'callee-id',
|
|
muted: false,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'callee'}),
|
|
},
|
|
};
|
|
|
|
const sorted = sortDMSessions(locale, teammateNameDisplay, 'my-id', sessions);
|
|
expect(sorted.map((s) => s.userModel?.username)).toEqual(['me', 'callee']);
|
|
});
|
|
});
|
|
|
|
describe('sortByCurrentUser (through sortDMSessions)', () => {
|
|
const locale = 'en';
|
|
const teammateNameDisplay = 'username';
|
|
|
|
it('should keep non-current users in their pre-existing order after moving the current user to the front', () => {
|
|
const sessions = {
|
|
aSession: {
|
|
sessionId: 'a-session',
|
|
userId: 'a-id',
|
|
muted: true,
|
|
raisedHand: 1000,
|
|
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
|
},
|
|
bSession: {
|
|
sessionId: 'b-session',
|
|
userId: 'b-id',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'bob'}),
|
|
},
|
|
cSession: {
|
|
sessionId: 'c-session',
|
|
userId: 'c-id',
|
|
muted: false,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'carol'}),
|
|
},
|
|
mySession: {
|
|
sessionId: 'my-session',
|
|
userId: 'my-id',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'me'}),
|
|
},
|
|
};
|
|
|
|
const sorted = sortDMSessions(locale, teammateNameDisplay, 'my-id', sessions, 'b-session');
|
|
expect(sorted.map((s) => s.userId)).toEqual(['my-id', 'b-id', 'a-id', 'c-id']);
|
|
});
|
|
|
|
it('should not change ordering when the current user has no session', () => {
|
|
const sessions = {
|
|
aSession: {
|
|
sessionId: 'a-session',
|
|
userId: 'a-id',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
|
},
|
|
bSession: {
|
|
sessionId: 'b-session',
|
|
userId: 'b-id',
|
|
muted: false,
|
|
raisedHand: 0,
|
|
userModel: TestHelper.fakeUserModel({username: 'bob'}),
|
|
},
|
|
};
|
|
|
|
const expected = sortSessions(locale, teammateNameDisplay, sessions, 'b-session').map((s) => s.userId);
|
|
const actual = sortDMSessions(locale, teammateNameDisplay, 'missing-user-id', sessions, 'b-session').map((s) => s.userId);
|
|
expect(actual).toEqual(expected);
|
|
});
|
|
});
|
|
|
|
describe('getHandsRaised', () => {
|
|
it('returns sessions with raised hands', () => {
|
|
const sessions = {
|
|
1: {
|
|
sessionId: '1',
|
|
userId: 'user1',
|
|
muted: true,
|
|
raisedHand: 0,
|
|
},
|
|
2: {
|
|
sessionId: '2',
|
|
userId: 'user2',
|
|
muted: true,
|
|
raisedHand: 1000,
|
|
},
|
|
3: {
|
|
sessionId: '3',
|
|
userId: 'user3',
|
|
muted: true,
|
|
raisedHand: 2000,
|
|
},
|
|
};
|
|
|
|
const raised = getHandsRaised(sessions);
|
|
expect(raised.length).toBe(2);
|
|
expect(raised.map((s) => s.sessionId).sort()).toEqual(['2', '3']);
|
|
});
|
|
});
|
|
|
|
describe('hasOtherUserJoined', () => {
|
|
const mySession = {sessionId: '1', userId: 'me', muted: true, raisedHand: 0};
|
|
|
|
it('should return false when only the same user has multiple sessions in the call', () => {
|
|
const sessions = {
|
|
1: mySession,
|
|
2: {sessionId: '2', userId: 'me', muted: true, raisedHand: 0},
|
|
};
|
|
|
|
expect(hasOtherUserJoined(sessions, 'me')).toBe(false);
|
|
});
|
|
|
|
it('should return true when another user is in the call', () => {
|
|
const sessions = {
|
|
1: mySession,
|
|
2: {sessionId: '2', userId: 'user2', muted: true, raisedHand: 0},
|
|
};
|
|
|
|
expect(hasOtherUserJoined(sessions, 'me')).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('getDMCalleeId', () => {
|
|
it('should return the other user in a DM', () => {
|
|
const channel = {type: 'D', name: 'me__them'} as ChannelModel;
|
|
|
|
expect(getDMCalleeId('me', channel)).toBe('them');
|
|
});
|
|
|
|
it('should return empty for a DM with yourself, which has no other party to wait for', () => {
|
|
const channel = {type: 'D', name: 'me__me'} as ChannelModel;
|
|
|
|
expect(getDMCalleeId('me', channel)).toBe('');
|
|
});
|
|
|
|
it('should return empty for group and open channels', () => {
|
|
expect(getDMCalleeId('me', {type: 'G', name: 'group'} as ChannelModel)).toBe('');
|
|
expect(getDMCalleeId('me', {type: 'O', name: 'town-square'} as ChannelModel)).toBe('');
|
|
});
|
|
|
|
it('should return empty when the channel is unknown', () => {
|
|
expect(getDMCalleeId('me', undefined)).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('getHandsRaisedNames', () => {
|
|
const locale = 'en';
|
|
const teammateNameDisplay = 'username';
|
|
const intl = {
|
|
formatMessage: ({id}: {id: string}) => (id === 'mobile.calls_you_2' ? 'You' : id),
|
|
} as IntlShape;
|
|
|
|
it('returns names in order of raised hand time', () => {
|
|
const sessions = [
|
|
{
|
|
sessionId: '1',
|
|
userId: 'user1',
|
|
raisedHand: 2000,
|
|
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
|
muted: false,
|
|
},
|
|
{
|
|
sessionId: '2',
|
|
userId: 'user2',
|
|
raisedHand: 1000,
|
|
userModel: TestHelper.fakeUserModel({username: 'bob'}),
|
|
muted: false,
|
|
},
|
|
];
|
|
|
|
const names = getHandsRaisedNames(sessions, '3', locale, teammateNameDisplay, intl);
|
|
expect(names).toEqual(['bob', 'alice']);
|
|
});
|
|
|
|
it('shows "You" for current user', () => {
|
|
const sessions = [
|
|
{
|
|
sessionId: '1',
|
|
userId: 'user1',
|
|
raisedHand: 1000,
|
|
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
|
muted: false,
|
|
},
|
|
];
|
|
|
|
const names = getHandsRaisedNames(sessions, '1', locale, teammateNameDisplay, intl);
|
|
expect(names).toEqual(['You']);
|
|
});
|
|
});
|
|
|
|
describe('isSupportedServerCalls', () => {
|
|
it('returns false for undefined version', () => {
|
|
expect(isSupportedServerCalls(undefined)).toBe(false);
|
|
});
|
|
|
|
it('returns true for supported version', () => {
|
|
expect(isSupportedServerCalls('7.6.0')).toBe(true);
|
|
});
|
|
|
|
it('returns false for unsupported version', () => {
|
|
expect(isSupportedServerCalls('6.2.0')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('isHostControlsAllowed and areGroupCallsAllowed', () => {
|
|
const config: CallsConfigState = {
|
|
...DefaultCallsConfig,
|
|
HostControlsAllowed: true,
|
|
GroupCallsAllowed: true,
|
|
};
|
|
|
|
it('returns config values', () => {
|
|
expect(isHostControlsAllowed(config)).toBe(true);
|
|
expect(areGroupCallsAllowed(config)).toBe(true);
|
|
});
|
|
|
|
it('returns false for undefined values', () => {
|
|
expect(isHostControlsAllowed({} as CallsConfigState)).toBe(false);
|
|
expect(areGroupCallsAllowed({} as CallsConfigState)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('isCallsCustomMessage', () => {
|
|
it('identifies calls messages', () => {
|
|
expect(isCallsCustomMessage(TestHelper.fakePost({type: Post.POST_TYPES.CUSTOM_CALLS}))).toBe(true);
|
|
expect(isCallsCustomMessage(TestHelper.fakePost({type: ''}))).toBe(false); // Regular post
|
|
});
|
|
});
|
|
|
|
describe('idsAreEqual', () => {
|
|
it('compares arrays of ids', () => {
|
|
expect(idsAreEqual(['1', '2', '3'], ['1', '2', '3'])).toBe(true);
|
|
expect(idsAreEqual(['1', '2', '3'], ['3', '2', '1'])).toBe(true);
|
|
expect(idsAreEqual(['1', '2'], ['1', '2', '3'])).toBe(false);
|
|
expect(idsAreEqual(['1', '2', '3'], ['1', '2'])).toBe(false);
|
|
expect(idsAreEqual(['1', '2', '3'], ['4', '5', '6'])).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('errorAlert', () => {
|
|
it('shows error alert', () => {
|
|
const mockAlert = jest.spyOn(Alert, 'alert');
|
|
const intl = {
|
|
formatMessage: ({defaultMessage}: {defaultMessage: string}, values?: any) => {
|
|
if (values) {
|
|
return defaultMessage.replace('{error}', values.error);
|
|
}
|
|
return defaultMessage;
|
|
},
|
|
} as IntlShape;
|
|
|
|
errorAlert('test error', intl);
|
|
|
|
expect(mockAlert).toHaveBeenCalledWith(
|
|
'Error',
|
|
'Error: test error',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('makeCallsTheme', () => {
|
|
it('creates calls theme from base theme', () => {
|
|
const theme = {
|
|
...Preferences.THEMES.denim,
|
|
sidebarBg: '#000000',
|
|
};
|
|
|
|
const callsTheme = makeCallsTheme(theme);
|
|
|
|
expect(callsTheme.callsBg).toBeDefined();
|
|
expect(callsTheme.callsBgRgb).toBeDefined();
|
|
expect(callsTheme.callsBadgeBg).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('isCallsStartedMessage', () => {
|
|
it('identifies calls notifications', () => {
|
|
expect(isCallsStartedMessage({sub_type: NOTIFICATION_SUB_TYPE.CALLS} as NotificationData)).toBe(true);
|
|
expect(isCallsStartedMessage({message: 'regular message'} as NotificationData)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('hasCaptions', () => {
|
|
it('checks for valid captions', () => {
|
|
expect(hasCaptions({captions: [{title: 'test', language: 'en', file_id: '123'}]})).toBe(true);
|
|
expect(hasCaptions({captions: []})).toBe(false);
|
|
expect(hasCaptions({})).toBe(false);
|
|
expect(hasCaptions(undefined)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('getTranscriptionUri', () => {
|
|
const serverUrl = 'https://example.com';
|
|
|
|
it('returns empty track when no captions', () => {
|
|
const result = getTranscriptionUri(serverUrl, {});
|
|
expect(result.tracks).toBeUndefined();
|
|
expect(result.selected).toEqual({type: SelectedTrackType.DISABLED, value: ''});
|
|
});
|
|
|
|
it('returns track info when captions exist', () => {
|
|
const props = {
|
|
captions: [{
|
|
title: 'English',
|
|
language: 'en',
|
|
file_id: '123',
|
|
}],
|
|
};
|
|
|
|
const result = getTranscriptionUri(serverUrl, props);
|
|
|
|
expect(result.tracks).toBeDefined();
|
|
expect(result.tracks?.length).toBe(1);
|
|
expect(result.selected).toEqual({type: SelectedTrackType.INDEX, value: 0});
|
|
});
|
|
});
|
|
|
|
describe('getCallPropsFromPost', () => {
|
|
test('undefined props', () => {
|
|
const post = TestHelper.fakePost({props: undefined});
|
|
|
|
const props = getCallPropsFromPost(post);
|
|
|
|
expect(props.title).toBe('');
|
|
expect(props.start_at).toBe(0);
|
|
expect(props.end_at).toBe(0);
|
|
expect(props.call_status).toBe('');
|
|
expect(props.recordings).toStrictEqual({});
|
|
expect(props.transcriptions).toStrictEqual({});
|
|
expect(props.participants.length).toBe(0);
|
|
});
|
|
|
|
test('missing props', () => {
|
|
const post = TestHelper.fakePost({props: {}});
|
|
|
|
const props = getCallPropsFromPost(post);
|
|
|
|
expect(props.title).toBe('');
|
|
expect(props.start_at).toBe(0);
|
|
expect(props.end_at).toBe(0);
|
|
expect(props.call_status).toBe('');
|
|
expect(props.recordings).toStrictEqual({});
|
|
expect(props.transcriptions).toStrictEqual({});
|
|
expect(props.participants.length).toBe(0);
|
|
});
|
|
|
|
test('invalid props', () => {
|
|
const callProps = {
|
|
title: {},
|
|
start_at: 'invalid',
|
|
end_at: [],
|
|
call_status: 'not_a_status',
|
|
recordings: null,
|
|
transcriptions: 45,
|
|
participants: 'invalid',
|
|
};
|
|
|
|
const post = TestHelper.fakePost({
|
|
props: callProps,
|
|
});
|
|
|
|
const props = getCallPropsFromPost(post);
|
|
|
|
expect(props.title).toBe('');
|
|
expect(props.start_at).toBe(0);
|
|
expect(props.end_at).toBe(0);
|
|
expect(props.call_status).toBe('');
|
|
expect(props.recordings).toStrictEqual({});
|
|
expect(props.transcriptions).toStrictEqual({});
|
|
expect(props.participants.length).toBe(0);
|
|
});
|
|
|
|
test('full props', () => {
|
|
const callProps = {
|
|
title: 'call title',
|
|
start_at: 1000,
|
|
end_at: 1045,
|
|
call_status: 'no_answer',
|
|
recordings: {
|
|
recA: {
|
|
file_id: 'recAFileID',
|
|
post_id: 'recAPostID',
|
|
tr_id: 'trA',
|
|
},
|
|
recB: {
|
|
file_id: 'recBFileID',
|
|
post_id: 'recBPostID',
|
|
tr_id: 'trB',
|
|
},
|
|
},
|
|
transcriptions: {
|
|
trA: {
|
|
file_id: 'trAFileID',
|
|
post_id: 'trAPostID',
|
|
rec_id: 'recA',
|
|
},
|
|
trB: {
|
|
file_id: 'trBFileID',
|
|
post_id: 'trBPostID',
|
|
rec_id: 'recB',
|
|
},
|
|
},
|
|
participants: ['userA', 'userB'],
|
|
};
|
|
|
|
const post = TestHelper.fakePost({
|
|
props: callProps,
|
|
});
|
|
|
|
const props = getCallPropsFromPost(post);
|
|
|
|
expect(props.title).toBe(post.props?.title);
|
|
expect(props.start_at).toBe(post.props?.start_at);
|
|
expect(props.end_at).toBe(post.props?.end_at);
|
|
expect(props.call_status).toBe(post.props?.call_status);
|
|
expect(props.recordings).toBe(post.props?.recordings);
|
|
expect(props.transcriptions).toBe(post.props?.transcriptions);
|
|
expect(props.participants).toBe(post.props?.participants);
|
|
});
|
|
});
|
|
|
|
describe('getCallCardState', () => {
|
|
const makeCallProps = (overrides: Partial<CallsPostProps> = {}): CallsPostProps => ({
|
|
title: '',
|
|
start_at: 1000,
|
|
end_at: 0,
|
|
call_status: '',
|
|
recordings: {},
|
|
transcriptions: {},
|
|
participants: [],
|
|
...overrides,
|
|
});
|
|
|
|
it('should be calling when the call is ringing and only the caller is in it', () => {
|
|
expect(getCallCardState(makeCallProps({call_status: CallPostStatus.Calling}), 1, true)).toBe(CallCardState.Calling);
|
|
});
|
|
|
|
it('should be active once the callee answers, even though call_status is still calling', () => {
|
|
expect(getCallCardState(makeCallProps({call_status: CallPostStatus.Calling}), 2, true)).toBe(CallCardState.Active);
|
|
});
|
|
|
|
it('should be active for an ongoing call with no call_status', () => {
|
|
expect(getCallCardState(makeCallProps(), 2, true)).toBe(CallCardState.Active);
|
|
});
|
|
|
|
it('should be ended once the call is gone, before the post has an end_at', () => {
|
|
expect(getCallCardState(makeCallProps({call_status: CallPostStatus.Calling}), 0, false)).toBe(CallCardState.Ended);
|
|
});
|
|
|
|
it('should be no answer for a call that timed out while ringing', () => {
|
|
expect(getCallCardState(makeCallProps({end_at: 31000, call_status: CallPostStatus.NoAnswer}), 0, false)).toBe(CallCardState.NoAnswer);
|
|
});
|
|
|
|
it('should be canceled for a call the caller hung up while ringing', () => {
|
|
expect(getCallCardState(makeCallProps({end_at: 3000, call_status: CallPostStatus.CanceledByCaller}), 0, false)).toBe(CallCardState.Canceled);
|
|
});
|
|
|
|
it('should be declined for a call the callee turned down', () => {
|
|
expect(getCallCardState(makeCallProps({end_at: 3000, call_status: CallPostStatus.Declined}), 0, false)).toBe(CallCardState.Declined);
|
|
});
|
|
|
|
it('should be ended for a call that was answered and then hung up', () => {
|
|
expect(getCallCardState(makeCallProps({end_at: 500000, call_status: CallPostStatus.Ended}), 0, false)).toBe(CallCardState.Ended);
|
|
});
|
|
|
|
it('should be ended for an ended call with no call_status, such as a channel call', () => {
|
|
expect(getCallCardState(makeCallProps({end_at: 3000, call_status: ''}), 0, false)).toBe(CallCardState.Ended);
|
|
});
|
|
});
|
|
|
|
describe('getNumUsersInCall', () => {
|
|
const session = (sessionId: string, userId: string): CallSession => ({sessionId, userId, muted: false, raisedHand: 0});
|
|
|
|
it('should count a user connected from more than one client once', () => {
|
|
const call = {
|
|
...DefaultCall,
|
|
sessions: {
|
|
session1: session('session1', 'user-1'),
|
|
session2: session('session2', 'user-1'),
|
|
session3: session('session3', 'user-2'),
|
|
},
|
|
};
|
|
|
|
expect(getNumUsersInCall(call)).toBe(2);
|
|
});
|
|
|
|
it('should be zero when there is no call', () => {
|
|
expect(getNumUsersInCall(undefined)).toBe(0);
|
|
});
|
|
});
|