Add model mocks to TestHelper (#8715)
* Add model mocks to TestHelper * Address feedback
This commit is contained in:
parent
97210af090
commit
85e01a7fb6
57 changed files with 1611 additions and 1059 deletions
|
|
@ -21,7 +21,6 @@ import {
|
|||
} from './post';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const serverUrl = 'baseHandler.test.com';
|
||||
let operator: ServerDataOperator;
|
||||
|
|
@ -47,11 +46,11 @@ jest.mock('@queries/servers/thread', () => {
|
|||
});
|
||||
|
||||
const channelId = 'channelid1';
|
||||
const user: UserProfile = {
|
||||
const user: UserProfile = TestHelper.fakeUser({
|
||||
id: 'userid',
|
||||
username: 'username',
|
||||
roles: '',
|
||||
} as UserProfile;
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await DatabaseManager.init([serverUrl]);
|
||||
|
|
@ -64,7 +63,7 @@ afterEach(async () => {
|
|||
|
||||
describe('sendAddToChannelEphemeralPost', () => {
|
||||
it('handle not found database', async () => {
|
||||
const {posts, error} = await sendAddToChannelEphemeralPost('foo', {} as UserModel, ['username2'], ['added username2'], channelId, '');
|
||||
const {posts, error} = await sendAddToChannelEphemeralPost('foo', TestHelper.fakeUserModel(), ['username2'], ['added username2'], channelId, '');
|
||||
expect(posts).toBeUndefined();
|
||||
expect(error).toBeTruthy();
|
||||
});
|
||||
|
|
@ -139,7 +138,7 @@ describe('removePost', () => {
|
|||
});
|
||||
|
||||
it('base case - system message', async () => {
|
||||
const systemPost = TestHelper.fakePost({channel_id: channelId, id: `${COMBINED_USER_ACTIVITY}id1_id2`, type: Post.POST_TYPES.COMBINED_USER_ACTIVITY as PostType, props: {system_post_ids: ['id1']}});
|
||||
const systemPost = TestHelper.fakePost({channel_id: channelId, id: `${COMBINED_USER_ACTIVITY}id1_id2`, type: Post.POST_TYPES.COMBINED_USER_ACTIVITY, props: {system_post_ids: ['id1']}});
|
||||
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
|
|
@ -187,16 +186,16 @@ describe('markPostAsDeleted', () => {
|
|||
describe('storePostsForChannel', () => {
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user.id});
|
||||
const teamId = 'tId1';
|
||||
const channel: Channel = {
|
||||
const channel: Channel = TestHelper.fakeChannel({
|
||||
id: channelId,
|
||||
team_id: teamId,
|
||||
total_msg_count: 0,
|
||||
} as Channel;
|
||||
const channelMember: ChannelMembership = {
|
||||
});
|
||||
const channelMember: ChannelMembership = TestHelper.fakeChannelMember({
|
||||
id: 'id',
|
||||
channel_id: channelId,
|
||||
msg_count: 0,
|
||||
} as ChannelMembership;
|
||||
});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const {models, error} = await storePostsForChannel('foo', channelId, [post], [post.id], '', ActionType.POSTS.RECEIVED_IN_CHANNEL, [user], false);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {
|
||||
setCurrentUserStatus,
|
||||
|
|
@ -13,8 +14,6 @@ import {
|
|||
} from './user';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const serverUrl = 'baseHandler.test.com';
|
||||
let operator: ServerDataOperator;
|
||||
|
|
@ -27,11 +26,11 @@ jest.mock('@init/credentials', () => {
|
|||
};
|
||||
});
|
||||
|
||||
const user: UserProfile = {
|
||||
const user: UserProfile = TestHelper.fakeUser({
|
||||
id: 'userid',
|
||||
username: 'username',
|
||||
roles: '',
|
||||
} as UserProfile;
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await DatabaseManager.init([serverUrl]);
|
||||
|
|
@ -44,12 +43,12 @@ afterEach(async () => {
|
|||
|
||||
describe('setCurrentUserStatus', () => {
|
||||
it('handle not found database', async () => {
|
||||
const result = await setCurrentUserStatus('foo', '') as {error: unknown};
|
||||
const result = await setCurrentUserStatus('foo', '');
|
||||
expect(result?.error).toBeDefined();
|
||||
});
|
||||
|
||||
it('handle no user', async () => {
|
||||
const result = await setCurrentUserStatus(serverUrl, '') as {error: unknown};
|
||||
const result = await setCurrentUserStatus(serverUrl, '');
|
||||
expect(result?.error).toBeDefined();
|
||||
expect((result?.error as Error).message).toBe(`No current user for ${serverUrl}`);
|
||||
});
|
||||
|
|
@ -58,20 +57,20 @@ describe('setCurrentUserStatus', () => {
|
|||
await operator.handleUsers({users: [user], prepareRecordsOnly: false});
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
|
||||
const result = await setCurrentUserStatus(serverUrl, 'away');
|
||||
expect(result).toBeNull();
|
||||
expect(result).not.toHaveProperty('error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateLocalCustomStatus', () => {
|
||||
it('handle not found database', async () => {
|
||||
const result = await updateLocalCustomStatus('foo', {} as UserModel) as {error: unknown};
|
||||
const result = await updateLocalCustomStatus('foo', TestHelper.fakeUserModel());
|
||||
expect(result?.error).toBeDefined();
|
||||
});
|
||||
|
||||
it('base case', async () => {
|
||||
const userModels = await operator.handleUsers({users: [user], prepareRecordsOnly: false});
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
|
||||
const result = await updateLocalCustomStatus(serverUrl, userModels[0], {text: 'customstatus'}) as {};
|
||||
const result = await updateLocalCustomStatus(serverUrl, userModels[0], {text: 'customstatus'});
|
||||
expect(result).toBeDefined();
|
||||
expect(result).not.toHaveProperty('error');
|
||||
});
|
||||
|
|
@ -79,14 +78,13 @@ describe('updateLocalCustomStatus', () => {
|
|||
|
||||
describe('updateRecentCustomStatuses', () => {
|
||||
it('handle not found database', async () => {
|
||||
const result = await updateRecentCustomStatuses('foo', {text: 'customstatus'}) as {error: unknown};
|
||||
expect(result?.error).toBeDefined();
|
||||
const result = await updateRecentCustomStatuses('foo', {text: 'customstatus'});
|
||||
expect(result.error).toBeDefined();
|
||||
});
|
||||
|
||||
it('base case', async () => {
|
||||
const result = await updateRecentCustomStatuses(serverUrl, {text: 'customstatus'}) as SystemModel[];
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBe(1); // system
|
||||
const result = await updateRecentCustomStatuses(serverUrl, {text: 'customstatus'});
|
||||
expect(result.models?.length).toBe(1); // system
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {addRecentReaction} from './reactions';
|
|||
import type Model from '@nozbe/watermelondb/Model';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
export async function setCurrentUserStatus(serverUrl: string, status: string) {
|
||||
export async function setCurrentUserStatus(serverUrl: string, status: string): Promise<{error?: unknown}> {
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const user = await getCurrentUser(database);
|
||||
|
|
@ -25,14 +25,14 @@ export async function setCurrentUserStatus(serverUrl: string, status: string) {
|
|||
await operator.batchRecords([user], 'setCurrentUserStatus');
|
||||
}
|
||||
|
||||
return null;
|
||||
return {};
|
||||
} catch (error) {
|
||||
logError('Failed setCurrentUserStatus', error);
|
||||
return {error};
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateLocalCustomStatus(serverUrl: string, user: UserModel, customStatus?: UserCustomStatus) {
|
||||
export async function updateLocalCustomStatus(serverUrl: string, user: UserModel, customStatus?: UserCustomStatus): Promise<{error?: unknown}> {
|
||||
try {
|
||||
const {operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const models: Model[] = [];
|
||||
|
|
@ -43,9 +43,9 @@ export async function updateLocalCustomStatus(serverUrl: string, user: UserModel
|
|||
|
||||
models.push(userModel);
|
||||
if (customStatus) {
|
||||
const recent = await updateRecentCustomStatuses(serverUrl, customStatus, true);
|
||||
if (Array.isArray(recent)) {
|
||||
models.push(...recent);
|
||||
const {models: customStatusModels} = await updateRecentCustomStatuses(serverUrl, customStatus, true);
|
||||
if (customStatusModels?.length) {
|
||||
models.push(...customStatusModels);
|
||||
}
|
||||
|
||||
if (customStatus.emoji) {
|
||||
|
|
@ -65,7 +65,7 @@ export async function updateLocalCustomStatus(serverUrl: string, user: UserModel
|
|||
}
|
||||
}
|
||||
|
||||
export const updateRecentCustomStatuses = async (serverUrl: string, customStatus: UserCustomStatus, prepareRecordsOnly = false, remove = false) => {
|
||||
export const updateRecentCustomStatuses = async (serverUrl: string, customStatus: UserCustomStatus, prepareRecordsOnly = false, remove = false): Promise<{models?: Model[]; error?: unknown}> => {
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const recentStatuses = await getRecentCustomStatuses(database);
|
||||
|
|
@ -83,13 +83,14 @@ export const updateRecentCustomStatuses = async (serverUrl: string, customStatus
|
|||
recentStatuses.unshift(customStatus);
|
||||
}
|
||||
|
||||
return operator.handleSystem({
|
||||
const models = await operator.handleSystem({
|
||||
systems: [{
|
||||
id: SYSTEM_IDENTIFIERS.RECENT_CUSTOM_STATUS,
|
||||
value: JSON.stringify(recentStatuses),
|
||||
}],
|
||||
prepareRecordsOnly,
|
||||
});
|
||||
return {models};
|
||||
} catch (error) {
|
||||
logError('Failed updateRecentCustomStatuses', error);
|
||||
return {error};
|
||||
|
|
|
|||
|
|
@ -880,7 +880,7 @@ export const getAllSupportedTimezones = async (serverUrl: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const fetchCustomAttributes = async (serverUrl: string, userId: string, filterEmpty = false): Promise<{attributes: CustomAttributeSet; error: unknown}> => {
|
||||
export const fetchCustomAttributes = async (serverUrl: string, userId: string, filterEmpty = false): Promise<{attributes: CustomAttributeSet; error?: unknown}> => {
|
||||
try {
|
||||
const client = NetworkManager.getClient(serverUrl);
|
||||
const [fields, attrValues] = await Promise.all([
|
||||
|
|
@ -901,13 +901,13 @@ export const fetchCustomAttributes = async (serverUrl: string, userId: string, f
|
|||
};
|
||||
}
|
||||
});
|
||||
return {attributes, error: undefined};
|
||||
return {attributes};
|
||||
}
|
||||
return {attributes: {} as Record<string, CustomAttribute>, error: undefined};
|
||||
return {attributes: {}};
|
||||
} catch (error) {
|
||||
logDebug('error on fetchCustomAttributes', getFullErrorMessage(error));
|
||||
forceLogoutIfNecessary(serverUrl, error);
|
||||
return {attributes: {} as Record<string, CustomAttribute>, error};
|
||||
return {attributes: {}, error};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,10 @@ import {getIsCRTEnabled} from '@queries/servers/thread';
|
|||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {handleFirstConnect, handleReconnect} from './index';
|
||||
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@actions/local/channel');
|
||||
jest.mock('@actions/local/systems');
|
||||
jest.mock('@actions/remote/channel');
|
||||
|
|
@ -87,10 +85,10 @@ describe('WebSocket Index Actions', () => {
|
|||
};
|
||||
|
||||
jest.mocked(entry).mockResolvedValue(mockEntryData);
|
||||
jest.mocked(getCurrentUser).mockResolvedValue({
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(TestHelper.fakeUserModel({
|
||||
id: currentUserId,
|
||||
locale: 'en',
|
||||
} as UserModel);
|
||||
}));
|
||||
jest.mocked(getConfig).mockResolvedValue({Version: '9.0.0'} as ClientConfig);
|
||||
jest.mocked(isSupportedServerCalls).mockReturnValue(true);
|
||||
|
||||
|
|
@ -107,10 +105,10 @@ describe('WebSocket Index Actions', () => {
|
|||
it('should handle error when server database not found', async () => {
|
||||
DatabaseManager.serverDatabases = {};
|
||||
|
||||
const error = await handleFirstConnect(serverUrl) as any;
|
||||
const error = await handleFirstConnect(serverUrl);
|
||||
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error.message).toBe('cannot find server database');
|
||||
expect((error as Error).message).toBe('cannot find server database');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -137,10 +135,10 @@ describe('WebSocket Index Actions', () => {
|
|||
};
|
||||
|
||||
jest.mocked(entry).mockResolvedValue(mockEntryData);
|
||||
jest.mocked(getCurrentUser).mockResolvedValue({
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(TestHelper.fakeUserModel({
|
||||
id: currentUserId,
|
||||
locale: 'en',
|
||||
} as UserModel);
|
||||
}));
|
||||
jest.mocked(getConfig).mockResolvedValue({Version: '9.0.0'} as ClientConfig);
|
||||
jest.mocked(isSupportedServerCalls).mockReturnValue(true);
|
||||
jest.mocked(getActiveServerUrl).mockResolvedValue(serverUrl);
|
||||
|
|
@ -169,7 +167,7 @@ describe('WebSocket Index Actions', () => {
|
|||
|
||||
it('should fetch thread posts when CRT enabled', async () => {
|
||||
const threadId = 'thread-id';
|
||||
const lastPost = {id: 'post-id', createAt: 123} as PostModel;
|
||||
const lastPost = TestHelper.fakePostModel({id: 'post-id', createAt: 123});
|
||||
|
||||
jest.mocked(NavigationStore.getScreensInStack).mockReturnValue(['Thread']);
|
||||
|
||||
|
|
@ -193,7 +191,7 @@ describe('WebSocket Index Actions', () => {
|
|||
});
|
||||
|
||||
it('should handle notification tapped state', async () => {
|
||||
(NavigationStore.getScreensInStack as jest.Mock).mockReturnValue(['Channel']);
|
||||
jest.mocked(NavigationStore.getScreensInStack).mockReturnValue(['Channel']);
|
||||
|
||||
jest.mocked(EphemeralStore.wasNotificationTapped).mockReturnValue(true);
|
||||
|
||||
|
|
@ -206,10 +204,10 @@ describe('WebSocket Index Actions', () => {
|
|||
it('should handle error in entry data', async () => {
|
||||
jest.mocked(entry).mockResolvedValue({error: new Error('entry error')});
|
||||
|
||||
const result = await handleReconnect(serverUrl) as any;
|
||||
const result = await handleReconnect(serverUrl);
|
||||
|
||||
expect(result).toBeInstanceOf(Error);
|
||||
expect(result.message).toBe('entry error');
|
||||
expect((result as Error).message).toBe('entry error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {DeviceEventEmitter} from 'react-native';
|
|||
import {markChannelAsViewed, markChannelAsUnread, storeMyChannelsForTeam, updateLastPostAt} from '@actions/local/channel';
|
||||
import {addPostAcknowledgement, markPostAsDeleted, removePostAcknowledgement} from '@actions/local/post';
|
||||
import {updateThread} from '@actions/local/thread';
|
||||
import {fetchChannelStats, fetchMyChannel, type MyChannelsRequest} from '@actions/remote/channel';
|
||||
import {fetchChannelStats, fetchMyChannel} from '@actions/remote/channel';
|
||||
import {fetchPostAuthors} from '@actions/remote/post';
|
||||
import {fetchThread} from '@actions/remote/thread';
|
||||
import {fetchMissingProfilesByIds} from '@actions/remote/user';
|
||||
|
|
@ -19,17 +19,13 @@ import {getCurrentUserId, getCurrentChannelId} from '@queries/servers/system';
|
|||
import {getIsCRTEnabled} from '@queries/servers/thread';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import NavigationStore from '@store/navigation_store';
|
||||
import MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {isTablet} from '@utils/helpers';
|
||||
import {shouldIgnorePost} from '@utils/post';
|
||||
|
||||
import {handleNewPostEvent, handlePostEdited, handlePostDeleted, handlePostUnread, handlePostAcknowledgementAdded, handlePostAcknowledgementRemoved} from './posts';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type ThreadModel from '@typings/database/models/servers/thread';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@queries/servers/post');
|
||||
jest.mock('@queries/servers/channel');
|
||||
|
|
@ -53,9 +49,9 @@ const serverUrl = 'baseHandler.test.com';
|
|||
describe('WebSocket Post Actions', () => {
|
||||
let operator: ServerDataOperator;
|
||||
|
||||
const post = {id: 'post1', channel_id: 'channel1', user_id: 'user1', create_at: 12345, message: 'hello'} as Post;
|
||||
const postModels = [{channelId: post.channel_id, userId: post.user_id, message: post.message} as PostModel];
|
||||
const myChannelModel = {id: 'channel1', manuallyUnread: false, messageCount: 4, mentionsCount: 0, lastViewedAt: 1} as MyChannelModel;
|
||||
const post = TestHelper.fakePost({id: 'post1', channel_id: 'channel1', user_id: 'user1', create_at: 12345, message: 'hello'});
|
||||
const postModels = [TestHelper.fakePostModel({channelId: post.channel_id, userId: post.user_id, message: post.message, isPinned: true})];
|
||||
const myChannelModel = TestHelper.fakeMyChannelModel({id: 'channel1', manuallyUnread: false, messageCount: 4, mentionsCount: 0, lastViewedAt: 1});
|
||||
|
||||
const mockedGetPostById = jest.mocked(getPostById);
|
||||
const mockedUpdateLastPostAt = jest.mocked(updateLastPostAt);
|
||||
|
|
@ -105,13 +101,13 @@ describe('WebSocket Post Actions', () => {
|
|||
mockedIsTablet.mockReturnValue(false);
|
||||
|
||||
it('should handle new post event - channel membership present', async () => {
|
||||
const userModel = {id: 'user1', username: 'username1'} as UserModel;
|
||||
const userModel = TestHelper.fakeUserModel({id: 'user1', username: 'username1'});
|
||||
const emitSpy = jest.spyOn(DeviceEventEmitter, 'emit');
|
||||
const batchRecordsSpy = jest.spyOn(operator, 'batchRecords').mockImplementation(jest.fn());
|
||||
jest.spyOn(operator, 'handlePosts').mockResolvedValue(postModels);
|
||||
jest.spyOn(operator, 'handleUsers').mockResolvedValue([userModel]);
|
||||
|
||||
mockedFetchPostAuthors.mockResolvedValueOnce({authors: [{id: 'user1', username: 'username1'} as UserProfile]});
|
||||
mockedFetchPostAuthors.mockResolvedValueOnce({authors: [TestHelper.fakeUser({id: 'user1', username: 'username1'})]});
|
||||
mockedGetMyChannel.mockResolvedValue(myChannelModel);
|
||||
mockedGetIsCRTEnabled.mockResolvedValue(false);
|
||||
mockedShouldIgnorePost.mockReturnValue(false);
|
||||
|
|
@ -120,12 +116,22 @@ describe('WebSocket Post Actions', () => {
|
|||
|
||||
expect(emitSpy).toHaveBeenCalledWith(Events.USER_STOP_TYPING, {
|
||||
channelId: 'channel1',
|
||||
rootId: undefined,
|
||||
rootId: '',
|
||||
userId: 'user1',
|
||||
now: expect.any(Number),
|
||||
});
|
||||
|
||||
expect(batchRecordsSpy).toHaveBeenCalledWith([userModel, {_preparedState: null, id: 'channel1', lastViewedAt: 1, manuallyUnread: false, mentionsCount: 0, messageCount: 4}, postModels[0]], 'handleNewPostEvent');
|
||||
expect(batchRecordsSpy).toHaveBeenCalledWith([
|
||||
userModel,
|
||||
expect.objectContaining({
|
||||
id: 'channel1',
|
||||
lastViewedAt: 1,
|
||||
manuallyUnread: false,
|
||||
mentionsCount: 0,
|
||||
messageCount: 4,
|
||||
}),
|
||||
postModels[0],
|
||||
], 'handleNewPostEvent');
|
||||
});
|
||||
|
||||
it('should handle new post event - without channel membership present', async () => {
|
||||
|
|
@ -134,7 +140,7 @@ describe('WebSocket Post Actions', () => {
|
|||
jest.spyOn(operator, 'handlePosts').mockResolvedValue(postModels);
|
||||
|
||||
mockedGetMyChannel.mockResolvedValueOnce(undefined);
|
||||
mockedFetchMyChannel.mockResolvedValue({teamId: 'team1', memberships: [{user_id: 'user1', channel_id: 'channel1'}]} as MyChannelsRequest);
|
||||
mockedFetchMyChannel.mockResolvedValue({teamId: 'team1', memberships: [TestHelper.fakeChannelMember({user_id: 'user1', channel_id: 'channel1'})]});
|
||||
mockedStoreMyChannelsForTeam.mockResolvedValue({models: [myChannelModel], error: undefined});
|
||||
mockedGetMyChannel.mockResolvedValueOnce(myChannelModel);
|
||||
mockedGetIsCRTEnabled.mockResolvedValue(false);
|
||||
|
|
@ -144,7 +150,7 @@ describe('WebSocket Post Actions', () => {
|
|||
|
||||
expect(emitSpy).toHaveBeenCalledWith(Events.USER_STOP_TYPING, {
|
||||
channelId: 'channel1',
|
||||
rootId: undefined,
|
||||
rootId: '',
|
||||
userId: 'user1',
|
||||
now: expect.any(Number),
|
||||
});
|
||||
|
|
@ -157,7 +163,7 @@ describe('WebSocket Post Actions', () => {
|
|||
const batchRecordsSpy = jest.spyOn(operator, 'batchRecords').mockImplementation(jest.fn());
|
||||
jest.spyOn(operator, 'handlePosts').mockResolvedValue(postModels);
|
||||
|
||||
mockedGetMyChannel.mockResolvedValue({...myChannelModel, manuallyUnread: true} as MyChannelModel);
|
||||
mockedGetMyChannel.mockResolvedValue(TestHelper.fakeMyChannelModel({...myChannelModel, manuallyUnread: true}));
|
||||
mockedGetIsCRTEnabled.mockResolvedValue(true);
|
||||
mockedShouldIgnorePost.mockReturnValue(false);
|
||||
mockedMarkChannelAsUnread.mockResolvedValue({member: myChannelModel});
|
||||
|
|
@ -166,16 +172,22 @@ describe('WebSocket Post Actions', () => {
|
|||
|
||||
expect(emitSpy).toHaveBeenCalledWith(Events.USER_STOP_TYPING, {
|
||||
channelId: 'channel1',
|
||||
rootId: undefined,
|
||||
rootId: '',
|
||||
userId: 'user1',
|
||||
now: expect.any(Number),
|
||||
});
|
||||
|
||||
expect(batchRecordsSpy).toHaveBeenCalledWith([{_preparedState: null, id: 'channel1', lastViewedAt: 1, manuallyUnread: false, mentionsCount: 0, messageCount: 4}, postModels[0]], 'handleNewPostEvent');
|
||||
expect(batchRecordsSpy).toHaveBeenCalledWith([expect.objectContaining({
|
||||
id: 'channel1',
|
||||
lastViewedAt: 1,
|
||||
manuallyUnread: false,
|
||||
mentionsCount: 0,
|
||||
messageCount: 4,
|
||||
}), postModels[0]], 'handleNewPostEvent');
|
||||
});
|
||||
|
||||
it('should handle new post event - out of order ws, CRT on, root id', async () => {
|
||||
const newPost = {...post, root_id: 'post2'} as Post;
|
||||
const newPost = TestHelper.fakePost({...post, root_id: 'post2'});
|
||||
jest.spyOn(EphemeralStore, 'getLastPostWebsocketEvent').mockReturnValueOnce({deleted: true, post: newPost});
|
||||
const emitSpy = jest.spyOn(DeviceEventEmitter, 'emit');
|
||||
const batchRecordsSpy = jest.spyOn(operator, 'batchRecords');
|
||||
|
|
@ -213,12 +225,18 @@ describe('WebSocket Post Actions', () => {
|
|||
expect(mockedGetScreensInStack).toHaveBeenCalled();
|
||||
expect(emitSpy).toHaveBeenCalledWith(Events.USER_STOP_TYPING, {
|
||||
channelId: 'channel1',
|
||||
rootId: undefined,
|
||||
rootId: '',
|
||||
userId: 'user1',
|
||||
now: expect.any(Number),
|
||||
});
|
||||
|
||||
expect(batchRecordsSpy).toHaveBeenCalledWith([{_preparedState: null, id: 'channel1', lastViewedAt: 1, manuallyUnread: false, mentionsCount: 0, messageCount: 4}, postModels[0]], 'handleNewPostEvent');
|
||||
expect(batchRecordsSpy).toHaveBeenCalledWith([expect.objectContaining({
|
||||
id: 'channel1',
|
||||
lastViewedAt: 1,
|
||||
manuallyUnread: false,
|
||||
mentionsCount: 0,
|
||||
messageCount: 4,
|
||||
}), postModels[0]], 'handleNewPostEvent');
|
||||
});
|
||||
|
||||
it('should handle new post event - no operator', async () => {
|
||||
|
|
@ -302,7 +320,7 @@ describe('WebSocket Post Actions', () => {
|
|||
},
|
||||
} as WebSocketMessage;
|
||||
|
||||
const threadModel = {viewedAt: 1, id: 'thread1'} as ThreadModel;
|
||||
const threadModel = TestHelper.fakeThreadModel({viewedAt: 1, id: 'thread1'});
|
||||
|
||||
it('should handle post deleted event', async () => {
|
||||
const batchRecordsSpy = jest.spyOn(operator, 'batchRecords').mockImplementation(jest.fn());
|
||||
|
|
@ -311,7 +329,7 @@ describe('WebSocket Post Actions', () => {
|
|||
mockedGetPostById.mockResolvedValue(postModels[0]);
|
||||
mockedMarkPostAsDeleted.mockResolvedValue({model: postModels[0]});
|
||||
mockedUpdateThread.mockResolvedValue({model: threadModel});
|
||||
mockedGetChannelById.mockResolvedValue({id: 'channel1', teamId: 'team1'} as ChannelModel);
|
||||
mockedGetChannelById.mockResolvedValue(TestHelper.fakeChannelModel({id: 'channel1', teamId: 'team1'}));
|
||||
|
||||
await handlePostDeleted(serverUrl, msg);
|
||||
|
||||
|
|
@ -372,7 +390,7 @@ describe('WebSocket Post Actions', () => {
|
|||
it('should handle post unread event', async () => {
|
||||
mockedGetMyChannel.mockResolvedValue(myChannelModel);
|
||||
mockedGetIsCRTEnabled.mockResolvedValue(false);
|
||||
mockedFetchMyChannel.mockResolvedValue({teamId: 'team1', memberships: [{user_id: 'user1', channel_id: 'channel1'}]} as MyChannelsRequest);
|
||||
mockedFetchMyChannel.mockResolvedValue({teamId: 'team1', memberships: [TestHelper.fakeChannelMember({user_id: 'user1', channel_id: 'channel1'})]});
|
||||
mockedMarkChannelAsUnread.mockResolvedValue({member: myChannelModel});
|
||||
|
||||
await handlePostUnread(serverUrl, msg);
|
||||
|
|
@ -381,9 +399,9 @@ describe('WebSocket Post Actions', () => {
|
|||
});
|
||||
|
||||
it('should handle post unread event - CRT enabled, manually marked read', async () => {
|
||||
mockedGetMyChannel.mockResolvedValue({...myChannelModel, manuallyUnread: true} as MyChannelModel);
|
||||
mockedGetMyChannel.mockResolvedValue(TestHelper.fakeMyChannelModel({...myChannelModel, manuallyUnread: true}));
|
||||
mockedGetIsCRTEnabled.mockResolvedValue(true);
|
||||
mockedFetchMyChannel.mockResolvedValue({teamId: 'team1', memberships: [{user_id: 'user1', channel_id: 'channel1'}]} as MyChannelsRequest);
|
||||
mockedFetchMyChannel.mockResolvedValue({teamId: 'team1', memberships: [TestHelper.fakeChannelMember({user_id: 'user1', channel_id: 'channel1'})]});
|
||||
mockedMarkChannelAsUnread.mockResolvedValue({member: myChannelModel});
|
||||
|
||||
await handlePostUnread(serverUrl, msg);
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ import DatabaseManager from '@database/manager';
|
|||
import {getRoleById} from '@queries/servers/role';
|
||||
import {getCurrentUserId} from '@queries/servers/system';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {handleRoleUpdatedEvent, handleUserRoleUpdatedEvent, handleTeamMemberRoleUpdatedEvent} from './roles';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type RoleModel from '@typings/database/models/servers/role';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@actions/remote/role');
|
||||
jest.mock('@database/manager');
|
||||
|
|
@ -38,7 +37,7 @@ describe('WebSocket Roles Actions', () => {
|
|||
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
|
||||
|
||||
batchRecords = jest.spyOn(operator, 'batchRecords').mockResolvedValue();
|
||||
handleRole = jest.spyOn(operator, 'handleRole').mockResolvedValue([{id: 'role1'} as RoleModel]);
|
||||
handleRole = jest.spyOn(operator, 'handleRole').mockResolvedValue([TestHelper.fakeRoleModel({id: 'role1'})]);
|
||||
handleMyTeam = jest.spyOn(operator, 'handleMyTeam').mockResolvedValue([]);
|
||||
handleTeamMemberships = jest.spyOn(operator, 'handleTeamMemberships').mockResolvedValue([]);
|
||||
});
|
||||
|
|
@ -77,7 +76,7 @@ describe('WebSocket Roles Actions', () => {
|
|||
name: 'test_role',
|
||||
permissions: ['permission1'],
|
||||
};
|
||||
jest.mocked(getRoleById).mockResolvedValue({id: roleId} as RoleModel);
|
||||
jest.mocked(getRoleById).mockResolvedValue(TestHelper.fakeRoleModel({id: roleId}));
|
||||
const msg = {
|
||||
data: {
|
||||
role: JSON.stringify(mockRole),
|
||||
|
|
@ -93,7 +92,7 @@ describe('WebSocket Roles Actions', () => {
|
|||
});
|
||||
|
||||
it('should handle invalid JSON in role data', async () => {
|
||||
jest.mocked(getRoleById).mockResolvedValue({id: roleId} as RoleModel);
|
||||
jest.mocked(getRoleById).mockResolvedValue(TestHelper.fakeRoleModel({id: roleId}));
|
||||
const msg = {
|
||||
data: {
|
||||
role: 'invalid json',
|
||||
|
|
@ -132,11 +131,11 @@ describe('WebSocket Roles Actions', () => {
|
|||
|
||||
it('should update roles and user', async () => {
|
||||
jest.mocked(getCurrentUserId).mockResolvedValue(currentUserId);
|
||||
jest.mocked(getCurrentUser).mockResolvedValue({
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(TestHelper.fakeUserModel({
|
||||
prepareUpdate: jest.fn(),
|
||||
} as unknown as UserModel);
|
||||
}));
|
||||
jest.mocked(fetchRolesIfNeeded).mockResolvedValue({
|
||||
roles: [{id: 'role1'} as Role],
|
||||
roles: [TestHelper.fakeRole({id: 'role1'})],
|
||||
});
|
||||
|
||||
const msg = {
|
||||
|
|
@ -156,7 +155,7 @@ describe('WebSocket Roles Actions', () => {
|
|||
jest.mocked(getCurrentUserId).mockResolvedValue(currentUserId);
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(undefined);
|
||||
jest.mocked(fetchRolesIfNeeded).mockResolvedValue({
|
||||
roles: [{id: 'role1'} as Role],
|
||||
roles: [TestHelper.fakeRole({id: 'role1'})],
|
||||
});
|
||||
|
||||
const msg = {
|
||||
|
|
@ -174,9 +173,9 @@ describe('WebSocket Roles Actions', () => {
|
|||
|
||||
it('should handle no new roles from fetchRolesIfNeeded', async () => {
|
||||
jest.mocked(getCurrentUserId).mockResolvedValue(currentUserId);
|
||||
jest.mocked(getCurrentUser).mockResolvedValue({
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(TestHelper.fakeUserModel({
|
||||
prepareUpdate: jest.fn(),
|
||||
} as unknown as UserModel);
|
||||
}));
|
||||
jest.mocked(fetchRolesIfNeeded).mockResolvedValue({
|
||||
roles: [],
|
||||
});
|
||||
|
|
@ -246,7 +245,7 @@ describe('WebSocket Roles Actions', () => {
|
|||
it('should update roles, myTeam and teamMembership', async () => {
|
||||
jest.mocked(getCurrentUserId).mockResolvedValue(currentUserId);
|
||||
jest.mocked(fetchRolesIfNeeded).mockResolvedValue({
|
||||
roles: [{id: 'role1'} as Role],
|
||||
roles: [TestHelper.fakeRole({id: 'role1'})],
|
||||
});
|
||||
|
||||
const msg = {
|
||||
|
|
|
|||
|
|
@ -13,11 +13,10 @@ import {getCurrentTeam, queryMyTeamsByIds} from '@queries/servers/team';
|
|||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {setTeamLoading} from '@store/team_load_store';
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {logDebug} from '@utils/log';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@actions/local/team', () => ({
|
||||
removeUserFromTeam: jest.fn(),
|
||||
|
|
@ -102,10 +101,10 @@ describe('WebSocket Team Actions', () => {
|
|||
const mockedUpdateUsersNoLongerVisible = jest.mocked(updateUsersNoLongerVisible);
|
||||
const mockedUpdateCanJoinTeams = jest.mocked(updateCanJoinTeams);
|
||||
|
||||
mockedQueryMyTeamsByIds.mockReturnValue({fetch: jest.fn().mockResolvedValue([{id: 'team1'}])} as any);
|
||||
mockedGetCurrentTeam.mockResolvedValue({id: 'team1'} as TeamModel);
|
||||
mockedQueryMyTeamsByIds.mockReturnValue(TestHelper.fakeQuery([TestHelper.fakeMyTeamModel({id: 'team1'})]));
|
||||
mockedGetCurrentTeam.mockResolvedValue(TestHelper.fakeTeamModel({id: 'team1'}));
|
||||
mockedRemoveUserFromTeam.mockResolvedValue({error: undefined});
|
||||
mockedGetCurrentUser.mockResolvedValue({id: 'user1', isGuest: true} as UserModel);
|
||||
mockedGetCurrentUser.mockResolvedValue(TestHelper.fakeUserModel({id: 'user1', isGuest: true}));
|
||||
mockedUpdateUsersNoLongerVisible.mockResolvedValue({error: undefined});
|
||||
mockedUpdateCanJoinTeams.mockResolvedValue({error: undefined});
|
||||
|
||||
|
|
@ -121,7 +120,7 @@ describe('WebSocket Team Actions', () => {
|
|||
const mockedUpdateCanJoinTeams = jest.mocked(updateCanJoinTeams);
|
||||
const mockedRemoveUserFromTeam = jest.mocked(removeUserFromTeam);
|
||||
|
||||
mockedQueryMyTeamsByIds.mockReturnValue({fetch: jest.fn().mockResolvedValue([undefined])} as any);
|
||||
mockedQueryMyTeamsByIds.mockReturnValue(TestHelper.fakeQuery([]));
|
||||
mockedUpdateCanJoinTeams.mockResolvedValue({error: undefined});
|
||||
|
||||
await handleTeamArchived(serverUrl, msg);
|
||||
|
|
@ -138,10 +137,10 @@ describe('WebSocket Team Actions', () => {
|
|||
const mockedUpdateUsersNoLongerVisible = jest.mocked(updateUsersNoLongerVisible);
|
||||
const mockedUpdateCanJoinTeams = jest.mocked(updateCanJoinTeams);
|
||||
|
||||
mockedQueryMyTeamsByIds.mockReturnValue({fetch: jest.fn().mockResolvedValue([{id: 'team1'}])} as any);
|
||||
mockedGetCurrentTeam.mockResolvedValue({id: 'team2'} as TeamModel);
|
||||
mockedQueryMyTeamsByIds.mockReturnValue(TestHelper.fakeQuery([TestHelper.fakeMyTeamModel({id: 'team1'})]));
|
||||
mockedGetCurrentTeam.mockResolvedValue(TestHelper.fakeTeamModel({id: 'team2'}));
|
||||
mockedRemoveUserFromTeam.mockResolvedValue({error: undefined});
|
||||
mockedGetCurrentUser.mockResolvedValue({id: 'user1', isGuest: false} as UserModel);
|
||||
mockedGetCurrentUser.mockResolvedValue(TestHelper.fakeUserModel({id: 'user1', isGuest: false}));
|
||||
mockedUpdateCanJoinTeams.mockResolvedValue({error: undefined});
|
||||
|
||||
await handleTeamArchived(serverUrl, msg);
|
||||
|
|
@ -214,8 +213,8 @@ describe('WebSocket Team Actions', () => {
|
|||
const mockedGetCurrentTeam = jest.mocked(getCurrentTeam);
|
||||
const mockedRemoveUserFromTeam = jest.mocked(removeUserFromTeam);
|
||||
|
||||
mockedGetCurrentUser.mockResolvedValue({id: 'user1', isGuest: true} as UserModel);
|
||||
mockedGetCurrentTeam.mockResolvedValue({id: 'team1'} as TeamModel);
|
||||
mockedGetCurrentUser.mockResolvedValue(TestHelper.fakeUserModel({id: 'user1', isGuest: true}));
|
||||
mockedGetCurrentTeam.mockResolvedValue(TestHelper.fakeTeamModel({id: 'team1'}));
|
||||
|
||||
await handleLeaveTeamEvent(serverUrl, msg);
|
||||
|
||||
|
|
@ -226,7 +225,7 @@ describe('WebSocket Team Actions', () => {
|
|||
const mockedGetCurrentUser = jest.mocked(getCurrentUser);
|
||||
const mockedRemoveUserFromTeam = jest.mocked(removeUserFromTeam);
|
||||
|
||||
mockedGetCurrentUser.mockResolvedValue({id: 'user2', isGuest: true} as UserModel);
|
||||
mockedGetCurrentUser.mockResolvedValue(TestHelper.fakeUserModel({id: 'user2', isGuest: true}));
|
||||
|
||||
await handleLeaveTeamEvent(serverUrl, msg);
|
||||
|
||||
|
|
@ -249,8 +248,8 @@ describe('WebSocket Team Actions', () => {
|
|||
const mockedGetCurrentTeam = jest.mocked(getCurrentTeam);
|
||||
const mockedRemoveUserFromTeam = jest.mocked(removeUserFromTeam);
|
||||
|
||||
mockedGetCurrentUser.mockResolvedValue({id: 'user1', isGuest: false} as UserModel);
|
||||
mockedGetCurrentTeam.mockResolvedValue({id: 'team2'} as TeamModel);
|
||||
mockedGetCurrentUser.mockResolvedValue(TestHelper.fakeUserModel({id: 'user1', isGuest: false}));
|
||||
mockedGetCurrentTeam.mockResolvedValue(TestHelper.fakeTeamModel({id: 'team2'}));
|
||||
|
||||
await handleLeaveTeamEvent(serverUrl, msg);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ import {queryChannelsByTypes, queryUserChannelsByTypes} from '@queries/servers/c
|
|||
import {queryDisplayNamePreferences} from '@queries/servers/preference';
|
||||
import {getConfig, getLicense} from '@queries/servers/system';
|
||||
import {getCurrentUser} from '@queries/servers/user';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {handleUserUpdatedEvent, handleUserTypingEvent, handleStatusChangedEvent, userTyping} from './users';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@actions/local/channel');
|
||||
jest.mock('@actions/local/user');
|
||||
|
|
@ -46,13 +46,11 @@ describe('WebSocket Users Actions', () => {
|
|||
await DatabaseManager.init([serverUrl]);
|
||||
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
|
||||
|
||||
jest.mocked(queryChannelsByTypes).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([]),
|
||||
} as any);
|
||||
jest.mocked(queryChannelsByTypes).mockReturnValue(TestHelper.fakeQuery([]));
|
||||
|
||||
DatabaseManager.getActiveServerUrl = jest.fn().mockResolvedValue(serverUrl);
|
||||
batchRecords = jest.spyOn(operator, 'batchRecords').mockResolvedValue();
|
||||
handleUsers = jest.spyOn(operator, 'handleUsers').mockResolvedValue([{id: 'user1'} as UserModel]);
|
||||
handleUsers = jest.spyOn(operator, 'handleUsers').mockResolvedValue([TestHelper.fakeUserModel({id: 'user1'})]);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
|
@ -84,17 +82,17 @@ describe('WebSocket Users Actions', () => {
|
|||
});
|
||||
|
||||
it('should handle current user update', async () => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUser({
|
||||
id: currentUserId,
|
||||
update_at: 1234,
|
||||
notify_props: {email: 'true'},
|
||||
} as UserProfile;
|
||||
notify_props: TestHelper.fakeUserNotifyProps({email: 'true'}),
|
||||
});
|
||||
|
||||
const mockCurrentUser = {
|
||||
const mockCurrentUser = TestHelper.fakeUserModel({
|
||||
id: currentUserId,
|
||||
updateAt: 1000,
|
||||
locale: 'en',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(mockCurrentUser);
|
||||
jest.mocked(fetchMe).mockResolvedValue({user: mockUser});
|
||||
|
|
@ -112,22 +110,21 @@ describe('WebSocket Users Actions', () => {
|
|||
});
|
||||
|
||||
it('should handle other user update', async () => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUser({
|
||||
id: otherUserId,
|
||||
update_at: 1234,
|
||||
};
|
||||
});
|
||||
|
||||
const mockCurrentUser = {
|
||||
const mockCurrentUser = TestHelper.fakeUserModel({
|
||||
id: currentUserId,
|
||||
updateAt: 1000,
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
jest.mocked(getCurrentUser).mockResolvedValue(mockCurrentUser);
|
||||
jest.mocked(queryUserChannelsByTypes).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([{id: 'channel-1'}]),
|
||||
} as any);
|
||||
jest.mocked(queryUserChannelsByTypes).mockReturnValue(
|
||||
TestHelper.fakeQuery([TestHelper.fakeChannelModel({id: 'channel-1'})]));
|
||||
jest.mocked(updateChannelsDisplayName).mockResolvedValue({models: []});
|
||||
handleUsers.mockResolvedValue([{id: 'model-1'}]);
|
||||
handleUsers.mockResolvedValue([TestHelper.fakeUserModel({id: 'model-1'})]);
|
||||
|
||||
const msg = {
|
||||
data: {
|
||||
|
|
@ -209,15 +206,13 @@ describe('WebSocket Users Actions', () => {
|
|||
|
||||
jest.mocked(getConfig).mockResolvedValue(mockConfig as any);
|
||||
jest.mocked(fetchUsersByIds).mockResolvedValue({
|
||||
users: [{id: otherUserId, username: 'other-user'} as UserProfile],
|
||||
users: [TestHelper.fakeUser({id: otherUserId, username: 'other-user'})],
|
||||
existingUsers: [],
|
||||
});
|
||||
|
||||
jest.mocked(queryDisplayNamePreferences).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([{
|
||||
value: 'full_name',
|
||||
}]),
|
||||
} as any);
|
||||
jest.mocked(queryDisplayNamePreferences).mockReturnValue(TestHelper.fakeQuery([TestHelper.fakePreferenceModel({
|
||||
value: 'full_name',
|
||||
})]));
|
||||
|
||||
jest.mocked(getLicense).mockResolvedValue({} as ClientLicense);
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ const CombinedUserActivity = ({
|
|||
} else {
|
||||
showModalOverCurrentContext(Screens.POST_OPTIONS, passProps, bottomSheetModalOptions(theme));
|
||||
}
|
||||
}, [post, canDelete, isTablet, intl, location]);
|
||||
}, [canDelete, post, location, isTablet, intl, theme]);
|
||||
|
||||
const renderMessage = (postType: string, userIds: string[], actorId?: string) => {
|
||||
if (!post) {
|
||||
|
|
@ -156,10 +156,10 @@ const CombinedUserActivity = ({
|
|||
(userIds[0] === currentUserId || userIds[0] === currentUsername) &&
|
||||
secureGetFromRecord(postTypeMessages, postType)?.one_you
|
||||
) {
|
||||
localeHolder = postTypeMessages[postType].one_you;
|
||||
localeHolder = postTypeMessages[postType as keyof typeof postTypeMessages].one_you;
|
||||
}
|
||||
} else {
|
||||
localeHolder = postTypeMessages[postType].two;
|
||||
localeHolder = postTypeMessages[postType as keyof typeof postTypeMessages].two;
|
||||
}
|
||||
|
||||
// We default to empty string, but this should never happen
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ export default {
|
|||
CRT_CHUNK_SIZE: 60,
|
||||
STATUS_INTERVAL: 60000,
|
||||
AUTOCOMPLETE_LIMIT_DEFAULT: 25,
|
||||
MENTION: 'mention',
|
||||
OUT_OF_OFFICE: 'ooo',
|
||||
OFFLINE: 'offline',
|
||||
AWAY: 'away',
|
||||
ONLINE: 'online',
|
||||
DND: 'dnd',
|
||||
MENTION: 'mention' as const,
|
||||
OUT_OF_OFFICE: 'ooo' as const,
|
||||
OFFLINE: 'offline' as const,
|
||||
AWAY: 'away' as const,
|
||||
ONLINE: 'online' as const,
|
||||
DND: 'dnd' as const,
|
||||
STATUS_COMMANDS: ['offline', 'away', 'online', 'dnd'],
|
||||
DEFAULT_CHANNEL: 'town-square',
|
||||
DM_CHANNEL: 'D' as const,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import {toMilliseconds} from '@utils/datetime';
|
||||
|
||||
export const PostTypes: Record<string, string> = {
|
||||
export const PostTypes = {
|
||||
CHANNEL_DELETED: 'system_channel_deleted',
|
||||
CHANNEL_UNARCHIVED: 'system_channel_restored',
|
||||
DISPLAYNAME_CHANGE: 'system_displayname_change',
|
||||
|
|
@ -35,7 +35,7 @@ export const PostTypes: Record<string, string> = {
|
|||
SYSTEM_AUTO_RESPONDER: 'system_auto_responder',
|
||||
CUSTOM_CALLS: 'custom_calls',
|
||||
CUSTOM_CALLS_RECORDING: 'custom_calls_recording',
|
||||
};
|
||||
} as const;
|
||||
|
||||
export const PostPriorityColors = {
|
||||
URGENT: '#D24B4E',
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ const {INFO, GLOBAL} = MM_TABLES.APP;
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<Model>}
|
||||
*/
|
||||
export const transformInfoRecord = ({action, database, value}: TransformerArgs): Promise<Model> => {
|
||||
const raw = value.raw as AppInfo;
|
||||
const record = value.record as InfoModel | undefined;
|
||||
export const transformInfoRecord = ({action, database, value}: TransformerArgs<InfoModel, AppInfo>): Promise<Model> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
|
||||
const fieldsMapper = (app: InfoModel) => {
|
||||
|
|
@ -46,8 +46,8 @@ export const transformInfoRecord = ({action, database, value}: TransformerArgs):
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<Model>}
|
||||
*/
|
||||
export const transformGlobalRecord = ({action, database, value}: TransformerArgs): Promise<Model> => {
|
||||
const raw = value.raw as IdValue;
|
||||
export const transformGlobalRecord = ({action, database, value}: TransformerArgs<GlobalModel, IdValue>): Promise<Model> => {
|
||||
const raw = value.raw;
|
||||
|
||||
const fieldsMapper = (global: GlobalModel) => {
|
||||
global._raw.id = raw?.id;
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ import type {
|
|||
|
||||
export interface BaseDataOperatorType {
|
||||
database: Database;
|
||||
handleRecords: <T extends Model>({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues, tableName, prepareRecordsOnly}: HandleRecordsArgs<T>, description: string) => Promise<Model[]>;
|
||||
processRecords: <T extends Model>({createOrUpdateRawValues, deleteRawValues, tableName, buildKeyRecordBy, fieldName}: ProcessRecordsArgs) => Promise<ProcessRecordResults<T>>;
|
||||
handleRecords: <T extends Model, R extends RawValue>({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues, tableName, prepareRecordsOnly}: HandleRecordsArgs<T, R>, description: string) => Promise<Model[]>;
|
||||
processRecords: <T extends Model, R extends RawValue>({createOrUpdateRawValues, deleteRawValues, tableName, buildKeyRecordBy, fieldName}: ProcessRecordsArgs<R>) => Promise<ProcessRecordResults<T, R>>;
|
||||
batchRecords: (models: Model[], description: string) => Promise<void>;
|
||||
prepareRecords: <T extends Model>({tableName, createRaws, deleteRaws, updateRaws, transformer}: OperationArgs<T>) => Promise<Model[]>;
|
||||
prepareRecords: <T extends Model, R extends RawValue>({tableName, createRaws, deleteRaws, updateRaws, transformer}: OperationArgs<T, R>) => Promise<Model[]>;
|
||||
}
|
||||
|
||||
export default class BaseDataOperator {
|
||||
|
|
@ -45,8 +45,8 @@ export default class BaseDataOperator {
|
|||
* @param {(existing: Model, newElement: RawValue) => boolean} inputsArg.buildKeyRecordBy
|
||||
* @returns {Promise<{ProcessRecordResults<T>}>}
|
||||
*/
|
||||
processRecords = async <T extends Model>({createOrUpdateRawValues = [], deleteRawValues = [], tableName, buildKeyRecordBy, fieldName, shouldUpdate}: ProcessRecordsArgs): Promise<ProcessRecordResults<T>> => {
|
||||
const getRecords = async (rawValues: RawValue[]) => {
|
||||
processRecords = async <T extends Model, R extends RawValue>({createOrUpdateRawValues = [], deleteRawValues = [], tableName, buildKeyRecordBy, fieldName, shouldUpdate}: ProcessRecordsArgs<R>): Promise<ProcessRecordResults<T, R>> => {
|
||||
const getRecords = async (rawValues: R[]) => {
|
||||
// We will query a table where one of its fields can match a range of values. Hence, here we are extracting all those potential values.
|
||||
const columnValues: string[] = getRangeOfValues({fieldName, raws: rawValues});
|
||||
|
||||
|
|
@ -69,8 +69,8 @@ export default class BaseDataOperator {
|
|||
return existingRecords;
|
||||
};
|
||||
|
||||
const createRaws: RecordPair[] = [];
|
||||
const updateRaws: RecordPair[] = [];
|
||||
const createRaws: Array<RecordPair<T, R>> = [];
|
||||
const updateRaws: Array<RecordPair<T, R>> = [];
|
||||
|
||||
// for delete flow
|
||||
const deleteRaws = await getRecords(deleteRawValues);
|
||||
|
|
@ -97,7 +97,7 @@ export default class BaseDataOperator {
|
|||
}
|
||||
|
||||
// Some raw value has an update_at field. We'll proceed to update only if the update_at value is different from the record's value in database
|
||||
const updateRecords = getValidRecordsForUpdate({
|
||||
const updateRecords = getValidRecordsForUpdate<T, R>({
|
||||
tableName,
|
||||
existingRecord,
|
||||
newValue: newElement,
|
||||
|
|
@ -129,7 +129,7 @@ export default class BaseDataOperator {
|
|||
* @param {(TransformerArgs) => Promise<T extends Model>;} transformer
|
||||
* @returns {Promise<T extends Model[]>}
|
||||
*/
|
||||
prepareRecords = async <T extends Model>({tableName, createRaws, deleteRaws, updateRaws, transformer}: OperationArgs<T>): Promise<T[]> => {
|
||||
prepareRecords = async <T extends Model, R extends RawValue>({tableName, createRaws, deleteRaws, updateRaws, transformer}: OperationArgs<T, R>): Promise<T[]> => {
|
||||
if (!this.database) {
|
||||
logWarning('Database not defined in prepareRecords');
|
||||
return [];
|
||||
|
|
@ -140,7 +140,7 @@ export default class BaseDataOperator {
|
|||
// create operation
|
||||
if (createRaws?.length) {
|
||||
const recordPromises = createRaws.map(
|
||||
(createRecord: RecordPair) => {
|
||||
(createRecord: RecordPair<T, R>) => {
|
||||
return transformer({
|
||||
database: this.database,
|
||||
tableName,
|
||||
|
|
@ -156,7 +156,7 @@ export default class BaseDataOperator {
|
|||
// update operation
|
||||
if (updateRaws?.length) {
|
||||
const recordPromises = updateRaws.map(
|
||||
(updateRecord: RecordPair) => {
|
||||
(updateRecord: RecordPair<T, R>) => {
|
||||
return transformer({
|
||||
database: this.database,
|
||||
tableName,
|
||||
|
|
@ -209,7 +209,7 @@ export default class BaseDataOperator {
|
|||
* @param {string} handleRecordsArgs.tableName
|
||||
* @returns {Promise<Model[]>}
|
||||
*/
|
||||
async handleRecords<T extends Model>({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues = [], tableName, prepareRecordsOnly = true, shouldUpdate}: HandleRecordsArgs<T>, description: string): Promise<T[]> {
|
||||
async handleRecords<T extends Model, R extends RawValue>({buildKeyRecordBy, fieldName, transformer, createOrUpdateRawValues, deleteRawValues = [], tableName, prepareRecordsOnly = true, shouldUpdate}: HandleRecordsArgs<T, R>, description: string): Promise<T[]> {
|
||||
if (!createOrUpdateRawValues.length && !deleteRawValues.length) {
|
||||
logWarning(
|
||||
`An empty "rawValues" array has been passed to the handleRecords method for tableName ${tableName}`,
|
||||
|
|
@ -217,7 +217,7 @@ export default class BaseDataOperator {
|
|||
return [];
|
||||
}
|
||||
|
||||
const {createRaws, deleteRaws, updateRaws} = await this.processRecords<T>({
|
||||
const {createRaws, deleteRaws, updateRaws} = await this.processRecords<T, R>({
|
||||
createOrUpdateRawValues,
|
||||
deleteRawValues,
|
||||
tableName,
|
||||
|
|
@ -227,7 +227,7 @@ export default class BaseDataOperator {
|
|||
});
|
||||
|
||||
let models: T[] = [];
|
||||
models = await this.prepareRecords<T>({
|
||||
models = await this.prepareRecords<T, R>({
|
||||
tableName,
|
||||
createRaws,
|
||||
updateRaws,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export interface ChannelHandlerMix {
|
|||
handleChannelMembership: ({channelMemberships, prepareRecordsOnly}: HandleChannelMembershipArgs) => Promise<ChannelMembershipModel[]>;
|
||||
handleMyChannelSettings: ({settings, prepareRecordsOnly}: HandleMyChannelSettingsArgs) => Promise<MyChannelSettingsModel[]>;
|
||||
handleChannelInfo: ({channelInfos, prepareRecordsOnly}: HandleChannelInfoArgs) => Promise<ChannelInfoModel[]>;
|
||||
handleMyChannel: ({channels, myChannels, isCRTEnabled, prepareRecordsOnly}: HandleMyChannelArgs) => Promise<Model[]>;
|
||||
handleMyChannel: ({channels, myChannels, isCRTEnabled, prepareRecordsOnly}: HandleMyChannelArgs) => Promise<MyChannelModel[]>;
|
||||
}
|
||||
|
||||
const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(superclass: TBase) => class extends superclass {
|
||||
|
|
@ -63,7 +63,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
return [];
|
||||
}
|
||||
|
||||
const uniqueRaws = getUniqueRawsBy({raws: channels, key: 'id'}) as Channel[];
|
||||
const uniqueRaws = getUniqueRawsBy({raws: channels, key: 'id'});
|
||||
const keys = uniqueRaws.map((c) => c.id);
|
||||
const db: Database = this.database;
|
||||
const existing = await db.get<ChannelModel>(CHANNEL).query(
|
||||
|
|
@ -113,7 +113,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
return [];
|
||||
}
|
||||
|
||||
const uniqueRaws = getUniqueRawsBy({raws: settings, key: 'id'}) as ChannelMembership[];
|
||||
const uniqueRaws = getUniqueRawsBy({raws: settings, key: 'id'});
|
||||
const keys = uniqueRaws.map((c) => c.channel_id);
|
||||
const db: Database = this.database;
|
||||
const existing = await db.get<MyChannelSettingsModel>(MY_CHANNEL_SETTINGS).query(
|
||||
|
|
@ -173,7 +173,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
const uniqueRaws = getUniqueRawsBy({
|
||||
raws: channelInfos as ChannelInfo[],
|
||||
key: 'id',
|
||||
}) as ChannelInfo[];
|
||||
});
|
||||
const keys = uniqueRaws.map((ci) => ci.id);
|
||||
const db: Database = this.database;
|
||||
const existing = await db.get<ChannelInfoModel>(CHANNEL_INFO).query(
|
||||
|
|
@ -221,7 +221,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
* @param {boolean} myChannelsArgs.prepareRecordsOnly
|
||||
* @returns {Promise<MyChannelModel[]>}
|
||||
*/
|
||||
handleMyChannel = async ({channels, myChannels, isCRTEnabled, prepareRecordsOnly = true}: HandleMyChannelArgs): Promise<Model[]> => {
|
||||
handleMyChannel = async ({channels, myChannels, isCRTEnabled, prepareRecordsOnly = true}: HandleMyChannelArgs): Promise<MyChannelModel[]> => {
|
||||
if (!myChannels?.length) {
|
||||
logWarning(
|
||||
'An empty or undefined "myChannels" array has been passed to the handleMyChannel method',
|
||||
|
|
@ -261,7 +261,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
const uniqueRaws = getUniqueRawsBy({
|
||||
raws: myChannels,
|
||||
key: 'id',
|
||||
}) as ChannelMembership[];
|
||||
});
|
||||
const ids = uniqueRaws.map((cm: ChannelMembership) => cm.channel_id);
|
||||
const db: Database = this.database;
|
||||
const existing = await db.get<MyChannelModel>(MY_CHANNEL).query(
|
||||
|
|
@ -322,7 +322,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
id: `${m.channel_id}-${m.user_id}`,
|
||||
}));
|
||||
|
||||
const uniqueRaws = getUniqueRawsBy({raws: memberships, key: 'id'}) as ChannelMember[];
|
||||
const uniqueRaws = getUniqueRawsBy({raws: memberships, key: 'id'});
|
||||
const ids = uniqueRaws.map((cm: ChannelMember) => `${cm.channel_id}-${cm.user_id}`);
|
||||
const db: Database = this.database;
|
||||
const existing = await db.get<ChannelMembershipModel>(CHANNEL_MEMBERSHIP).query(
|
||||
|
|
@ -372,7 +372,7 @@ const ChannelHandler = <TBase extends Constructor<ServerDataOperatorBase>>(super
|
|||
return [];
|
||||
}
|
||||
|
||||
const uniqueRaws = getUniqueRawsBy({raws: bookmarks, key: 'id'}) as ChannelBookmarkWithFileInfo[];
|
||||
const uniqueRaws = getUniqueRawsBy({raws: bookmarks, key: 'id'});
|
||||
const keys = uniqueRaws.map((c) => c.id);
|
||||
const db: Database = this.database;
|
||||
const existing = await db.get<ChannelBookmarkModel>(CHANNEL_BOOKMARK).query(
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ export default class ServerDataOperatorBase extends BaseDataOperator {
|
|||
return res;
|
||||
}, {createOrUpdateFiles: [], deleteFiles: []});
|
||||
|
||||
const processedFiles = (await this.processRecords<FileModel>({
|
||||
const processedFiles = (await this.processRecords<FileModel, FileInfo>({
|
||||
createOrUpdateRawValues: raws.createOrUpdateFiles,
|
||||
tableName: FILE,
|
||||
fieldName: 'id',
|
||||
|
|
@ -187,7 +187,7 @@ export default class ServerDataOperatorBase extends BaseDataOperator {
|
|||
shouldUpdate: shouldUpdateFileRecord,
|
||||
}));
|
||||
|
||||
const preparedFiles = await this.prepareRecords<FileModel>({
|
||||
const preparedFiles = await this.prepareRecords<FileModel, FileInfo>({
|
||||
createRaws: processedFiles.createRaws,
|
||||
updateRaws: processedFiles.updateRaws,
|
||||
deleteRaws: processedFiles.deleteRaws,
|
||||
|
|
@ -215,7 +215,7 @@ export default class ServerDataOperatorBase extends BaseDataOperator {
|
|||
* @param {(TransformerArgs) => Promise<Model>} execute.recordOperator
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async execute<T extends Model>({createRaws, transformer, tableName, updateRaws}: OperationArgs<T>, description: string): Promise<T[]> {
|
||||
async execute<T extends Model, R extends RawValue>({createRaws, transformer, tableName, updateRaws}: OperationArgs<T, R>, description: string): Promise<T[]> {
|
||||
const models = await this.prepareRecords({
|
||||
tableName,
|
||||
createRaws,
|
||||
|
|
|
|||
|
|
@ -601,15 +601,15 @@ const PostHandler = <TBase extends Constructor<ServerDataOperatorBase>>(supercla
|
|||
return [];
|
||||
}
|
||||
|
||||
const update: RecordPair[] = [];
|
||||
const update: Array<RecordPair<PostsInThreadModel, PostsInThread>> = [];
|
||||
const create: PostsInThread[] = [];
|
||||
const ids = Object.keys(postsMap);
|
||||
for await (const rootId of ids) {
|
||||
const {firstPost, lastPost} = getPostListEdges(postsMap[rootId]);
|
||||
const chunks = (await this.database.get(POSTS_IN_THREAD).query(
|
||||
const chunks = (await this.database.get<PostsInThreadModel>(POSTS_IN_THREAD).query(
|
||||
Q.where('root_id', rootId),
|
||||
Q.sortBy('latest', Q.desc),
|
||||
).fetch()) as PostsInThreadModel[];
|
||||
).fetch());
|
||||
|
||||
if (chunks.length) {
|
||||
const chunk = chunks[0];
|
||||
|
|
@ -633,12 +633,12 @@ const PostHandler = <TBase extends Constructor<ServerDataOperatorBase>>(supercla
|
|||
}
|
||||
}
|
||||
|
||||
const postInThreadRecords = (await this.prepareRecords({
|
||||
const postInThreadRecords = await this.prepareRecords<PostsInThreadModel, PostsInThread>({
|
||||
createRaws: getRawRecordPairs(create),
|
||||
updateRaws: update,
|
||||
transformer: transformPostInThreadRecord,
|
||||
tableName: POSTS_IN_THREAD,
|
||||
})) as PostsInThreadModel[];
|
||||
});
|
||||
|
||||
if (postInThreadRecords?.length && !prepareRecordsOnly) {
|
||||
await this.batchRecords(postInThreadRecords, 'handleReceivedPostsInThread');
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const TeamThreadsSyncHandler = <TBase extends Constructor<ServerDataOperatorBase
|
|||
}, {});
|
||||
|
||||
const create: TeamThreadsSync[] = [];
|
||||
const update: RecordPair[] = [];
|
||||
const update: Array<RecordPair<TeamThreadsSyncModel, TeamThreadsSync>> = [];
|
||||
|
||||
for await (const item of uniqueRaws) {
|
||||
const {id} = item;
|
||||
|
|
@ -54,12 +54,12 @@ const TeamThreadsSyncHandler = <TBase extends Constructor<ServerDataOperatorBase
|
|||
}
|
||||
}
|
||||
|
||||
const models = (await this.prepareRecords({
|
||||
const models = await this.prepareRecords<TeamThreadsSyncModel, TeamThreadsSync>({
|
||||
createRaws: getRawRecordPairs(create),
|
||||
updateRaws: update,
|
||||
transformer: transformTeamThreadsSyncRecord,
|
||||
tableName: TEAM_THREADS_SYNC,
|
||||
})) as TeamThreadsSyncModel[];
|
||||
});
|
||||
|
||||
if (models?.length && !prepareRecordsOnly) {
|
||||
await this.batchRecords(models, 'handleTeamThreadsSync');
|
||||
|
|
|
|||
|
|
@ -20,19 +20,22 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<CategoryModel>}
|
||||
*/
|
||||
export const transformCategoryRecord = ({action, database, value}: TransformerArgs): Promise<CategoryModel> => {
|
||||
const raw = value.raw as Category;
|
||||
const record = value.record as CategoryModel;
|
||||
export const transformCategoryRecord = ({action, database, value}: TransformerArgs<CategoryModel, Category>) => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// id of category comes from server response
|
||||
const fieldsMapper = (category: CategoryModel) => {
|
||||
category._raw.id = isCreateAction ? (raw?.id ?? category.id) : record.id;
|
||||
category._raw.id = isCreateAction ? (raw?.id ?? category.id) : record!.id;
|
||||
category.displayName = raw.display_name;
|
||||
category.sorting = raw.sorting || 'recent';
|
||||
category.sortOrder = raw.sort_order === 0 ? 0 : raw.sort_order / 10; // Sort order from server is in multiples of 10
|
||||
category.muted = raw.muted ?? false;
|
||||
category.collapsed = isCreateAction ? false : record.collapsed;
|
||||
category.collapsed = isCreateAction ? false : record!.collapsed;
|
||||
category.type = raw.type;
|
||||
category.teamId = raw.team_id;
|
||||
};
|
||||
|
|
@ -43,7 +46,7 @@ export const transformCategoryRecord = ({action, database, value}: TransformerAr
|
|||
tableName: CATEGORY,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<CategoryModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -53,14 +56,17 @@ export const transformCategoryRecord = ({action, database, value}: TransformerAr
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<CategoryChannelModel>}
|
||||
*/
|
||||
export const transformCategoryChannelRecord = ({action, database, value}: TransformerArgs): Promise<CategoryChannelModel> => {
|
||||
const raw = value.raw as CategoryChannel;
|
||||
const record = value.record as CategoryChannelModel;
|
||||
export const transformCategoryChannelRecord = ({action, database, value}: TransformerArgs<CategoryChannelModel, CategoryChannel>) => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (categoryChannel: CategoryChannelModel) => {
|
||||
categoryChannel._raw.id = isCreateAction ? (raw?.id ?? categoryChannel.id) : record.id;
|
||||
categoryChannel._raw.id = isCreateAction ? (raw?.id ?? categoryChannel.id) : record!.id;
|
||||
categoryChannel.channelId = raw.channel_id;
|
||||
categoryChannel.categoryId = raw.category_id;
|
||||
categoryChannel.sortOrder = raw.sort_order;
|
||||
|
|
@ -72,5 +78,5 @@ export const transformCategoryChannelRecord = ({action, database, value}: Transf
|
|||
tableName: CATEGORY_CHANNEL,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<CategoryChannelModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ describe('*** CHANNEL Prepare Records Test ***', () => {
|
|||
record: undefined,
|
||||
raw: {
|
||||
id: 'c',
|
||||
channel_id: 'c',
|
||||
guest_count: 10,
|
||||
header: 'channel info header',
|
||||
member_count: 10,
|
||||
|
|
|
|||
|
|
@ -29,14 +29,17 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ChannelModel>}
|
||||
*/
|
||||
export const transformChannelRecord = ({action, database, value}: TransformerArgs): Promise<ChannelModel> => {
|
||||
const raw = value.raw as Channel;
|
||||
const record = value.record as ChannelModel;
|
||||
export const transformChannelRecord = ({action, database, value}: TransformerArgs<ChannelModel, Channel>): Promise<ChannelModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (channel: ChannelModel) => {
|
||||
channel._raw.id = isCreateAction ? (raw?.id ?? channel.id) : record.id;
|
||||
channel._raw.id = isCreateAction ? (raw?.id ?? channel.id) : record!.id;
|
||||
channel.createAt = raw.create_at;
|
||||
channel.creatorId = raw.creator_id;
|
||||
channel.deleteAt = raw.delete_at;
|
||||
|
|
@ -56,7 +59,7 @@ export const transformChannelRecord = ({action, database, value}: TransformerArg
|
|||
tableName: CHANNEL,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ChannelModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -66,13 +69,16 @@ export const transformChannelRecord = ({action, database, value}: TransformerArg
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<MyChannelSettingsModel>}
|
||||
*/
|
||||
export const transformMyChannelSettingsRecord = ({action, database, value}: TransformerArgs): Promise<MyChannelSettingsModel> => {
|
||||
const raw = value.raw as ChannelMembership;
|
||||
const record = value.record as MyChannelSettingsModel;
|
||||
export const transformMyChannelSettingsRecord = ({action, database, value}: TransformerArgs<MyChannelSettingsModel, ChannelMembership>): Promise<MyChannelSettingsModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (myChannelSetting: MyChannelSettingsModel) => {
|
||||
myChannelSetting._raw.id = isCreateAction ? (raw.channel_id || myChannelSetting.id) : record.id;
|
||||
myChannelSetting._raw.id = isCreateAction ? (raw.channel_id || myChannelSetting.id) : record!.id;
|
||||
myChannelSetting.notifyProps = raw.notify_props;
|
||||
};
|
||||
|
||||
|
|
@ -82,7 +88,7 @@ export const transformMyChannelSettingsRecord = ({action, database, value}: Tran
|
|||
tableName: MY_CHANNEL_SETTINGS,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<MyChannelSettingsModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -92,13 +98,16 @@ export const transformMyChannelSettingsRecord = ({action, database, value}: Tran
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ChannelInfoModel>}
|
||||
*/
|
||||
export const transformChannelInfoRecord = ({action, database, value}: TransformerArgs): Promise<ChannelInfoModel> => {
|
||||
const raw = value.raw as Partial<ChannelInfo>;
|
||||
const record = value.record as ChannelInfoModel;
|
||||
export const transformChannelInfoRecord = ({action, database, value}: TransformerArgs<ChannelInfoModel, ChannelInfo>): Promise<ChannelInfoModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (channelInfo: ChannelInfoModel) => {
|
||||
channelInfo._raw.id = isCreateAction ? (raw.id || channelInfo.id) : record.id;
|
||||
channelInfo._raw.id = isCreateAction ? (raw.id || channelInfo.id) : record!.id;
|
||||
channelInfo.guestCount = raw.guest_count ?? channelInfo.guestCount ?? 0;
|
||||
channelInfo.header = raw.header ?? channelInfo.header ?? '';
|
||||
channelInfo.memberCount = raw.member_count ?? channelInfo.memberCount ?? 0;
|
||||
|
|
@ -113,7 +122,7 @@ export const transformChannelInfoRecord = ({action, database, value}: Transforme
|
|||
tableName: CHANNEL_INFO,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ChannelInfoModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -123,13 +132,16 @@ export const transformChannelInfoRecord = ({action, database, value}: Transforme
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<MyChannelModel>}
|
||||
*/
|
||||
export const transformMyChannelRecord = async ({action, database, value}: TransformerArgs): Promise<MyChannelModel> => {
|
||||
const raw = value.raw as ChannelMembership;
|
||||
const record = value.record as MyChannelModel;
|
||||
export const transformMyChannelRecord = async ({action, database, value}: TransformerArgs<MyChannelModel, ChannelMembership>): Promise<MyChannelModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (myChannel: MyChannelModel) => {
|
||||
myChannel._raw.id = isCreateAction ? (raw.channel_id || myChannel.id) : record.id;
|
||||
myChannel._raw.id = isCreateAction ? (raw.channel_id || myChannel.id) : record!.id;
|
||||
myChannel.roles = raw.roles;
|
||||
|
||||
// ignoring msg_count_root because msg_count, mention_count, last_post_at is already calculated in "handleMyChannel" based on CRT is enabled or not
|
||||
|
|
@ -149,7 +161,7 @@ export const transformMyChannelRecord = async ({action, database, value}: Transf
|
|||
tableName: MY_CHANNEL,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<MyChannelModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -159,14 +171,17 @@ export const transformMyChannelRecord = async ({action, database, value}: Transf
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ChannelMembershipModel>}
|
||||
*/
|
||||
export const transformChannelMembershipRecord = ({action, database, value}: TransformerArgs): Promise<ChannelMembershipModel> => {
|
||||
const raw = value.raw as ChannelMembership;
|
||||
const record = value.record as ChannelMembershipModel;
|
||||
export const transformChannelMembershipRecord = ({action, database, value}: TransformerArgs<ChannelMembershipModel, ChannelMembership>): Promise<ChannelMembershipModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (channelMember: ChannelMembershipModel) => {
|
||||
channelMember._raw.id = isCreateAction ? (raw?.id ?? channelMember.id) : record.id;
|
||||
channelMember._raw.id = isCreateAction ? (raw?.id ?? channelMember.id) : record!.id;
|
||||
channelMember.channelId = raw.channel_id;
|
||||
channelMember.userId = raw.user_id;
|
||||
channelMember.schemeAdmin = raw.scheme_admin ?? false;
|
||||
|
|
@ -178,7 +193,7 @@ export const transformChannelMembershipRecord = ({action, database, value}: Tran
|
|||
tableName: CHANNEL_MEMBERSHIP,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ChannelMembershipModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -188,14 +203,17 @@ export const transformChannelMembershipRecord = ({action, database, value}: Tran
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ChannelBookmarkModel>}
|
||||
*/
|
||||
export const transformChannelBookmarkRecord = ({action, database, value}: TransformerArgs): Promise<ChannelBookmarkModel> => {
|
||||
const raw = value.raw as ChannelBookmark;
|
||||
const record = value.record as ChannelBookmarkModel;
|
||||
export const transformChannelBookmarkRecord = ({action, database, value}: TransformerArgs<ChannelBookmarkModel, ChannelBookmark>): Promise<ChannelBookmarkModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (bookmark: ChannelBookmarkModel) => {
|
||||
bookmark._raw.id = isCreateAction ? (raw?.id ?? bookmark.id) : record.id;
|
||||
bookmark._raw.id = isCreateAction ? (raw?.id ?? bookmark.id) : record!.id;
|
||||
bookmark.createAt = raw.create_at;
|
||||
bookmark.deleteAt = raw.delete_at;
|
||||
bookmark.updateAt = raw.update_at;
|
||||
|
|
@ -219,5 +237,5 @@ export const transformChannelBookmarkRecord = ({action, database, value}: Transf
|
|||
tableName: CHANNEL_BOOKMARK,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ChannelBookmarkModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ describe('*** System Prepare Records Test ***', () => {
|
|||
database: database!,
|
||||
value: {
|
||||
record: undefined,
|
||||
raw: {id: 'system-1', name: 'system-name-1', value: 'system'},
|
||||
raw: {id: 'system-1', value: 'system'},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<CustomEmojiModel>}
|
||||
*/
|
||||
export const transformCustomEmojiRecord = ({action, database, value}: TransformerArgs): Promise<CustomEmojiModel> => {
|
||||
const raw = value.raw as CustomEmoji;
|
||||
const record = value.record as CustomEmojiModel;
|
||||
export const transformCustomEmojiRecord = ({action, database, value}: TransformerArgs<CustomEmojiModel, CustomEmoji>): Promise<CustomEmojiModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (emoji: CustomEmojiModel) => {
|
||||
emoji._raw.id = isCreateAction ? (raw?.id ?? emoji.id) : record.id;
|
||||
emoji._raw.id = isCreateAction ? (raw?.id ?? emoji.id) : record!.id;
|
||||
emoji.name = raw.name;
|
||||
};
|
||||
|
||||
|
|
@ -43,7 +46,7 @@ export const transformCustomEmojiRecord = ({action, database, value}: Transforme
|
|||
tableName: CUSTOM_EMOJI,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<CustomEmojiModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -53,14 +56,17 @@ export const transformCustomEmojiRecord = ({action, database, value}: Transforme
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<RoleModel>}
|
||||
*/
|
||||
export const transformRoleRecord = ({action, database, value}: TransformerArgs): Promise<RoleModel> => {
|
||||
const raw = value.raw as Role;
|
||||
const record = value.record as RoleModel;
|
||||
export const transformRoleRecord = ({action, database, value}: TransformerArgs<RoleModel, Role>): Promise<RoleModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (role: RoleModel) => {
|
||||
role._raw.id = isCreateAction ? (raw?.id ?? role.id) : record.id;
|
||||
role._raw.id = isCreateAction ? (raw?.id ?? role.id) : record!.id;
|
||||
role.name = raw?.name;
|
||||
role.permissions = raw?.permissions;
|
||||
};
|
||||
|
|
@ -71,7 +77,7 @@ export const transformRoleRecord = ({action, database, value}: TransformerArgs):
|
|||
tableName: ROLE,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<RoleModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -81,8 +87,8 @@ export const transformRoleRecord = ({action, database, value}: TransformerArgs):
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<SystemModel>}
|
||||
*/
|
||||
export const transformSystemRecord = ({action, database, value}: TransformerArgs): Promise<SystemModel> => {
|
||||
const raw = value.raw as IdValue;
|
||||
export const transformSystemRecord = ({action, database, value}: TransformerArgs<SystemModel, IdValue>): Promise<SystemModel> => {
|
||||
const raw = value.raw;
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (system: SystemModel) => {
|
||||
|
|
@ -96,7 +102,7 @@ export const transformSystemRecord = ({action, database, value}: TransformerArgs
|
|||
tableName: SYSTEM,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<SystemModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -106,8 +112,8 @@ export const transformSystemRecord = ({action, database, value}: TransformerArgs
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ConfigModel>}
|
||||
*/
|
||||
export const transformConfigRecord = ({action, database, value}: TransformerArgs): Promise<ConfigModel> => {
|
||||
const raw = value.raw as IdValue;
|
||||
export const transformConfigRecord = ({action, database, value}: TransformerArgs<ConfigModel, IdValue>): Promise<ConfigModel> => {
|
||||
const raw = value.raw;
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (config: ConfigModel) => {
|
||||
|
|
@ -121,7 +127,7 @@ export const transformConfigRecord = ({action, database, value}: TransformerArgs
|
|||
tableName: CONFIG,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ConfigModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -131,14 +137,17 @@ export const transformConfigRecord = ({action, database, value}: TransformerArgs
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<FileModel>}
|
||||
*/
|
||||
export const transformFileRecord = ({action, database, value}: TransformerArgs): Promise<FileModel> => {
|
||||
const raw = value.raw as FileInfo;
|
||||
const record = value.record as FileModel;
|
||||
export const transformFileRecord = ({action, database, value}: TransformerArgs<FileModel, FileInfo>): Promise<FileModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (file: FileModel) => {
|
||||
file._raw.id = isCreateAction ? (raw.id || file.id) : record.id;
|
||||
file._raw.id = isCreateAction ? (raw.id || file.id) : record!.id;
|
||||
file.postId = raw.post_id || '';
|
||||
file.name = raw.name;
|
||||
file.extension = raw.extension;
|
||||
|
|
@ -156,5 +165,5 @@ export const transformFileRecord = ({action, database, value}: TransformerArgs):
|
|||
tableName: FILE,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<FileModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<GroupModel>}
|
||||
*/
|
||||
export const transformGroupRecord = ({action, database, value}: TransformerArgs): Promise<GroupModel> => {
|
||||
const raw = value.raw as Group;
|
||||
const record = value.record as GroupModel;
|
||||
export const transformGroupRecord = ({action, database, value}: TransformerArgs<GroupModel, Group>): Promise<GroupModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// id of group comes from server response
|
||||
const fieldsMapper = (group: GroupModel) => {
|
||||
group._raw.id = isCreateAction ? (raw?.id ?? group.id) : record.id;
|
||||
group._raw.id = isCreateAction ? (raw?.id ?? group.id) : record!.id;
|
||||
group.name = raw.name;
|
||||
group.displayName = raw.display_name;
|
||||
group.source = raw.source;
|
||||
|
|
@ -47,7 +50,7 @@ export const transformGroupRecord = ({action, database, value}: TransformerArgs)
|
|||
tableName: GROUP,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<GroupModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -57,8 +60,8 @@ export const transformGroupRecord = ({action, database, value}: TransformerArgs)
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<GroupChannelModel>}
|
||||
*/
|
||||
export const transformGroupChannelRecord = ({action, database, value}: TransformerArgs): Promise<GroupChannelModel> => {
|
||||
const raw = value.raw as GroupChannel;
|
||||
export const transformGroupChannelRecord = ({action, database, value}: TransformerArgs<GroupChannelModel, GroupChannel>): Promise<GroupChannelModel> => {
|
||||
const raw = value.raw;
|
||||
|
||||
// id of group comes from server response
|
||||
const fieldsMapper = (model: GroupChannelModel) => {
|
||||
|
|
@ -73,7 +76,7 @@ export const transformGroupChannelRecord = ({action, database, value}: Transform
|
|||
tableName: GROUP_CHANNEL,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<GroupChannelModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -83,8 +86,8 @@ export const transformGroupChannelRecord = ({action, database, value}: Transform
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<GroupMembershipModel>}
|
||||
*/
|
||||
export const transformGroupMembershipRecord = ({action, database, value}: TransformerArgs): Promise<GroupMembershipModel> => {
|
||||
const raw = value.raw as GroupMembership;
|
||||
export const transformGroupMembershipRecord = ({action, database, value}: TransformerArgs<GroupMembershipModel, GroupMembership>): Promise<GroupMembershipModel> => {
|
||||
const raw = value.raw;
|
||||
|
||||
// id of group comes from server response
|
||||
const fieldsMapper = (model: GroupMembershipModel) => {
|
||||
|
|
@ -99,7 +102,7 @@ export const transformGroupMembershipRecord = ({action, database, value}: Transf
|
|||
tableName: GROUP_MEMBERSHIP,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<GroupMembershipModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -109,8 +112,8 @@ export const transformGroupMembershipRecord = ({action, database, value}: Transf
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<GroupTeamModel>}
|
||||
*/
|
||||
export const transformGroupTeamRecord = ({action, database, value}: TransformerArgs): Promise<GroupTeamModel> => {
|
||||
const raw = value.raw as GroupTeam;
|
||||
export const transformGroupTeamRecord = ({action, database, value}: TransformerArgs<GroupTeamModel, GroupTeam>): Promise<GroupTeamModel> => {
|
||||
const raw = value.raw;
|
||||
|
||||
// id of group comes from server response
|
||||
const fieldsMapper = (model: GroupTeamModel) => {
|
||||
|
|
@ -125,5 +128,5 @@ export const transformGroupTeamRecord = ({action, database, value}: TransformerA
|
|||
tableName: GROUP_TEAM,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<GroupTeamModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,17 +17,17 @@ import type {PrepareBaseRecordArgs} from '@typings/database/database';
|
|||
* @param {((PrepareBaseRecordArgs) => void)} operatorBase.generator
|
||||
* @returns {Promise<Model>}
|
||||
*/
|
||||
export const prepareBaseRecord = async ({
|
||||
export const prepareBaseRecord = async <T extends Model, R extends RawValue>({
|
||||
action,
|
||||
database,
|
||||
tableName,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}: PrepareBaseRecordArgs): Promise<Model> => {
|
||||
}: PrepareBaseRecordArgs<T, R>) => {
|
||||
if (action === OperationType.UPDATE) {
|
||||
const record = value.record as Model;
|
||||
const record = value.record!;
|
||||
return record.prepareUpdate(() => fieldsMapper(record));
|
||||
}
|
||||
|
||||
return database.collections.get(tableName!).prepareCreate(fieldsMapper);
|
||||
return database.collections.get<T>(tableName!).prepareCreate(fieldsMapper);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ describe('*** POST Prepare Records Test ***', () => {
|
|||
value: {
|
||||
record: undefined,
|
||||
raw: {
|
||||
id: 'ps81i4yypoo',
|
||||
root_id: 'ps81iqbddesfby8jayz7owg4yypoo',
|
||||
message: 'draft message',
|
||||
channel_id: 'channel_idp23232e',
|
||||
|
|
|
|||
|
|
@ -24,14 +24,17 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<PostModel>}
|
||||
*/
|
||||
export const transformPostRecord = ({action, database, value}: TransformerArgs): Promise<PostModel> => {
|
||||
const raw = value.raw as Post;
|
||||
const record = value.record as PostModel;
|
||||
export const transformPostRecord = ({action, database, value}: TransformerArgs<PostModel, Post>): Promise<PostModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (post: PostModel) => {
|
||||
post._raw.id = isCreateAction ? (raw?.id ?? post.id) : record.id;
|
||||
post._raw.id = isCreateAction ? (raw?.id ?? post.id) : record!.id;
|
||||
post.channelId = raw.channel_id;
|
||||
post.createAt = raw.create_at;
|
||||
post.deleteAt = raw.delete_at || raw.delete_at === 0 ? raw?.delete_at : 0;
|
||||
|
|
@ -61,7 +64,7 @@ export const transformPostRecord = ({action, database, value}: TransformerArgs):
|
|||
tableName: POST,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<PostModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -71,13 +74,16 @@ export const transformPostRecord = ({action, database, value}: TransformerArgs):
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<PostsInThreadModel>}
|
||||
*/
|
||||
export const transformPostInThreadRecord = ({action, database, value}: TransformerArgs): Promise<PostsInThreadModel> => {
|
||||
const raw = value.raw as PostsInThread;
|
||||
const record = value.record as PostsInThreadModel;
|
||||
export const transformPostInThreadRecord = ({action, database, value}: TransformerArgs<PostsInThreadModel, PostsInThread>) => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (postsInThread: PostsInThreadModel) => {
|
||||
postsInThread._raw.id = isCreateAction ? (raw.id || postsInThread.id) : record.id;
|
||||
postsInThread._raw.id = isCreateAction ? (raw.id || postsInThread.id) : record!.id;
|
||||
postsInThread.rootId = raw.root_id;
|
||||
postsInThread.earliest = raw.earliest;
|
||||
postsInThread.latest = raw.latest!;
|
||||
|
|
@ -89,7 +95,7 @@ export const transformPostInThreadRecord = ({action, database, value}: Transform
|
|||
tableName: POSTS_IN_THREAD,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<PostsInThreadModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -99,10 +105,10 @@ export const transformPostInThreadRecord = ({action, database, value}: Transform
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<DraftModel>}
|
||||
*/
|
||||
export const transformDraftRecord = ({action, database, value}: TransformerArgs): Promise<DraftModel> => {
|
||||
export const transformDraftRecord = ({action, database, value}: TransformerArgs<DraftModel, Draft>): Promise<DraftModel> => {
|
||||
const emptyFileInfo: FileInfo[] = [];
|
||||
const emptyPostMetadata: PostMetadata = {};
|
||||
const raw = value.raw as Draft;
|
||||
const raw = value.raw;
|
||||
|
||||
// We use the raw id as Draft is client side only and we would only be creating/deleting drafts
|
||||
const fieldsMapper = (draft: DraftModel) => {
|
||||
|
|
@ -121,7 +127,7 @@ export const transformDraftRecord = ({action, database, value}: TransformerArgs)
|
|||
tableName: DRAFT,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<DraftModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -131,13 +137,16 @@ export const transformDraftRecord = ({action, database, value}: TransformerArgs)
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<PostsInChannelModel>}
|
||||
*/
|
||||
export const transformPostsInChannelRecord = ({action, database, value}: TransformerArgs): Promise<PostsInChannelModel> => {
|
||||
const raw = value.raw as PostsInChannel;
|
||||
const record = value.record as PostsInChannelModel;
|
||||
export const transformPostsInChannelRecord = ({action, database, value}: TransformerArgs<PostsInChannelModel, PostsInChannel>): Promise<PostsInChannelModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (postsInChannel: PostsInChannelModel) => {
|
||||
postsInChannel._raw.id = isCreateAction ? (raw.id || postsInChannel.id) : record.id;
|
||||
postsInChannel._raw.id = isCreateAction ? (raw.id || postsInChannel.id) : record!.id;
|
||||
postsInChannel.channelId = raw.channel_id;
|
||||
postsInChannel.earliest = raw.earliest;
|
||||
postsInChannel.latest = raw.latest;
|
||||
|
|
@ -149,5 +158,5 @@ export const transformPostsInChannelRecord = ({action, database, value}: Transfo
|
|||
tableName: POSTS_IN_CHANNEL,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<PostsInChannelModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ describe('*** REACTION Prepare Records Test ***', () => {
|
|||
post_id: 'ps81iqbddesfby8jayz7owg4yypoo',
|
||||
emoji_name: 'thumbsup',
|
||||
create_at: 1596032651748,
|
||||
update_at: 1608253011321,
|
||||
delete_at: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,14 +16,17 @@ const {REACTION} = MM_TABLES.SERVER;
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ReactionModel>}
|
||||
*/
|
||||
export const transformReactionRecord = ({action, database, value}: TransformerArgs): Promise<ReactionModel> => {
|
||||
const raw = value.raw as Reaction;
|
||||
const record = value.record as ReactionModel;
|
||||
export const transformReactionRecord = ({action, database, value}: TransformerArgs<ReactionModel, Reaction>): Promise<ReactionModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// id of reaction comes from server response
|
||||
const fieldsMapper = (reaction: ReactionModel) => {
|
||||
reaction._raw.id = isCreateAction ? (raw?.id ?? reaction.id) : record.id;
|
||||
reaction._raw.id = isCreateAction ? (raw?.id ?? reaction.id) : record!.id;
|
||||
reaction.userId = raw.user_id;
|
||||
reaction.postId = raw.post_id;
|
||||
reaction.emojiName = raw.emoji_name;
|
||||
|
|
@ -36,5 +39,5 @@ export const transformReactionRecord = ({action, database, value}: TransformerAr
|
|||
tableName: REACTION,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ReactionModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<TeamMembershipModel>}
|
||||
*/
|
||||
export const transformTeamMembershipRecord = ({action, database, value}: TransformerArgs): Promise<TeamMembershipModel> => {
|
||||
const raw = value.raw as TeamMembership;
|
||||
const record = value.record as TeamMembershipModel;
|
||||
export const transformTeamMembershipRecord = ({action, database, value}: TransformerArgs<TeamMembershipModel, TeamMembership>): Promise<TeamMembershipModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (teamMembership: TeamMembershipModel) => {
|
||||
teamMembership._raw.id = isCreateAction ? (raw?.id ?? teamMembership.id) : record.id;
|
||||
teamMembership._raw.id = isCreateAction ? (raw?.id ?? teamMembership.id) : record!.id;
|
||||
teamMembership.teamId = raw.team_id;
|
||||
teamMembership.userId = raw.user_id;
|
||||
teamMembership.schemeAdmin = raw.scheme_admin;
|
||||
|
|
@ -45,7 +48,7 @@ export const transformTeamMembershipRecord = ({action, database, value}: Transfo
|
|||
tableName: TEAM_MEMBERSHIP,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<TeamMembershipModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -55,14 +58,17 @@ export const transformTeamMembershipRecord = ({action, database, value}: Transfo
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<TeamModel>}
|
||||
*/
|
||||
export const transformTeamRecord = ({action, database, value}: TransformerArgs): Promise<TeamModel> => {
|
||||
const raw = value.raw as Team;
|
||||
const record = value.record as TeamModel;
|
||||
export const transformTeamRecord = ({action, database, value}: TransformerArgs<TeamModel, Team>): Promise<TeamModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (team: TeamModel) => {
|
||||
team._raw.id = isCreateAction ? (raw?.id ?? team.id) : record.id;
|
||||
team._raw.id = isCreateAction ? (raw?.id ?? team.id) : record!.id;
|
||||
team.isAllowOpenInvite = raw.allow_open_invite;
|
||||
team.description = raw.description;
|
||||
team.displayName = raw.display_name;
|
||||
|
|
@ -81,7 +87,7 @@ export const transformTeamRecord = ({action, database, value}: TransformerArgs):
|
|||
tableName: TEAM,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<TeamModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -91,13 +97,16 @@ export const transformTeamRecord = ({action, database, value}: TransformerArgs):
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<TeamChannelHistoryModel>}
|
||||
*/
|
||||
export const transformTeamChannelHistoryRecord = ({action, database, value}: TransformerArgs): Promise<TeamChannelHistoryModel> => {
|
||||
const raw = value.raw as TeamChannelHistory;
|
||||
const record = value.record as TeamChannelHistoryModel;
|
||||
export const transformTeamChannelHistoryRecord = ({action, database, value}: TransformerArgs<TeamChannelHistoryModel, TeamChannelHistory>): Promise<TeamChannelHistoryModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (teamChannelHistory: TeamChannelHistoryModel) => {
|
||||
teamChannelHistory._raw.id = isCreateAction ? (raw.id || teamChannelHistory.id) : record.id;
|
||||
teamChannelHistory._raw.id = isCreateAction ? (raw.id || teamChannelHistory.id) : record!.id;
|
||||
teamChannelHistory.channelIds = raw.channel_ids;
|
||||
};
|
||||
|
||||
|
|
@ -107,7 +116,7 @@ export const transformTeamChannelHistoryRecord = ({action, database, value}: Tra
|
|||
tableName: TEAM_CHANNEL_HISTORY,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<TeamChannelHistoryModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -117,13 +126,16 @@ export const transformTeamChannelHistoryRecord = ({action, database, value}: Tra
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<TeamSearchHistoryModel>}
|
||||
*/
|
||||
export const transformTeamSearchHistoryRecord = ({action, database, value}: TransformerArgs): Promise<TeamSearchHistoryModel> => {
|
||||
const raw = value.raw as TeamSearchHistory;
|
||||
const record = value.record as TeamSearchHistoryModel;
|
||||
export const transformTeamSearchHistoryRecord = ({action, database, value}: TransformerArgs<TeamSearchHistoryModel, TeamSearchHistory>): Promise<TeamSearchHistoryModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (teamSearchHistory: TeamSearchHistoryModel) => {
|
||||
teamSearchHistory._raw.id = isCreateAction ? (teamSearchHistory.id) : record.id;
|
||||
teamSearchHistory._raw.id = isCreateAction ? (teamSearchHistory.id) : record!.id;
|
||||
teamSearchHistory.createdAt = raw.created_at;
|
||||
teamSearchHistory.displayTerm = raw.display_term;
|
||||
teamSearchHistory.term = raw.term;
|
||||
|
|
@ -136,7 +148,7 @@ export const transformTeamSearchHistoryRecord = ({action, database, value}: Tran
|
|||
tableName: TEAM_SEARCH_HISTORY,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<TeamSearchHistoryModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -146,13 +158,16 @@ export const transformTeamSearchHistoryRecord = ({action, database, value}: Tran
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<MyTeamModel>}
|
||||
*/
|
||||
export const transformMyTeamRecord = ({action, database, value}: TransformerArgs): Promise<MyTeamModel> => {
|
||||
const raw = value.raw as MyTeam;
|
||||
const record = value.record as MyTeamModel;
|
||||
export const transformMyTeamRecord = ({action, database, value}: TransformerArgs<MyTeamModel, MyTeam>): Promise<MyTeamModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (myTeam: MyTeamModel) => {
|
||||
myTeam._raw.id = isCreateAction ? (raw.id || myTeam.id) : record.id;
|
||||
myTeam._raw.id = isCreateAction ? (raw.id || myTeam.id) : record!.id;
|
||||
myTeam.roles = raw.roles;
|
||||
};
|
||||
|
||||
|
|
@ -162,5 +177,5 @@ export const transformMyTeamRecord = ({action, database, value}: TransformerArgs
|
|||
tableName: MY_TEAM,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<MyTeamModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,14 +24,17 @@ const {
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ThreadModel>}
|
||||
*/
|
||||
export const transformThreadRecord = ({action, database, value}: TransformerArgs): Promise<ThreadModel> => {
|
||||
const raw = value.raw as ThreadWithLastFetchedAt;
|
||||
const record = value.record as ThreadModel;
|
||||
export const transformThreadRecord = ({action, database, value}: TransformerArgs<ThreadModel, ThreadWithLastFetchedAt>): Promise<ThreadModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// If isCreateAction is true, we will use the id (API response) from the RAW, else we shall use the existing record id from the database
|
||||
const fieldsMapper = (thread: ThreadModel) => {
|
||||
thread._raw.id = isCreateAction ? (raw?.id ?? thread.id) : record.id;
|
||||
thread._raw.id = isCreateAction ? (raw?.id ?? thread.id) : record!.id;
|
||||
|
||||
// When post is individually fetched, we get last_reply_at as 0, so we use the record's value.
|
||||
// If there is no reply at, we default to the post's create_at
|
||||
|
|
@ -39,7 +42,7 @@ export const transformThreadRecord = ({action, database, value}: TransformerArgs
|
|||
|
||||
thread.lastViewedAt = raw.last_viewed_at ?? record?.lastViewedAt ?? 0;
|
||||
thread.replyCount = raw.reply_count;
|
||||
thread.isFollowing = raw.is_following ?? record?.isFollowing;
|
||||
thread.isFollowing = raw.is_following ?? record?.isFollowing ?? false;
|
||||
thread.unreadReplies = raw.unread_replies ?? record?.unreadReplies ?? 0;
|
||||
thread.unreadMentions = raw.unread_mentions ?? record?.unreadMentions ?? 0;
|
||||
thread.viewedAt = record?.viewedAt || 0;
|
||||
|
|
@ -52,7 +55,7 @@ export const transformThreadRecord = ({action, database, value}: TransformerArgs
|
|||
tableName: THREAD,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ThreadModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -62,14 +65,17 @@ export const transformThreadRecord = ({action, database, value}: TransformerArgs
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<ThreadParticipantModel>}
|
||||
*/
|
||||
export const transformThreadParticipantRecord = ({action, database, value}: TransformerArgs): Promise<ThreadParticipantModel> => {
|
||||
const raw = value.raw as ThreadParticipant;
|
||||
const record = value.record as ThreadParticipantModel;
|
||||
export const transformThreadParticipantRecord = ({action, database, value}: TransformerArgs<ThreadParticipantModel, ThreadParticipant>): Promise<ThreadParticipantModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
// id of participant comes from server response
|
||||
const fieldsMapper = (participant: ThreadParticipantModel) => {
|
||||
participant._raw.id = isCreateAction ? `${raw.thread_id}-${raw.id}` : record.id;
|
||||
participant._raw.id = isCreateAction ? `${raw.thread_id}-${raw.id}` : record!.id;
|
||||
participant.threadId = raw.thread_id;
|
||||
participant.userId = raw.id;
|
||||
};
|
||||
|
|
@ -80,16 +86,19 @@ export const transformThreadParticipantRecord = ({action, database, value}: Tran
|
|||
tableName: THREAD_PARTICIPANT,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ThreadParticipantModel>;
|
||||
});
|
||||
};
|
||||
|
||||
export const transformThreadInTeamRecord = ({action, database, value}: TransformerArgs): Promise<ThreadInTeamModel> => {
|
||||
const raw = value.raw as ThreadInTeam;
|
||||
const record = value.record as ThreadInTeamModel;
|
||||
export const transformThreadInTeamRecord = ({action, database, value}: TransformerArgs<ThreadInTeamModel, ThreadInTeam>): Promise<ThreadInTeamModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (threadInTeam: ThreadInTeamModel) => {
|
||||
threadInTeam._raw.id = isCreateAction ? `${raw.thread_id}-${raw.team_id}` : record.id;
|
||||
threadInTeam._raw.id = isCreateAction ? `${raw.thread_id}-${raw.team_id}` : record!.id;
|
||||
threadInTeam.threadId = raw.thread_id;
|
||||
threadInTeam.teamId = raw.team_id;
|
||||
};
|
||||
|
|
@ -100,18 +109,21 @@ export const transformThreadInTeamRecord = ({action, database, value}: Transform
|
|||
tableName: THREADS_IN_TEAM,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<ThreadInTeamModel>;
|
||||
});
|
||||
};
|
||||
|
||||
export const transformTeamThreadsSyncRecord = ({action, database, value}: TransformerArgs): Promise<TeamThreadsSyncModel> => {
|
||||
const raw = value.raw as TeamThreadsSync;
|
||||
const record = value.record as TeamThreadsSyncModel;
|
||||
export const transformTeamThreadsSyncRecord = ({action, database, value}: TransformerArgs<TeamThreadsSyncModel, TeamThreadsSync>): Promise<TeamThreadsSyncModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
if (!isCreateAction && !record) {
|
||||
throw new Error('Record not found for non create action');
|
||||
}
|
||||
|
||||
const fieldsMapper = (teamThreadsSync: TeamThreadsSyncModel) => {
|
||||
teamThreadsSync._raw.id = isCreateAction ? (raw?.id ?? teamThreadsSync.id) : record.id;
|
||||
teamThreadsSync.earliest = raw.earliest || record?.earliest;
|
||||
teamThreadsSync.latest = raw.latest || record?.latest;
|
||||
teamThreadsSync._raw.id = isCreateAction ? (raw?.id ?? teamThreadsSync.id) : record!.id;
|
||||
teamThreadsSync.earliest = raw.earliest || record?.earliest || 0;
|
||||
teamThreadsSync.latest = raw.latest || record?.latest || 0;
|
||||
};
|
||||
|
||||
return prepareBaseRecord({
|
||||
|
|
@ -120,5 +132,5 @@ export const transformTeamThreadsSyncRecord = ({action, database, value}: Transf
|
|||
tableName: TEAM_THREADS_SYNC,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<TeamThreadsSyncModel>;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,14 +17,14 @@ const {PREFERENCE, USER} = MM_TABLES.SERVER;
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<UserModel>}
|
||||
*/
|
||||
export const transformUserRecord = ({action, database, value}: TransformerArgs): Promise<UserModel> => {
|
||||
const raw = value.raw as UserProfile;
|
||||
const record = value.record as UserModel;
|
||||
export const transformUserRecord = ({action, database, value}: TransformerArgs<UserModel, UserProfile>): Promise<UserModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
|
||||
// id of user comes from server response
|
||||
const fieldsMapper = (user: UserModel) => {
|
||||
user._raw.id = isCreateAction ? (raw?.id ?? user.id) : record.id;
|
||||
user._raw.id = isCreateAction ? (raw?.id ?? user.id) : record?.id || '';
|
||||
user.authService = raw.auth_service;
|
||||
user.deleteAt = raw.delete_at;
|
||||
user.updateAt = raw.update_at;
|
||||
|
|
@ -71,7 +71,7 @@ export const transformUserRecord = ({action, database, value}: TransformerArgs):
|
|||
tableName: USER,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<UserModel>;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -81,14 +81,14 @@ export const transformUserRecord = ({action, database, value}: TransformerArgs):
|
|||
* @param {RecordPair} operator.value
|
||||
* @returns {Promise<PreferenceModel>}
|
||||
*/
|
||||
export const transformPreferenceRecord = ({action, database, value}: TransformerArgs): Promise<PreferenceModel> => {
|
||||
const raw = value.raw as PreferenceType;
|
||||
const record = value.record as PreferenceModel;
|
||||
export const transformPreferenceRecord = ({action, database, value}: TransformerArgs<PreferenceModel, PreferenceType>): Promise<PreferenceModel> => {
|
||||
const raw = value.raw;
|
||||
const record = value.record;
|
||||
const isCreateAction = action === OperationType.CREATE;
|
||||
|
||||
// id of preference comes from server response
|
||||
const fieldsMapper = (preference: PreferenceModel) => {
|
||||
preference._raw.id = isCreateAction ? preference.id : record.id;
|
||||
preference._raw.id = isCreateAction ? preference.id : record?.id || '';
|
||||
preference.category = raw.category;
|
||||
preference.name = raw.name;
|
||||
preference.userId = raw.user_id;
|
||||
|
|
@ -101,6 +101,6 @@ export const transformPreferenceRecord = ({action, database, value}: Transformer
|
|||
tableName: PREFERENCE,
|
||||
value,
|
||||
fieldsMapper,
|
||||
}) as Promise<PreferenceModel>;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ import {MM_TABLES} from '@constants/database';
|
|||
|
||||
import type {Model} from '@nozbe/watermelondb';
|
||||
import type {IdenticalRecordArgs, RangeOfValueArgs, RecordPair, RetrieveRecordsArgs} from '@typings/database/database';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const {CHANNEL, POST, TEAM, USER} = MM_TABLES.SERVER;
|
||||
|
||||
|
|
@ -21,13 +17,12 @@ const {CHANNEL, POST, TEAM, USER} = MM_TABLES.SERVER;
|
|||
* @param {Model} identicalRecord.existingRecord
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const getValidRecordsForUpdate = ({tableName, newValue, existingRecord}: IdenticalRecordArgs) => {
|
||||
export const getValidRecordsForUpdate = <T extends Model, R extends RawValue>({tableName, newValue, existingRecord}: IdenticalRecordArgs<T, R>) => {
|
||||
const guardTables = [CHANNEL, POST, TEAM, USER];
|
||||
if (guardTables.includes(tableName)) {
|
||||
type Raw = Post | UserProfile | Team | SlashCommand | Channel;
|
||||
type ExistingRecord = PostModel | UserModel | TeamModel | ChannelModel;
|
||||
|
||||
const shouldUpdate = (newValue as Raw).update_at === (existingRecord as ExistingRecord).updateAt;
|
||||
const newValueUpdateAt = ('update_at' in newValue) ? newValue.update_at : 0;
|
||||
const existingRecordUpdateAt = ('updateAt' in existingRecord) ? existingRecord.updateAt : 0;
|
||||
const shouldUpdate = newValueUpdateAt === existingRecordUpdateAt;
|
||||
|
||||
if (shouldUpdate) {
|
||||
return {
|
||||
|
|
@ -66,7 +61,7 @@ export const getRangeOfValues = ({fieldName, raws}: RangeOfValueArgs) => {
|
|||
* @param {any[]} raws
|
||||
* @returns {{record: undefined, raw: any}[]}
|
||||
*/
|
||||
export const getRawRecordPairs = (raws: any[]): RecordPair[] => {
|
||||
export const getRawRecordPairs = <T extends Model, R extends RawValue>(raws: R[]): Array<RecordPair<T, R>> => {
|
||||
return raws.map((raw) => {
|
||||
return {raw, record: undefined};
|
||||
});
|
||||
|
|
@ -78,7 +73,7 @@ export const getRawRecordPairs = (raws: any[]): RecordPair[] => {
|
|||
* @param {RawValue[]} raws
|
||||
* @param {string} key
|
||||
*/
|
||||
export const getUniqueRawsBy = ({raws, key}: { raws: RawValue[]; key: string}) => {
|
||||
export const getUniqueRawsBy = <T extends RawValue>({raws, key}: { raws: T[]; key: string}) => {
|
||||
return [...new Map(raws.map((item) => {
|
||||
const curItemKey = item[key as keyof typeof item];
|
||||
return [curItemKey, item];
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export const sanitizeReactions = async ({database, post_id, rawReactions, skipSy
|
|||
// similarObjects: Contains objects that are in both the RawReaction array and in the Reaction table
|
||||
const similarObjects = new Set<ReactionModel>();
|
||||
|
||||
const createReactions: RecordPair[] = [];
|
||||
const createReactions: Array<RecordPair<ReactionModel, Reaction>> = [];
|
||||
|
||||
const reactionsMap = reactions.reduce((result: Record<string, ReactionModel>, reaction) => {
|
||||
result[`${reaction.userId}-${reaction.emojiName}`] = reaction;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export const sanitizeThreadParticipants = async ({database, skipSync, thread_id,
|
|||
// similarObjects: Contains objects that are in both the RawParticipant array and in the ThreadParticipant table
|
||||
const similarObjects = new Set<ThreadParticipantModel>();
|
||||
|
||||
const createParticipants: RecordPair[] = [];
|
||||
const createParticipants: Array<RecordPair<ThreadParticipantModel, ThreadParticipant>> = [];
|
||||
const participantsMap = participants.reduce((result: Record<string, ThreadParticipantModel>, participant) => {
|
||||
result[participant.userId] = participant;
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
// See LICENSE.txt for license information.
|
||||
import {renderHook} from '@testing-library/react-hooks';
|
||||
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {getUsersByUsername} from '@utils/user';
|
||||
|
||||
import {useMemoMentionedUser, useMemoMentionedGroup} from './markdown';
|
||||
|
||||
import type {GroupModel, UserModel} from '@database/models/server';
|
||||
|
||||
jest.mock('@utils/user', () => ({
|
||||
getUsersByUsername: jest.fn(),
|
||||
}));
|
||||
|
|
@ -16,7 +15,7 @@ const mockGetUsersByUsername = jest.mocked(getUsersByUsername);
|
|||
|
||||
describe('useMemoMentionedUser', () => {
|
||||
it('should return the mentioned user if found', () => {
|
||||
const users = [{username: 'john_doe'} as UserModel];
|
||||
const users = [TestHelper.fakeUserModel({username: 'john_doe'})];
|
||||
const mentionName = 'john_doe';
|
||||
const usersByUsername = {john_doe: users[0]};
|
||||
mockGetUsersByUsername.mockReturnValue(usersByUsername);
|
||||
|
|
@ -27,7 +26,7 @@ describe('useMemoMentionedUser', () => {
|
|||
});
|
||||
|
||||
it('should return undefined if the mentioned user is not found', () => {
|
||||
const users = [{username: 'john_doe'} as UserModel];
|
||||
const users = [TestHelper.fakeUserModel({username: 'john_doe'})];
|
||||
const mentionName = 'jane_doe';
|
||||
const usersByUsername = {john_doe: users[0]};
|
||||
mockGetUsersByUsername.mockReturnValue(usersByUsername);
|
||||
|
|
@ -38,7 +37,7 @@ describe('useMemoMentionedUser', () => {
|
|||
});
|
||||
|
||||
it('should trim trailing punctuation from the mention name', () => {
|
||||
const users = [{username: 'john_doe'} as UserModel];
|
||||
const users = [TestHelper.fakeUserModel({username: 'john_doe'})];
|
||||
const mentionName = 'john_doe.';
|
||||
const usersByUsername = {john_doe: users[0]};
|
||||
mockGetUsersByUsername.mockReturnValue(usersByUsername);
|
||||
|
|
@ -51,7 +50,7 @@ describe('useMemoMentionedUser', () => {
|
|||
|
||||
describe('useMemoMentionedGroup', () => {
|
||||
it('should return the mentioned group if found', () => {
|
||||
const groups = [{name: 'developers'} as GroupModel];
|
||||
const groups = [TestHelper.fakeGroupModel({name: 'developers'})];
|
||||
const user = undefined;
|
||||
const mentionName = 'developers';
|
||||
|
||||
|
|
@ -61,7 +60,7 @@ describe('useMemoMentionedGroup', () => {
|
|||
});
|
||||
|
||||
it('should return undefined if the mentioned group is not found', () => {
|
||||
const groups = [{name: 'developers'} as GroupModel];
|
||||
const groups = [TestHelper.fakeGroupModel({name: 'developers'})];
|
||||
const user = undefined;
|
||||
const mentionName = 'designers';
|
||||
|
||||
|
|
@ -71,8 +70,8 @@ describe('useMemoMentionedGroup', () => {
|
|||
});
|
||||
|
||||
it('should return undefined if the user is defined', () => {
|
||||
const groups = [{name: 'developers'} as GroupModel];
|
||||
const user = {username: 'john_doe'} as UserModel;
|
||||
const groups = [TestHelper.fakeGroupModel({name: 'developers'})];
|
||||
const user = TestHelper.fakeUserModel({username: 'john_doe'});
|
||||
const mentionName = 'developers';
|
||||
|
||||
const {result} = renderHook(() => useMemoMentionedGroup(groups, user, mentionName));
|
||||
|
|
@ -81,7 +80,7 @@ describe('useMemoMentionedGroup', () => {
|
|||
});
|
||||
|
||||
it('should trim trailing punctuation from the mention name', () => {
|
||||
const groups = [{name: 'developers'} as GroupModel];
|
||||
const groups = [TestHelper.fakeGroupModel({name: 'developers'})];
|
||||
const user = undefined;
|
||||
const mentionName = 'developers.';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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
|
||||
|
|
@ -70,13 +72,15 @@ import {
|
|||
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';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@calls/alerts');
|
||||
|
||||
jest.mock('@constants/calls', () => ({
|
||||
...jest.requireActual('@constants/calls'),
|
||||
CALL_QUALITY_RESET_MS: 100,
|
||||
}));
|
||||
|
||||
|
|
@ -97,12 +101,13 @@ jest.mock('@queries/servers/channel', () => ({
|
|||
}));
|
||||
|
||||
jest.mock('@queries/servers/user', () => ({
|
||||
getUserById: jest.fn(() => Promise.resolve({
|
||||
username: 'user-5',
|
||||
})),
|
||||
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({
|
||||
|
|
@ -305,14 +310,14 @@ describe('useCallsState', () => {
|
|||
},
|
||||
};
|
||||
const expectedChannelsWithCallsState = initialChannelsWithCallsState;
|
||||
const expectedCurrentCallState = {
|
||||
const expectedCurrentCallState: CurrentCall = {
|
||||
...initialCurrentCallState,
|
||||
...expectedCallsState['channel-1'],
|
||||
} as CurrentCall;
|
||||
};
|
||||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -325,11 +330,11 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => userJoinedCall('server1', 'channel-1', 'user-3', 'session3'));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls, expectedCallsState);
|
||||
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] as CallsState).calls, expectedCallsState);
|
||||
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
||||
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
||||
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
||||
});
|
||||
|
|
@ -365,14 +370,14 @@ describe('useCallsState', () => {
|
|||
},
|
||||
};
|
||||
const expectedChannelsWithCallsState = initialChannelsWithCallsState;
|
||||
const expectedCurrentCallState = {
|
||||
const expectedCurrentCallState: CurrentCall = {
|
||||
...initialCurrentCallState,
|
||||
...expectedCallsState['channel-1'],
|
||||
} as CurrentCall;
|
||||
};
|
||||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -385,11 +390,11 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => userLeftCall('server1', 'channel-1', 'session1'));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls, expectedCallsState);
|
||||
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] as CallsState).calls, expectedCallsState);
|
||||
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
||||
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
||||
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
||||
});
|
||||
|
|
@ -438,7 +443,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -451,7 +456,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => userLeftCall('server1', 'channel-1', 'session1'));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls, expectedCallsState);
|
||||
assert.deepEqual(result.current[0].calls, expectedCallsState);
|
||||
assert.deepEqual(result.current[1], expectedChannelsWithCallsState);
|
||||
assert.deepEqual(result.current[2], expectedCurrentCallState);
|
||||
});
|
||||
|
|
@ -469,7 +474,7 @@ describe('useCallsState', () => {
|
|||
await DatabaseManager.init(['server1']);
|
||||
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
assert.deepEqual(result.current[0], DefaultCallsState);
|
||||
assert.deepEqual(result.current[1], {});
|
||||
|
|
@ -480,7 +485,7 @@ describe('useCallsState', () => {
|
|||
setCurrentCall(initialCurrentCallState);
|
||||
await callStarted('server1', call1);
|
||||
});
|
||||
assert.deepEqual((result.current[0] as CallsState).calls, {'channel-1': 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();
|
||||
|
|
@ -533,7 +538,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -546,19 +551,19 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => setUserMuted('server1', 'channel-1', 'session1', true));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls['channel-1'].sessions.session1.muted, true);
|
||||
assert.deepEqual((result.current[2] as CurrentCall | null)?.sessions.session1.muted, 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] as CallsState).calls['channel-1'].sessions.session1.muted, false);
|
||||
assert.deepEqual((result.current[0] as CallsState).calls['channel-1'].sessions.session2.muted, false);
|
||||
assert.deepEqual((result.current[2] as CurrentCall | null)?.sessions.session1.muted, false);
|
||||
assert.deepEqual((result.current[2] as CurrentCall | null)?.sessions.session2.muted, 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] as CallsState).calls['channel-1'].sessions.session2.muted, true);
|
||||
assert.deepEqual((result.current[2] as CurrentCall | null)?.sessions.session2.muted, 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);
|
||||
|
|
@ -579,7 +584,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -592,9 +597,9 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => setCallScreenOn('server1', 'channel-1', 'session1'));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls['channel-1'].screenOn, 'session1');
|
||||
assert.deepEqual((result.current[0]).calls['channel-1'].screenOn, 'session1');
|
||||
assert.deepEqual(result.current[1], initialChannelsWithCallsState);
|
||||
assert.deepEqual((result.current[2] as CurrentCall).screenOn, 'session1');
|
||||
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);
|
||||
|
|
@ -644,7 +649,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -655,12 +660,12 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => setRaisedHand('server1', 'channel-1', 'session2', 345));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls, expectedCalls);
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null), expectedCurrentCallState);
|
||||
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] as CallsState).calls, expectedCalls);
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null), expectedCurrentCallState);
|
||||
assert.deepEqual((result.current[0]).calls, expectedCalls);
|
||||
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
||||
|
||||
// unraise hand:
|
||||
act(() => setRaisedHand('server1', 'channel-1', 'session2', 0));
|
||||
|
|
@ -772,7 +777,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => setCallsState('server1', initialCallsState));
|
||||
assert.deepEqual(result.current[0], initialCallsState);
|
||||
|
|
@ -781,9 +786,9 @@ describe('useCallsState', () => {
|
|||
// 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] as CurrentCall | null)?.screenShareURL, '');
|
||||
assert.deepEqual((result.current[1])?.screenShareURL, '');
|
||||
act(() => setScreenShareURL('testUrl'));
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.screenShareURL, 'testUrl');
|
||||
assert.deepEqual((result.current[1])?.screenShareURL, 'testUrl');
|
||||
|
||||
act(() => {
|
||||
myselfLeftCall();
|
||||
|
|
@ -817,7 +822,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => setCallsState('server1', initialCallsState));
|
||||
assert.deepEqual(result.current[0], initialCallsState);
|
||||
|
|
@ -826,11 +831,11 @@ describe('useCallsState', () => {
|
|||
// test
|
||||
act(() => newCurrentCall('server1', 'channel-1', 'myUserId'));
|
||||
act(() => userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId'));
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.speakerphoneOn, false);
|
||||
assert.deepEqual((result.current[1])?.speakerphoneOn, false);
|
||||
act(() => setSpeakerPhone(true));
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.speakerphoneOn, true);
|
||||
assert.deepEqual((result.current[1])?.speakerphoneOn, true);
|
||||
act(() => setSpeakerPhone(false));
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.speakerphoneOn, false);
|
||||
assert.deepEqual((result.current[1])?.speakerphoneOn, false);
|
||||
assert.deepEqual(result.current[0], expectedCallsState);
|
||||
act(() => {
|
||||
myselfLeftCall();
|
||||
|
|
@ -872,7 +877,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => setCallsState('server1', initialCallsState));
|
||||
assert.deepEqual(result.current[0], initialCallsState);
|
||||
|
|
@ -881,10 +886,10 @@ describe('useCallsState', () => {
|
|||
// test
|
||||
act(() => newCurrentCall('server1', 'channel-1', 'myUserId'));
|
||||
act(() => userJoinedCall('server1', 'channel-1', 'myUserId', 'mySessionId'));
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.audioDeviceInfo, defaultAudioDeviceInfo);
|
||||
assert.deepEqual((result.current[1])?.audioDeviceInfo, defaultAudioDeviceInfo);
|
||||
act(() => setAudioDeviceInfo(newAudioDeviceInfo));
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.audioDeviceInfo, newAudioDeviceInfo);
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null)?.speakerphoneOn, false);
|
||||
assert.deepEqual((result.current[1])?.audioDeviceInfo, newAudioDeviceInfo);
|
||||
assert.deepEqual((result.current[1])?.speakerphoneOn, false);
|
||||
assert.deepEqual(result.current[0], expectedCallsState);
|
||||
act(() => {
|
||||
myselfLeftCall();
|
||||
|
|
@ -1025,7 +1030,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => setCallsState('server1', initialCallsState));
|
||||
assert.deepEqual(result.current[0], initialCallsState);
|
||||
|
|
@ -1041,8 +1046,8 @@ describe('useCallsState', () => {
|
|||
|
||||
// call quality goes bad
|
||||
act(() => processMeanOpinionScore(3.4999));
|
||||
assert.deepEqual((result.current[1] as CurrentCall).callQualityAlert, true);
|
||||
assert.equal((result.current[1] as CurrentCall).callQualityAlertDismissed, 0);
|
||||
assert.deepEqual((result.current[1])?.callQualityAlert, true);
|
||||
assert.equal((result.current[1])?.callQualityAlertDismissed, 0);
|
||||
|
||||
// call quality goes good
|
||||
act(() => processMeanOpinionScore(4));
|
||||
|
|
@ -1050,26 +1055,26 @@ describe('useCallsState', () => {
|
|||
|
||||
// call quality goes bad
|
||||
act(() => processMeanOpinionScore(3.499));
|
||||
assert.deepEqual((result.current[1] as CurrentCall).callQualityAlert, true);
|
||||
assert.equal((result.current[1] as CurrentCall).callQualityAlertDismissed, 0);
|
||||
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] as CurrentCall).callQualityAlert, false);
|
||||
assert.equal((result.current[1] as CurrentCall).callQualityAlertDismissed >= timeNow &&
|
||||
(result.current[1] as CurrentCall).callQualityAlertDismissed <= Date.now(), true);
|
||||
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] as CurrentCall).callQualityAlert, false);
|
||||
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] as CurrentCall).callQualityAlert, true);
|
||||
assert.deepEqual((result.current[1])?.callQualityAlert, true);
|
||||
});
|
||||
|
||||
it('voiceOn and Off', async () => {
|
||||
|
|
@ -1265,7 +1270,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -1276,11 +1281,11 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => setRecordingState('server1', 'channel-1', recState));
|
||||
assert.deepEqual((result.current[0] as CallsState), expectedCallsState);
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null), expectedCurrentCallState);
|
||||
assert.deepEqual((result.current[0]), expectedCallsState);
|
||||
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
||||
act(() => setRecordingState('server1', 'channel-2', recState));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls['channel-2'], {...call2, recState});
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null), expectedCurrentCallState);
|
||||
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();
|
||||
});
|
||||
|
|
@ -1318,7 +1323,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -1329,11 +1334,11 @@ describe('useCallsState', () => {
|
|||
|
||||
// test
|
||||
act(() => setHost('server1', 'channel-1', 'user-52'));
|
||||
assert.deepEqual((result.current[0] as CallsState), expectedCallsState);
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null), expectedCurrentCallState);
|
||||
assert.deepEqual((result.current[0]), expectedCallsState);
|
||||
assert.deepEqual((result.current[1]), expectedCurrentCallState);
|
||||
act(() => setHost('server1', 'channel-2', 'user-1923'));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls['channel-2'], {...call2, hostId: 'user-1923'});
|
||||
assert.deepEqual((result.current[1] as CurrentCall | null), expectedCurrentCallState);
|
||||
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();
|
||||
});
|
||||
|
|
@ -1352,7 +1357,7 @@ describe('useCallsState', () => {
|
|||
incomingCalls: [{
|
||||
callID: 'callDM',
|
||||
callerID: 'user-5',
|
||||
callerModel: {username: 'user-5'} as UserModel,
|
||||
callerModel: user5,
|
||||
channelID: 'channel-private',
|
||||
myUserId: 'myId',
|
||||
serverUrl: 'server1',
|
||||
|
|
@ -1452,7 +1457,7 @@ describe('useCallsState', () => {
|
|||
incomingCalls: [{
|
||||
callID: 'callDM',
|
||||
callerID: 'user-5',
|
||||
callerModel: {username: 'user-5'} as UserModel,
|
||||
callerModel: TestHelper.fakeUserModel({username: 'user-5'}),
|
||||
channelID: 'channel-private',
|
||||
myUserId: 'myId',
|
||||
serverUrl: 'server1',
|
||||
|
|
@ -1576,7 +1581,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useChannelsWithCalls('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
await act(async () => {
|
||||
await setCallsState('server1', initialCallsState);
|
||||
|
|
@ -1599,7 +1604,7 @@ describe('useCallsState', () => {
|
|||
// test: update existing call
|
||||
const updatedCall1 = {...call1, screenOn: 'newScreen'};
|
||||
await act(async () => setCallForChannel('server1', 'channel-1', updatedCall1));
|
||||
assert.deepEqual((result.current[0] as CallsState).calls['channel-1'], updatedCall1);
|
||||
assert.deepEqual(result.current[0].calls['channel-1'], updatedCall1);
|
||||
assert.deepEqual(result.current[2], {...initialCurrentCallState, screenOn: 'newScreen'});
|
||||
|
||||
// test: remove call
|
||||
|
|
@ -1613,7 +1618,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// test: just update enabled state
|
||||
await act(async () => setCallForChannel('server1', 'channel-3', undefined, true));
|
||||
assert.deepEqual((result.current[0] as CallsState).enabled['channel-3'], true);
|
||||
assert.deepEqual(result.current[0].enabled['channel-3'], true);
|
||||
assert.deepEqual(result.current[1], {'channel-2': true});
|
||||
});
|
||||
|
||||
|
|
@ -1663,7 +1668,7 @@ describe('useCallsState', () => {
|
|||
|
||||
// setup
|
||||
const {result} = renderHook(() => {
|
||||
return [useCallsState('server1'), useCurrentCall()];
|
||||
return [useCallsState('server1'), useCurrentCall()] as const;
|
||||
});
|
||||
act(() => {
|
||||
setCallsState('server1', initialCallsState);
|
||||
|
|
@ -1679,9 +1684,9 @@ describe('useCallsState', () => {
|
|||
receivedCaption('server1', caption1user2Data);
|
||||
});
|
||||
assert.deepEqual(result.current[0], initialCallsState);
|
||||
let currentCall = result.current[1] as CurrentCall;
|
||||
assert.equal(currentCall.captions.session1.text, 'caption 2');
|
||||
assert.equal(currentCall.captions.session2.text, 'caption 1 user 2');
|
||||
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(() => {
|
||||
|
|
@ -1689,8 +1694,8 @@ describe('useCallsState', () => {
|
|||
receivedCaption('server1', caption2user2Data);
|
||||
});
|
||||
assert.deepEqual(result.current[0], initialCallsState);
|
||||
currentCall = result.current[1] as CurrentCall;
|
||||
assert.equal(currentCall.captions.session1.text, 'caption 3');
|
||||
assert.equal(currentCall.captions.session2.text, 'caption 2 user 2');
|
||||
currentCall = result.current[1];
|
||||
assert.equal(currentCall?.captions.session1.text, 'caption 3');
|
||||
assert.equal(currentCall?.captions.session2.text, 'caption 2 user 2');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ import {Alert} from 'react-native';
|
|||
import {SelectedTrackType} from 'react-native-video';
|
||||
|
||||
import {type CallsConfigState, DefaultCallsConfig} from '@calls/types/calls';
|
||||
import {License, Post} from '@constants';
|
||||
import {License, Post, Preferences} from '@constants';
|
||||
import {NOTIFICATION_SUB_TYPE} from '@constants/push_notification';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {
|
||||
getICEServersConfigs,
|
||||
|
|
@ -28,7 +29,6 @@ import {
|
|||
getTranscriptionUri,
|
||||
} from './utils';
|
||||
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
describe('getICEServersConfigs', () => {
|
||||
|
|
@ -136,21 +136,21 @@ describe('sortSessions', () => {
|
|||
userId: 'user1',
|
||||
muted: true,
|
||||
raisedHand: 0,
|
||||
userModel: {username: 'charlie'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'charlie'}),
|
||||
},
|
||||
2: {
|
||||
sessionId: '2',
|
||||
userId: 'user2',
|
||||
muted: true,
|
||||
raisedHand: 0,
|
||||
userModel: {username: 'alice'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
||||
},
|
||||
3: {
|
||||
sessionId: '3',
|
||||
userId: 'user3',
|
||||
muted: true,
|
||||
raisedHand: 0,
|
||||
userModel: {username: 'bob'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'bob'}),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -165,21 +165,21 @@ describe('sortSessions', () => {
|
|||
userId: 'user1',
|
||||
muted: true,
|
||||
raisedHand: 0,
|
||||
userModel: {username: 'a'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'a'}),
|
||||
},
|
||||
2: {
|
||||
sessionId: '2',
|
||||
userId: 'user2',
|
||||
muted: false,
|
||||
raisedHand: 0,
|
||||
userModel: {username: 'b'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'b'}),
|
||||
},
|
||||
3: {
|
||||
sessionId: '3',
|
||||
userId: 'user3',
|
||||
muted: true,
|
||||
raisedHand: 1000,
|
||||
userModel: {username: 'c'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'c'}),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -194,14 +194,14 @@ describe('sortSessions', () => {
|
|||
userId: 'user1',
|
||||
muted: true,
|
||||
raisedHand: 2000, // Raised hand second
|
||||
userModel: {username: 'a'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'a'}),
|
||||
},
|
||||
2: {
|
||||
sessionId: '2',
|
||||
userId: 'user2',
|
||||
muted: true,
|
||||
raisedHand: 1000, // Raised hand first
|
||||
userModel: {username: 'b'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'b'}),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -252,14 +252,14 @@ describe('getHandsRaisedNames', () => {
|
|||
sessionId: '1',
|
||||
userId: 'user1',
|
||||
raisedHand: 2000,
|
||||
userModel: {username: 'alice'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
||||
muted: false,
|
||||
},
|
||||
{
|
||||
sessionId: '2',
|
||||
userId: 'user2',
|
||||
raisedHand: 1000,
|
||||
userModel: {username: 'bob'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'bob'}),
|
||||
muted: false,
|
||||
},
|
||||
];
|
||||
|
|
@ -274,7 +274,7 @@ describe('getHandsRaisedNames', () => {
|
|||
sessionId: '1',
|
||||
userId: 'user1',
|
||||
raisedHand: 1000,
|
||||
userModel: {username: 'alice'} as UserModel,
|
||||
userModel: TestHelper.fakeUserModel({username: 'alice'}),
|
||||
muted: false,
|
||||
},
|
||||
];
|
||||
|
|
@ -318,9 +318,8 @@ describe('isHostControlsAllowed and areGroupCallsAllowed', () => {
|
|||
|
||||
describe('isCallsCustomMessage', () => {
|
||||
it('identifies calls messages', () => {
|
||||
expect(isCallsCustomMessage({type: Post.POST_TYPES.CUSTOM_CALLS} as Post)).toBe(true);
|
||||
expect(isCallsCustomMessage({type: 'regular_post' as unknown} as Post)).toBe(false);
|
||||
expect(isCallsCustomMessage({} as Post)).toBe(false);
|
||||
expect(isCallsCustomMessage(TestHelper.fakePost({type: Post.POST_TYPES.CUSTOM_CALLS}))).toBe(true);
|
||||
expect(isCallsCustomMessage(TestHelper.fakePost({type: ''}))).toBe(false); // Regular post
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -358,8 +357,9 @@ describe('errorAlert', () => {
|
|||
describe('makeCallsTheme', () => {
|
||||
it('creates calls theme from base theme', () => {
|
||||
const theme = {
|
||||
...Preferences.THEMES.denim,
|
||||
sidebarBg: '#000000',
|
||||
} as Theme;
|
||||
};
|
||||
|
||||
const callsTheme = makeCallsTheme(theme);
|
||||
|
||||
|
|
@ -415,7 +415,7 @@ describe('getTranscriptionUri', () => {
|
|||
|
||||
describe('getCallPropsFromPost', () => {
|
||||
test('undefined props', () => {
|
||||
const post = {} as Post;
|
||||
const post = TestHelper.fakePost({props: undefined});
|
||||
|
||||
const props = getCallPropsFromPost(post);
|
||||
|
||||
|
|
@ -429,9 +429,7 @@ describe('getCallPropsFromPost', () => {
|
|||
});
|
||||
|
||||
test('missing props', () => {
|
||||
const post = {
|
||||
props: {},
|
||||
} as Post;
|
||||
const post = TestHelper.fakePost({props: {}});
|
||||
|
||||
const props = getCallPropsFromPost(post);
|
||||
|
||||
|
|
@ -455,9 +453,9 @@ describe('getCallPropsFromPost', () => {
|
|||
recording_files: 45,
|
||||
};
|
||||
|
||||
const post = {
|
||||
props: callProps as unknown,
|
||||
} as Post;
|
||||
const post = TestHelper.fakePost({
|
||||
props: callProps,
|
||||
});
|
||||
|
||||
const props = getCallPropsFromPost(post);
|
||||
|
||||
|
|
@ -503,9 +501,9 @@ describe('getCallPropsFromPost', () => {
|
|||
participants: ['userA', 'userB'],
|
||||
};
|
||||
|
||||
const post = {
|
||||
props: callProps as unknown,
|
||||
} as Post;
|
||||
const post = TestHelper.fakePost({
|
||||
props: callProps,
|
||||
});
|
||||
|
||||
const props = getCallPropsFromPost(post);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
/* eslint-disable max-lines */
|
||||
|
||||
import {Database, Model, Query, Relation, Q} from '@nozbe/watermelondb';
|
||||
import {Database, Q} from '@nozbe/watermelondb';
|
||||
import {of as of$} from 'rxjs';
|
||||
|
||||
import {General, Permissions} from '@constants';
|
||||
|
|
@ -18,7 +18,6 @@ import {prepareChannels,
|
|||
prepareMyChannelsForTeam,
|
||||
prepareDeleteChannel,
|
||||
prepareDeleteBookmarks,
|
||||
type ChannelMembershipsExtended,
|
||||
queryAllChannels,
|
||||
queryAllChannelsForTeam,
|
||||
queryAllChannelsInfo,
|
||||
|
|
@ -71,13 +70,10 @@ import {queryRoles} from './role';
|
|||
import {getCurrentChannelId, observeCurrentChannelId, observeCurrentUserId} from './system';
|
||||
import {observeTeammateNameDisplay} from './user';
|
||||
|
||||
import type {UserModel} from '@database/models/server';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type ChannelBookmarkModel from '@typings/database/models/servers/channel_bookmark';
|
||||
import type ChannelInfoModel from '@typings/database/models/servers/channel_info';
|
||||
import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings';
|
||||
|
||||
jest.mock('./role');
|
||||
jest.mock('./system');
|
||||
|
|
@ -98,10 +94,22 @@ describe('prepareChannels', () => {
|
|||
});
|
||||
|
||||
it('should prepare channels, channelInfos, channelMemberships, memberships, and myChannelSettings', () => {
|
||||
const channels = [{id: 'channel1'}, {id: 'channel2'}] as Channel[];
|
||||
const channelInfos = [{id: 'channel1'}, {id: 'channel2'}] as ChannelInfo[];
|
||||
const channelMemberships = [{channel_id: 'channel1', user_id: 'user1'}, {channel_id: 'channel2', user_id: 'user2'}] as ChannelMembershipsExtended[];
|
||||
const memberships = [{channel_id: 'channel1', user_id: 'user1'}, {channel_id: 'channel2', user_id: 'user2'}] as ChannelMembership[];
|
||||
const channels = [
|
||||
TestHelper.fakeChannel({id: 'channel1'}),
|
||||
TestHelper.fakeChannel({id: 'channel2'}),
|
||||
];
|
||||
const channelInfos = [
|
||||
TestHelper.fakeChannelInfo({id: 'channel1'}),
|
||||
TestHelper.fakeChannelInfo({id: 'channel2'}),
|
||||
];
|
||||
const channelMemberships = [
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel1', user_id: 'user1'}),
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel2', user_id: 'user2'}),
|
||||
];
|
||||
const memberships = [
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel1', user_id: 'user1'}),
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel2', user_id: 'user2'}),
|
||||
];
|
||||
|
||||
const channelRecords = Promise.resolve([]);
|
||||
const channelInfoRecords = Promise.resolve([]);
|
||||
|
|
@ -109,11 +117,11 @@ describe('prepareChannels', () => {
|
|||
const myChannelRecords = Promise.resolve([]);
|
||||
const myChannelSettingsRecords = Promise.resolve([]);
|
||||
|
||||
(operator.handleChannel as jest.Mock).mockReturnValue(channelRecords);
|
||||
(operator.handleChannelInfo as jest.Mock).mockReturnValue(channelInfoRecords);
|
||||
(operator.handleChannelMembership as jest.Mock).mockReturnValue(membershipRecords);
|
||||
(operator.handleMyChannel as jest.Mock).mockReturnValue(myChannelRecords);
|
||||
(operator.handleMyChannelSettings as jest.Mock).mockReturnValue(myChannelSettingsRecords);
|
||||
jest.mocked(operator.handleChannel).mockReturnValue(channelRecords);
|
||||
jest.mocked(operator.handleChannelInfo).mockReturnValue(channelInfoRecords);
|
||||
jest.mocked(operator.handleChannelMembership).mockReturnValue(membershipRecords);
|
||||
jest.mocked(operator.handleMyChannel).mockReturnValue(myChannelRecords);
|
||||
jest.mocked(operator.handleMyChannelSettings).mockReturnValue(myChannelSettingsRecords);
|
||||
|
||||
const result = prepareChannels(operator, channels, channelInfos, channelMemberships, memberships, true);
|
||||
|
||||
|
|
@ -126,7 +134,7 @@ describe('prepareChannels', () => {
|
|||
});
|
||||
|
||||
it('should return an empty array if an error occurs', () => {
|
||||
(operator.handleChannel as jest.Mock).mockImplementation(() => {
|
||||
jest.mocked(operator.handleChannel).mockImplementation(() => {
|
||||
throw new Error('Test error');
|
||||
});
|
||||
|
||||
|
|
@ -151,13 +159,13 @@ describe('prepareMissingChannelsForAllTeams', () => {
|
|||
|
||||
it('should prepare missing channels for all teams', () => {
|
||||
const channels = [
|
||||
{id: 'channel1', header: 'header1', purpose: 'purpose1', last_post_at: 123, last_root_post_at: 456},
|
||||
{id: 'channel2', header: 'header2', purpose: 'purpose2', last_post_at: 789, last_root_post_at: 101112},
|
||||
] as Channel[];
|
||||
TestHelper.fakeChannel({id: 'channel1', header: 'header1', purpose: 'purpose1', last_post_at: 123, last_root_post_at: 456}),
|
||||
TestHelper.fakeChannel({id: 'channel2', header: 'header2', purpose: 'purpose2', last_post_at: 789, last_root_post_at: 101112}),
|
||||
];
|
||||
const channelMembers = [
|
||||
{channel_id: 'channel1', user_id: 'user1'},
|
||||
{channel_id: 'channel2', user_id: 'user2'},
|
||||
] as ChannelMembership[];
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel1', user_id: 'user1'}),
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel2', user_id: 'user2'}),
|
||||
];
|
||||
|
||||
const channelRecords = Promise.resolve([]);
|
||||
const channelInfoRecords = Promise.resolve([]);
|
||||
|
|
@ -165,11 +173,11 @@ describe('prepareMissingChannelsForAllTeams', () => {
|
|||
const myChannelRecords = Promise.resolve([]);
|
||||
const myChannelSettingsRecords = Promise.resolve([]);
|
||||
|
||||
(operator.handleChannel as jest.Mock).mockReturnValue(channelRecords);
|
||||
(operator.handleChannelInfo as jest.Mock).mockReturnValue(channelInfoRecords);
|
||||
(operator.handleChannelMembership as jest.Mock).mockReturnValue(membershipRecords);
|
||||
(operator.handleMyChannel as jest.Mock).mockReturnValue(myChannelRecords);
|
||||
(operator.handleMyChannelSettings as jest.Mock).mockReturnValue(myChannelSettingsRecords);
|
||||
jest.mocked(operator.handleChannel).mockReturnValue(channelRecords);
|
||||
jest.mocked(operator.handleChannelInfo).mockReturnValue(channelInfoRecords);
|
||||
jest.mocked(operator.handleChannelMembership).mockReturnValue(membershipRecords);
|
||||
jest.mocked(operator.handleMyChannel).mockReturnValue(myChannelRecords);
|
||||
jest.mocked(operator.handleMyChannelSettings).mockReturnValue(myChannelSettingsRecords);
|
||||
|
||||
const result = prepareMissingChannelsForAllTeams(operator, channels, channelMembers, true);
|
||||
|
||||
|
|
@ -184,31 +192,31 @@ describe('prepareMissingChannelsForAllTeams', () => {
|
|||
});
|
||||
expect(operator.handleChannelMembership).toHaveBeenCalledWith({
|
||||
channelMemberships: [
|
||||
{channel_id: 'channel1', user_id: 'user1', id: 'channel1', last_post_at: 123, last_root_post_at: 456},
|
||||
{channel_id: 'channel2', user_id: 'user2', id: 'channel2', last_post_at: 789, last_root_post_at: 101112},
|
||||
expect.objectContaining({channel_id: 'channel1', user_id: 'user1', id: 'channel1', last_post_at: 123, last_root_post_at: 456}),
|
||||
expect.objectContaining({channel_id: 'channel2', user_id: 'user2', id: 'channel2', last_post_at: 789, last_root_post_at: 101112}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
expect(operator.handleMyChannel).toHaveBeenCalledWith({
|
||||
channels,
|
||||
myChannels: [
|
||||
{channel_id: 'channel1', user_id: 'user1', id: 'channel1', last_post_at: 123, last_root_post_at: 456},
|
||||
{channel_id: 'channel2', user_id: 'user2', id: 'channel2', last_post_at: 789, last_root_post_at: 101112},
|
||||
expect.objectContaining({channel_id: 'channel1', user_id: 'user1', id: 'channel1', last_post_at: 123, last_root_post_at: 456}),
|
||||
expect.objectContaining({channel_id: 'channel2', user_id: 'user2', id: 'channel2', last_post_at: 789, last_root_post_at: 101112}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
isCRTEnabled: true,
|
||||
});
|
||||
expect(operator.handleMyChannelSettings).toHaveBeenCalledWith({
|
||||
settings: [
|
||||
{channel_id: 'channel1', user_id: 'user1', id: 'channel1', last_post_at: 123, last_root_post_at: 456},
|
||||
{channel_id: 'channel2', user_id: 'user2', id: 'channel2', last_post_at: 789, last_root_post_at: 101112},
|
||||
expect.objectContaining({channel_id: 'channel1', user_id: 'user1', id: 'channel1', last_post_at: 123, last_root_post_at: 456}),
|
||||
expect.objectContaining({channel_id: 'channel2', user_id: 'user2', id: 'channel2', last_post_at: 789, last_root_post_at: 101112}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an empty array if an error occurs', () => {
|
||||
(operator.handleChannel as jest.Mock).mockImplementation(() => {
|
||||
jest.mocked(operator.handleChannel).mockImplementation(() => {
|
||||
throw new Error('Test error');
|
||||
});
|
||||
|
||||
|
|
@ -245,13 +253,13 @@ describe('prepareMyChannelsForTeam', () => {
|
|||
it('should prepare my channels for a team', async () => {
|
||||
const teamId = 'team_id';
|
||||
const channels = [
|
||||
{id: 'channel1', header: 'header1', purpose: 'purpose1', last_post_at: 123, last_root_post_at: 456},
|
||||
{id: 'channel2', header: 'header2', purpose: 'purpose2', last_post_at: 789, last_root_post_at: 101112},
|
||||
] as Channel[];
|
||||
TestHelper.fakeChannel({id: 'channel1', header: 'header1', purpose: 'purpose1', last_post_at: 123, last_root_post_at: 456}),
|
||||
TestHelper.fakeChannel({id: 'channel2', header: 'header2', purpose: 'purpose2', last_post_at: 789, last_root_post_at: 101112}),
|
||||
];
|
||||
const channelMembers = [
|
||||
{channel_id: 'channel1', user_id: 'user1'},
|
||||
{channel_id: 'channel2', user_id: 'user2'},
|
||||
] as ChannelMembership[];
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel1', user_id: 'user1'}),
|
||||
TestHelper.fakeChannelMember({channel_id: 'channel2', user_id: 'user2'}),
|
||||
];
|
||||
|
||||
const allChannelsForTeam = {
|
||||
channel1: {id: 'channel1'},
|
||||
|
|
@ -274,11 +282,11 @@ describe('prepareMyChannelsForTeam', () => {
|
|||
const myChannelRecords = Promise.resolve([]);
|
||||
const myChannelSettingsRecords = Promise.resolve([]);
|
||||
|
||||
(operator.handleChannel as jest.Mock).mockReturnValue(channelRecords);
|
||||
(operator.handleChannelInfo as jest.Mock).mockReturnValue(channelInfoRecords);
|
||||
(operator.handleChannelMembership as jest.Mock).mockReturnValue(membershipRecords);
|
||||
(operator.handleMyChannel as jest.Mock).mockReturnValue(myChannelRecords);
|
||||
(operator.handleMyChannelSettings as jest.Mock).mockReturnValue(myChannelSettingsRecords);
|
||||
jest.mocked(operator.handleChannel).mockReturnValue(channelRecords);
|
||||
jest.mocked(operator.handleChannelInfo).mockReturnValue(channelInfoRecords);
|
||||
jest.mocked(operator.handleChannelMembership).mockReturnValue(membershipRecords);
|
||||
jest.mocked(operator.handleMyChannel).mockReturnValue(myChannelRecords);
|
||||
jest.mocked(operator.handleMyChannelSettings).mockReturnValue(myChannelSettingsRecords);
|
||||
|
||||
query = jest.fn().mockResolvedValueOnce(Object.entries(allChannelsForTeam).map((c) => c[1])).mockResolvedValueOnce(Object.entries(allChannelsInfoForTeam).map((i) => i[1]));
|
||||
const result = await prepareMyChannelsForTeam(operator, teamId, channels, channelMembers, true);
|
||||
|
|
@ -288,31 +296,31 @@ describe('prepareMyChannelsForTeam', () => {
|
|||
expect(operator.handleChannel).toHaveBeenCalledWith({channels, prepareRecordsOnly: true});
|
||||
expect(operator.handleChannelInfo).toHaveBeenCalledWith({
|
||||
channelInfos: [
|
||||
{id: 'channel1', header: 'header1', purpose: 'purpose1', guest_count: 2, member_count: 10, pinned_post_count: 1, files_count: 5},
|
||||
{id: 'channel2', header: 'header2', purpose: 'purpose2', guest_count: 3, member_count: 20, pinned_post_count: 2, files_count: 10},
|
||||
expect.objectContaining({id: 'channel1', header: 'header1', purpose: 'purpose1', guest_count: 2, member_count: 10, pinned_post_count: 1, files_count: 5}),
|
||||
expect.objectContaining({id: 'channel2', header: 'header2', purpose: 'purpose2', guest_count: 3, member_count: 20, pinned_post_count: 2, files_count: 10}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
expect(operator.handleChannelMembership).toHaveBeenCalledWith({
|
||||
channelMemberships: [
|
||||
{channel_id: 'channel1', user_id: 'user1'},
|
||||
{channel_id: 'channel2', user_id: 'user2'},
|
||||
expect.objectContaining({channel_id: 'channel1', user_id: 'user1'}),
|
||||
expect.objectContaining({channel_id: 'channel2', user_id: 'user2'}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
expect(operator.handleMyChannel).toHaveBeenCalledWith({
|
||||
channels,
|
||||
myChannels: [
|
||||
{channel_id: 'channel1', user_id: 'user1', id: 'channel1'},
|
||||
{channel_id: 'channel2', user_id: 'user2', id: 'channel2'},
|
||||
expect.objectContaining({channel_id: 'channel1', user_id: 'user1', id: 'channel1'}),
|
||||
expect.objectContaining({channel_id: 'channel2', user_id: 'user2', id: 'channel2'}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
isCRTEnabled: true,
|
||||
});
|
||||
expect(operator.handleMyChannelSettings).toHaveBeenCalledWith({
|
||||
settings: [
|
||||
{channel_id: 'channel1', user_id: 'user1', id: 'channel1'},
|
||||
{channel_id: 'channel2', user_id: 'user2', id: 'channel2'},
|
||||
expect.objectContaining({channel_id: 'channel1', user_id: 'user1', id: 'channel1'}),
|
||||
expect.objectContaining({channel_id: 'channel2', user_id: 'user2', id: 'channel2'}),
|
||||
],
|
||||
prepareRecordsOnly: true,
|
||||
});
|
||||
|
|
@ -323,38 +331,35 @@ describe('prepareDeleteChannel', () => {
|
|||
let channel: ChannelModel;
|
||||
|
||||
beforeEach(() => {
|
||||
channel = {
|
||||
channel = TestHelper.fakeChannelModel({
|
||||
prepareDestroyPermanently: jest.fn().mockReturnValue({}),
|
||||
membership: {fetch: jest.fn()} as unknown as Relation<Model>,
|
||||
info: {fetch: jest.fn()} as unknown as Relation<Model>,
|
||||
categoryChannel: {fetch: jest.fn()} as unknown as Relation<Model>,
|
||||
members: {fetch: jest.fn()} as unknown as Query<Model>,
|
||||
drafts: {fetch: jest.fn()} as unknown as Query<Model>,
|
||||
postsInChannel: {fetch: jest.fn()} as unknown as Query<Model>,
|
||||
posts: {fetch: jest.fn()} as unknown as Query<Model>,
|
||||
bookmarks: {fetch: jest.fn()} as unknown as Query<Model>,
|
||||
} as unknown as ChannelModel;
|
||||
});
|
||||
});
|
||||
|
||||
it('should prepare models for deletion', async () => {
|
||||
const prepareDestroyPermanently = jest.fn().mockReturnValue({});
|
||||
const membershipModel = {prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'membership'})};
|
||||
const infoModel = {prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'info'})};
|
||||
const categoryChannelModel = {prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'category'})};
|
||||
const memberModels = [{prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'member'})}];
|
||||
const draftModels = [{prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'draft'})}];
|
||||
const postsInChannelModels = [{prepareDestroyPermanently}];
|
||||
const postModels = [{id: 'post1', prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'post'})}];
|
||||
const bookmarkModels = [{id: 'bookmark1', prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'bookmark'})}];
|
||||
const membershipModel = TestHelper.fakeMyChannelMembershipModel({prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'membership'})});
|
||||
const infoModel = TestHelper.fakeChannelInfoModel({prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'info'})});
|
||||
const categoryChannelModel = TestHelper.fakeCategoryChannelModel({prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'category'})});
|
||||
const memberModels = [TestHelper.fakeChannelMembershipModel({prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'member'})})];
|
||||
const draftModels = [TestHelper.fakeDraftModel({prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'draft'})})];
|
||||
const postsInChannelModels = [
|
||||
TestHelper.fakePostsInChannelModel({prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'postsInChannel'})}),
|
||||
];
|
||||
const postModels = [
|
||||
TestHelper.fakePostModel({id: 'post1', prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'post'})}),
|
||||
];
|
||||
const bookmarkModels = [
|
||||
TestHelper.fakeChannelBookmarkModel({id: 'bookmark1', prepareDestroyPermanently: jest.fn().mockReturnValue({id: 'bookmark'})}),
|
||||
];
|
||||
|
||||
(channel.membership.fetch as jest.Mock).mockResolvedValue(membershipModel);
|
||||
(channel.info.fetch as jest.Mock).mockResolvedValue(infoModel);
|
||||
(channel.categoryChannel.fetch as jest.Mock).mockResolvedValue(categoryChannelModel);
|
||||
(channel.members.fetch as jest.Mock).mockResolvedValue(memberModels);
|
||||
(channel.drafts.fetch as jest.Mock).mockResolvedValue(draftModels);
|
||||
(channel.postsInChannel.fetch as jest.Mock).mockResolvedValue(postsInChannelModels);
|
||||
(channel.posts.fetch as jest.Mock).mockResolvedValue(postModels);
|
||||
(channel.bookmarks.fetch as jest.Mock).mockResolvedValue(bookmarkModels);
|
||||
jest.mocked(channel.membership.fetch).mockResolvedValue(membershipModel);
|
||||
jest.mocked(channel.info.fetch).mockResolvedValue(infoModel);
|
||||
jest.mocked(channel.categoryChannel.fetch).mockResolvedValue(categoryChannelModel);
|
||||
jest.mocked(channel.members.fetch).mockResolvedValue(memberModels);
|
||||
jest.mocked(channel.drafts.fetch).mockResolvedValue(draftModels);
|
||||
jest.mocked(channel.postsInChannel.fetch).mockResolvedValue(postsInChannelModels);
|
||||
jest.mocked(channel.posts.fetch).mockResolvedValue(postModels);
|
||||
jest.mocked(channel.bookmarks.fetch).mockResolvedValue(bookmarkModels);
|
||||
|
||||
const result = await prepareDeleteChannel(channel);
|
||||
|
||||
|
|
@ -365,7 +370,7 @@ describe('prepareDeleteChannel', () => {
|
|||
{id: 'category'},
|
||||
{id: 'member'},
|
||||
{id: 'draft'},
|
||||
{},
|
||||
{id: 'postsInChannel'},
|
||||
{id: 'post'},
|
||||
{id: 'bookmark'},
|
||||
]);
|
||||
|
|
@ -381,9 +386,9 @@ describe('prepareDeleteChannel', () => {
|
|||
});
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
(channel.membership.fetch as jest.Mock).mockRejectedValue(new Error('Test error'));
|
||||
(channel.info.fetch as jest.Mock).mockRejectedValue(new Error('Test error'));
|
||||
(channel.categoryChannel.fetch as jest.Mock).mockRejectedValue(new Error('Test error'));
|
||||
jest.mocked(channel.membership.fetch).mockRejectedValue(new Error('Test error'));
|
||||
jest.mocked(channel.info.fetch).mockRejectedValue(new Error('Test error'));
|
||||
jest.mocked(channel.categoryChannel.fetch).mockRejectedValue(new Error('Test error'));
|
||||
|
||||
const result = await prepareDeleteChannel(channel);
|
||||
|
||||
|
|
@ -396,17 +401,16 @@ describe('prepareDeleteBookmarks', () => {
|
|||
let bookmark: ChannelBookmarkModel;
|
||||
|
||||
beforeEach(() => {
|
||||
bookmark = {
|
||||
bookmark = TestHelper.fakeChannelBookmarkModel({
|
||||
prepareDestroyPermanently: jest.fn().mockReturnValue({}),
|
||||
file: {fetch: jest.fn()} as unknown as Relation<Model>,
|
||||
fileId: 'file_id',
|
||||
} as unknown as ChannelBookmarkModel;
|
||||
});
|
||||
});
|
||||
|
||||
it('should prepare bookmark and associated file for deletion', async () => {
|
||||
const fileModel = {prepareDestroyPermanently: jest.fn().mockReturnValue({})};
|
||||
const fileModel = TestHelper.fakeFileModel({prepareDestroyPermanently: jest.fn().mockReturnValue({})});
|
||||
|
||||
(bookmark.file.fetch as jest.Mock).mockResolvedValue(fileModel);
|
||||
jest.mocked(bookmark.file.fetch).mockResolvedValue(fileModel);
|
||||
|
||||
const result = await prepareDeleteBookmarks(bookmark);
|
||||
|
||||
|
|
@ -417,7 +421,7 @@ describe('prepareDeleteBookmarks', () => {
|
|||
});
|
||||
|
||||
it('should handle errors gracefully when fetching associated file', async () => {
|
||||
(bookmark.file.fetch as jest.Mock).mockRejectedValue(new Error('Test error'));
|
||||
jest.mocked(bookmark.file.fetch).mockRejectedValue(new Error('Test error'));
|
||||
|
||||
const result = await prepareDeleteBookmarks(bookmark);
|
||||
|
||||
|
|
@ -692,10 +696,10 @@ describe('Channel Functions', () => {
|
|||
describe('getMyChannel', () => {
|
||||
it('should return the channel member if found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockMember = {id: channelId} as MyChannelModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockMember = TestHelper.fakeMyChannelModel({id: channelId});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockMember),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getMyChannel(database, channelId);
|
||||
|
||||
|
|
@ -705,9 +709,9 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return undefined if the channel member is not found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockRejectedValue(new Error('Not found')),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getMyChannel(database, channelId);
|
||||
|
||||
|
|
@ -722,9 +726,9 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([{id: channelId, observe: jest.fn().mockReturnValue(of$({id: channelId}))}])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = observeMyChannel(database, channelId);
|
||||
|
||||
|
|
@ -740,9 +744,9 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = observeMyChannel(database, channelId);
|
||||
|
||||
|
|
@ -761,9 +765,9 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([{id: channelId, roles, observe: jest.fn().mockReturnValue(of$({roles}))}])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = observeMyChannelRoles(database, channelId);
|
||||
|
||||
|
|
@ -777,9 +781,9 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = observeMyChannelRoles(database, channelId);
|
||||
|
||||
|
|
@ -792,10 +796,10 @@ describe('Channel Functions', () => {
|
|||
describe('getChannelById', () => {
|
||||
it('should return the channel if found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockedChannel = {id: channelId} as ChannelModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockedChannel = TestHelper.fakeChannelModel({id: channelId});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockedChannel),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelById(database, channelId);
|
||||
|
||||
|
|
@ -805,9 +809,9 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return undefined if the channel is not found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockRejectedValue(new Error('Not found')),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelById(database, channelId);
|
||||
|
||||
|
|
@ -822,9 +826,9 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([{id: channelId, observe: jest.fn().mockReturnValue(of$({id: channelId}))}])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = observeChannel(database, channelId);
|
||||
|
||||
|
|
@ -840,9 +844,9 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = observeChannel(database, channelId);
|
||||
|
||||
|
|
@ -858,12 +862,12 @@ describe('Channel Functions', () => {
|
|||
it('should return the channel if found', async () => {
|
||||
const teamId = 'team_id';
|
||||
const channelName = 'channel_name';
|
||||
const mockedChannel = {id: 'channel_id', name: channelName} as ChannelModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockedChannel = TestHelper.fakeChannelModel({id: 'channel_id', name: channelName});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: jest.fn().mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([mockedChannel]),
|
||||
}),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelByName(database, teamId, channelName);
|
||||
|
||||
|
|
@ -874,11 +878,11 @@ describe('Channel Functions', () => {
|
|||
it('should return undefined if the channel is not found', async () => {
|
||||
const teamId = 'team_id';
|
||||
const channelName = 'channel_name';
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: jest.fn().mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([]),
|
||||
}),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelByName(database, teamId, channelName);
|
||||
|
||||
|
|
@ -890,10 +894,10 @@ describe('Channel Functions', () => {
|
|||
describe('getChannelInfo', () => {
|
||||
it('should return the channel info if found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockChannelInfo = {id: channelId} as ChannelInfoModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockChannelInfo = TestHelper.fakeChannelInfoModel({id: channelId});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockChannelInfo),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelInfo(database, channelId);
|
||||
|
||||
|
|
@ -903,9 +907,9 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return undefined if the channel info is not found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockRejectedValue(new Error('Not found')),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelInfo(database, channelId);
|
||||
|
||||
|
|
@ -927,12 +931,12 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return the default channel for the team', async () => {
|
||||
const teamId = 'team_id';
|
||||
const defaultChannel = {id: 'default_channel', name: General.DEFAULT_CHANNEL} as ChannelModel;
|
||||
const myFirstTeamChannel = {id: 'first_team_channel'} as ChannelModel;
|
||||
const roles = [{permissions: [Permissions.JOIN_PUBLIC_CHANNELS]}];
|
||||
(queryRoles as jest.Mock).mockReturnValue({fetch: jest.fn().mockResolvedValue(roles)});
|
||||
(hasPermission as jest.Mock).mockReturnValue(true);
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
const defaultChannel = TestHelper.fakeChannelModel({id: 'default_channel', name: General.DEFAULT_CHANNEL});
|
||||
const myFirstTeamChannel = TestHelper.fakeChannelModel({id: 'first_team_channel'});
|
||||
const roles = [TestHelper.fakeRoleModel({permissions: [Permissions.JOIN_PUBLIC_CHANNELS]})];
|
||||
jest.mocked(queryRoles).mockReturnValue(TestHelper.fakeQuery(roles));
|
||||
jest.mocked(hasPermission).mockReturnValue(true);
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([defaultChannel, myFirstTeamChannel]),
|
||||
});
|
||||
|
||||
|
|
@ -955,11 +959,11 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return the default channel for the team with ignore id', async () => {
|
||||
const teamId = 'team_id';
|
||||
const defaultChannel = {id: 'default_channel', name: General.DEFAULT_CHANNEL} as ChannelModel;
|
||||
const myFirstTeamChannel = {id: 'first_team_channel'} as ChannelModel;
|
||||
(queryRoles as jest.Mock).mockReturnValue({fetch: jest.fn().mockResolvedValue([])});
|
||||
(hasPermission as jest.Mock).mockReturnValue(true);
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
const defaultChannel = TestHelper.fakeChannelModel({id: 'default_channel', name: General.DEFAULT_CHANNEL});
|
||||
const myFirstTeamChannel = TestHelper.fakeChannelModel({id: 'first_team_channel'});
|
||||
jest.mocked(queryRoles).mockReturnValue(TestHelper.fakeQuery([]));
|
||||
jest.mocked(hasPermission).mockReturnValue(true);
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([defaultChannel, myFirstTeamChannel]),
|
||||
});
|
||||
|
||||
|
|
@ -982,11 +986,11 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return the first team channel if no default channel is found', async () => {
|
||||
const teamId = 'team_id';
|
||||
const myFirstTeamChannel = {id: 'first_team_channel'} as ChannelModel;
|
||||
const roles = [{permissions: []}];
|
||||
(queryRoles as jest.Mock).mockReturnValue({fetch: jest.fn().mockResolvedValue(roles)});
|
||||
(hasPermission as jest.Mock).mockReturnValue(false);
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
const myFirstTeamChannel = TestHelper.fakeChannelModel({id: 'first_team_channel'});
|
||||
const roles = [TestHelper.fakeRoleModel({permissions: []})];
|
||||
jest.mocked(queryRoles).mockReturnValue(TestHelper.fakeQuery(roles));
|
||||
jest.mocked(hasPermission).mockReturnValue(false);
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([myFirstTeamChannel]),
|
||||
});
|
||||
|
||||
|
|
@ -1009,10 +1013,10 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return undefined if no channels are found', async () => {
|
||||
const teamId = 'team_id';
|
||||
const roles = [{permissions: [Permissions.JOIN_PUBLIC_CHANNELS]}];
|
||||
(queryRoles as jest.Mock).mockReturnValue({fetch: jest.fn().mockResolvedValue(roles)});
|
||||
(hasPermission as jest.Mock).mockReturnValue(true);
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
const roles = [TestHelper.fakeRoleModel({permissions: [Permissions.JOIN_PUBLIC_CHANNELS]})];
|
||||
jest.mocked(queryRoles).mockReturnValue(TestHelper.fakeQuery(roles));
|
||||
jest.mocked(hasPermission).mockReturnValue(true);
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([]),
|
||||
});
|
||||
|
||||
|
|
@ -1037,11 +1041,11 @@ describe('Channel Functions', () => {
|
|||
describe('getCurrentChannel', () => {
|
||||
it('should return the current channel if found', async () => {
|
||||
const currentChannelId = 'current_channel_id';
|
||||
const mockedChannel = {id: currentChannelId} as ChannelModel;
|
||||
(getCurrentChannelId as jest.Mock).mockResolvedValue(currentChannelId);
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockedChannel = TestHelper.fakeChannelModel({id: currentChannelId});
|
||||
jest.mocked(getCurrentChannelId).mockResolvedValue(currentChannelId);
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockedChannel),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getCurrentChannel(database);
|
||||
|
||||
|
|
@ -1051,7 +1055,7 @@ describe('Channel Functions', () => {
|
|||
});
|
||||
|
||||
it('should return undefined if no current channel is found', async () => {
|
||||
(getCurrentChannelId as jest.Mock).mockResolvedValue(undefined);
|
||||
jest.mocked(getCurrentChannelId).mockResolvedValue('');
|
||||
|
||||
const result = await getCurrentChannel(database);
|
||||
|
||||
|
|
@ -1063,11 +1067,11 @@ describe('Channel Functions', () => {
|
|||
describe('getCurrentChannelInfo', () => {
|
||||
it('should return the current channel info if found', async () => {
|
||||
const currentChannelId = 'current_channel_id';
|
||||
const mockChannelInfo = {id: currentChannelId} as ChannelInfoModel;
|
||||
(getCurrentChannelId as jest.Mock).mockResolvedValue(currentChannelId);
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockChannelInfo = TestHelper.fakeChannelInfoModel({id: currentChannelId});
|
||||
jest.mocked(getCurrentChannelId).mockResolvedValue(currentChannelId);
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockChannelInfo),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getCurrentChannelInfo(database);
|
||||
|
||||
|
|
@ -1077,7 +1081,7 @@ describe('Channel Functions', () => {
|
|||
});
|
||||
|
||||
it('should return undefined if no current channel info is found', async () => {
|
||||
(getCurrentChannelId as jest.Mock).mockResolvedValue(undefined);
|
||||
jest.mocked(getCurrentChannelId).mockResolvedValue('');
|
||||
|
||||
const result = await getCurrentChannelInfo(database);
|
||||
|
||||
|
|
@ -1089,14 +1093,14 @@ describe('Channel Functions', () => {
|
|||
describe('observeCurrentChannel', () => {
|
||||
it('should observe the current channel', () => {
|
||||
const currentChannelId = 'current_channel_id';
|
||||
const mockedChannel = {id: currentChannelId, observe: jest.fn().mockReturnValue(of$({id: currentChannelId}))} as unknown as ChannelModel;
|
||||
const mockedChannel = TestHelper.fakeChannelModel({id: currentChannelId, observe: jest.fn().mockReturnValue(of$({id: currentChannelId}))});
|
||||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([mockedChannel])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
(observeCurrentChannelId as jest.Mock).mockReturnValue(of$(currentChannelId));
|
||||
} as any);
|
||||
jest.mocked(observeCurrentChannelId).mockReturnValue(of$(currentChannelId));
|
||||
|
||||
const result = observeCurrentChannel(database);
|
||||
|
||||
|
|
@ -1111,10 +1115,10 @@ describe('Channel Functions', () => {
|
|||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: mockQuery,
|
||||
});
|
||||
(observeCurrentChannelId as jest.Mock).mockReturnValue(of$(currentChannelId));
|
||||
} as any);
|
||||
jest.mocked(observeCurrentChannelId).mockReturnValue(of$(currentChannelId));
|
||||
|
||||
const result = observeCurrentChannel(database);
|
||||
|
||||
|
|
@ -1128,10 +1132,10 @@ describe('Channel Functions', () => {
|
|||
describe('getChannelInfo', () => {
|
||||
it('should return the channel info if found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockChannelInfo = {id: channelId} as ChannelInfoModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockChannelInfo = TestHelper.fakeChannelInfoModel({id: channelId});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockChannelInfo),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelInfo(database, channelId);
|
||||
|
||||
|
|
@ -1141,9 +1145,9 @@ describe('Channel Functions', () => {
|
|||
|
||||
it('should return undefined if the channel info is not found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
find: jest.fn().mockRejectedValue(new Error('Not found')),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await getChannelInfo(database, channelId);
|
||||
|
||||
|
|
@ -1172,14 +1176,12 @@ describe('Channel Membership Functions', () => {
|
|||
it('should delete channel membership and return models', async () => {
|
||||
const userId = 'user_id';
|
||||
const channelId = 'channel_id';
|
||||
const mockMembership = {
|
||||
prepareDestroyPermanently: jest.fn().mockReturnValue({}),
|
||||
} as unknown as ChannelMembershipModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockMembership = TestHelper.fakeChannelMembershipModel({prepareDestroyPermanently: jest.fn().mockReturnValue({})});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: jest.fn().mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([mockMembership]),
|
||||
}),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await deleteChannelMembership(operator, userId, channelId);
|
||||
|
||||
|
|
@ -1191,14 +1193,12 @@ describe('Channel Membership Functions', () => {
|
|||
it('should return models without batching if prepareRecordsOnly is true', async () => {
|
||||
const userId = 'user_id';
|
||||
const channelId = 'channel_id';
|
||||
const mockMembership = {
|
||||
prepareDestroyPermanently: jest.fn().mockReturnValue({}),
|
||||
} as unknown as ChannelMembershipModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
const mockMembership = TestHelper.fakeChannelMembershipModel({prepareDestroyPermanently: jest.fn().mockReturnValue({})});
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: jest.fn().mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([mockMembership]),
|
||||
}),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await deleteChannelMembership(operator, userId, channelId, true);
|
||||
|
||||
|
|
@ -1211,11 +1211,11 @@ describe('Channel Membership Functions', () => {
|
|||
const userId = 'user_id';
|
||||
const channelId = 'channel_id';
|
||||
const error = new Error('Test error');
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
jest.mocked(database.get).mockReturnValue({
|
||||
query: jest.fn().mockReturnValue({
|
||||
fetch: jest.fn().mockRejectedValue(error),
|
||||
}),
|
||||
});
|
||||
} as any);
|
||||
|
||||
const result = await deleteChannelMembership(operator, userId, channelId);
|
||||
|
||||
|
|
@ -1241,7 +1241,7 @@ describe('Channel Membership Functions', () => {
|
|||
const userId = 'user_id';
|
||||
const channelId = 'channel_id';
|
||||
const error = new Error('Test error');
|
||||
(operator.handleChannelMembership as jest.Mock).mockRejectedValue(error);
|
||||
jest.mocked(operator.handleChannelMembership).mockRejectedValue(error);
|
||||
|
||||
const result = await addChannelMembership(operator, userId, channelId);
|
||||
|
||||
|
|
@ -1264,11 +1264,11 @@ describe('Channel Membership Functions', () => {
|
|||
it('should return the members count by channel IDs', async () => {
|
||||
const channelsId = ['channel1', 'channel2'];
|
||||
const mockMemberships = [
|
||||
{channelId: 'channel1'},
|
||||
{channelId: 'channel1'},
|
||||
{channelId: 'channel2'},
|
||||
] as ChannelMembershipModel[];
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
TestHelper.fakeChannelMembershipModel({channelId: 'channel1'}),
|
||||
TestHelper.fakeChannelMembershipModel({channelId: 'channel1'}),
|
||||
TestHelper.fakeChannelMembershipModel({channelId: 'channel2'}),
|
||||
];
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue(mockMemberships),
|
||||
});
|
||||
|
||||
|
|
@ -1281,8 +1281,8 @@ describe('Channel Membership Functions', () => {
|
|||
|
||||
it('should return zero counts for channels with no members', async () => {
|
||||
const channelsId = ['channel1', 'channel2'];
|
||||
const mockMemberships = [] as ChannelMembershipModel[];
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
const mockMemberships: ChannelMembershipModel[] = [];
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue(mockMemberships),
|
||||
});
|
||||
|
||||
|
|
@ -1296,7 +1296,7 @@ describe('Channel Membership Functions', () => {
|
|||
it('should handle errors gracefully', async () => {
|
||||
const channelsId = ['channel1', 'channel2'];
|
||||
const error = new Error('Test error');
|
||||
(mockQuery as jest.Mock).mockReturnValue({
|
||||
jest.mocked(mockQuery).mockReturnValue({
|
||||
fetch: jest.fn().mockRejectedValue(error),
|
||||
});
|
||||
|
||||
|
|
@ -1336,9 +1336,9 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe all my channel notify props', () => {
|
||||
const mockSettings = [
|
||||
{id: 'id1', notifyProps: {mark_unread: 'all'}},
|
||||
{id: 'id2', notifyProps: {mark_unread: 'mention'}},
|
||||
] as MyChannelSettingsModel[];
|
||||
TestHelper.fakeMyChannelSettingsModel({id: 'id1', notifyProps: {mark_unread: 'all'}}),
|
||||
TestHelper.fakeMyChannelSettingsModel({id: 'id2', notifyProps: {mark_unread: 'mention'}}),
|
||||
];
|
||||
mockQuery.mockReturnValue({
|
||||
observeWithColumns: jest.fn().mockReturnValue(of$(mockSettings)),
|
||||
});
|
||||
|
|
@ -1356,13 +1356,13 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe notify props by channels', () => {
|
||||
const channels = [
|
||||
{id: 'channel1'},
|
||||
{id: 'channel2'},
|
||||
] as ChannelModel[];
|
||||
TestHelper.fakeChannelModel({id: 'channel1'}),
|
||||
TestHelper.fakeChannelModel({id: 'channel2'}),
|
||||
];
|
||||
const mockSettings = [
|
||||
{id: 'channel1', notifyProps: {mark_unread: 'all'}},
|
||||
{id: 'channel2', notifyProps: {mark_unread: 'mention'}},
|
||||
] as MyChannelSettingsModel[];
|
||||
TestHelper.fakeMyChannelSettingsModel({id: 'channel1', notifyProps: {mark_unread: 'all'}}),
|
||||
TestHelper.fakeMyChannelSettingsModel({id: 'channel2', notifyProps: {mark_unread: 'mention'}}),
|
||||
];
|
||||
mockQuery.mockReturnValue({
|
||||
observeWithColumns: jest.fn().mockReturnValue(of$(mockSettings)),
|
||||
});
|
||||
|
|
@ -1381,9 +1381,9 @@ describe('Channel Observations', () => {
|
|||
it('should observe my channel mention count', () => {
|
||||
const teamId = 'team_id';
|
||||
const mockChannels = [
|
||||
{mentionsCount: 2, isUnread: true},
|
||||
{mentionsCount: 3, isUnread: false},
|
||||
] as MyChannelModel[];
|
||||
TestHelper.fakeMyChannelModel({mentionsCount: 2, isUnread: true}),
|
||||
TestHelper.fakeMyChannelModel({mentionsCount: 3, isUnread: false}),
|
||||
];
|
||||
mockQuery.mockReturnValue({
|
||||
observeWithColumns: jest.fn().mockReturnValue(of$(mockChannels)),
|
||||
});
|
||||
|
|
@ -1398,9 +1398,9 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe my channel mention count with no team id', () => {
|
||||
const mockChannels = [
|
||||
{mentionsCount: 2, isUnread: true},
|
||||
{mentionsCount: 3, isUnread: false},
|
||||
] as MyChannelModel[];
|
||||
TestHelper.fakeMyChannelModel({mentionsCount: 2, isUnread: true}),
|
||||
TestHelper.fakeMyChannelModel({mentionsCount: 3, isUnread: false}),
|
||||
];
|
||||
mockQuery.mockReturnValue({
|
||||
observeWithColumns: jest.fn().mockReturnValue(of$(mockChannels)),
|
||||
});
|
||||
|
|
@ -1416,8 +1416,8 @@ describe('Channel Observations', () => {
|
|||
it('should observe direct channels by term', () => {
|
||||
const term = '@test';
|
||||
const mockCurrentUserId = 'user_id';
|
||||
const mockChannels = [{id: 'channel1'}] as MyChannelModel[];
|
||||
(observeCurrentUserId as jest.Mock).mockReturnValue(of$(mockCurrentUserId));
|
||||
const mockChannels = [TestHelper.fakeMyChannelModel({id: 'channel1'})];
|
||||
jest.mocked(observeCurrentUserId).mockReturnValue(of$(mockCurrentUserId));
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$(mockChannels)),
|
||||
});
|
||||
|
|
@ -1432,8 +1432,8 @@ describe('Channel Observations', () => {
|
|||
it('should observe not direct channels by term', () => {
|
||||
const term = 'test';
|
||||
const mockTeammateNameSetting = General.TEAMMATE_NAME_DISPLAY.SHOW_USERNAME;
|
||||
const mockUsers = [{id: 'user1'}] as UserModel[];
|
||||
(observeTeammateNameDisplay as jest.Mock).mockReturnValue(of$(mockTeammateNameSetting));
|
||||
const mockUsers = [TestHelper.fakeUserModel({id: 'user1'})];
|
||||
jest.mocked(observeTeammateNameDisplay).mockReturnValue(of$(mockTeammateNameSetting));
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$(mockUsers)),
|
||||
});
|
||||
|
|
@ -1447,7 +1447,7 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe joined channels by term', () => {
|
||||
const term = 'test';
|
||||
const mockChannels = [{id: 'channel1'}] as MyChannelModel[];
|
||||
const mockChannels = [TestHelper.fakeMyChannelModel({id: 'channel1'})];
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$(mockChannels)),
|
||||
});
|
||||
|
|
@ -1472,7 +1472,7 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe archive channels by term', () => {
|
||||
const term = 'test';
|
||||
const mockChannels = [{id: 'channel1'}] as MyChannelModel[];
|
||||
const mockChannels = [TestHelper.fakeMyChannelModel({id: 'channel1'})];
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$(mockChannels)),
|
||||
});
|
||||
|
|
@ -1497,7 +1497,9 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe channel settings', () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockSettings = {id: channelId, observe: jest.fn().mockReturnValue(of$({id: channelId}))} as unknown as MyChannelSettingsModel;
|
||||
const mockSettings = TestHelper.fakeMyChannelSettingsModel({id: channelId});
|
||||
jest.mocked(mockSettings.observe).mockReturnValue(of$(mockSettings));
|
||||
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([mockSettings])),
|
||||
});
|
||||
|
|
@ -1506,13 +1508,14 @@ describe('Channel Observations', () => {
|
|||
|
||||
expect(database.get).toHaveBeenCalledWith(MM_TABLES.SERVER.MY_CHANNEL_SETTINGS);
|
||||
result.subscribe((value) => {
|
||||
expect(value).toEqual({id: channelId});
|
||||
expect(value).toMatchObject({id: channelId});
|
||||
});
|
||||
});
|
||||
|
||||
it('should observe is muted setting', () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockSettings = {id: channelId, notifyProps: {mark_unread: General.MENTION}, observe: jest.fn().mockReturnValue(of$({id: channelId, notifyProps: {mark_unread: General.MENTION}}))} as unknown as MyChannelSettingsModel;
|
||||
const mockSettings = TestHelper.fakeMyChannelSettingsModel({id: channelId, notifyProps: {mark_unread: General.MENTION}});
|
||||
jest.mocked(mockSettings.observe).mockReturnValue(of$(mockSettings));
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([mockSettings])),
|
||||
});
|
||||
|
|
@ -1526,8 +1529,8 @@ describe('Channel Observations', () => {
|
|||
});
|
||||
|
||||
it('should observe channels by last post at', () => {
|
||||
const myChannels = [{id: 'channel1'}] as MyChannelModel[];
|
||||
const mockChannels = [{id: 'channel1'}] as ChannelModel[];
|
||||
const myChannels = [TestHelper.fakeMyChannelModel({id: 'channel1'})];
|
||||
const mockChannels = [TestHelper.fakeChannelModel({id: 'channel1'})];
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$(mockChannels)),
|
||||
});
|
||||
|
|
@ -1542,7 +1545,10 @@ describe('Channel Observations', () => {
|
|||
|
||||
it('should observe channel members', () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockMembers = [{id: 'member1'}, {id: 'member2'}] as ChannelMembershipModel[];
|
||||
const mockMembers = [
|
||||
TestHelper.fakeChannelMembershipModel({id: 'member1'}),
|
||||
TestHelper.fakeChannelMembershipModel({id: 'member2'}),
|
||||
];
|
||||
mockQuery.mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$(mockMembers)),
|
||||
});
|
||||
|
|
@ -1580,7 +1586,7 @@ describe('observeMyChannelUnreads', () => {
|
|||
|
||||
it('should return true when there are unread channels that are not muted', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const notify_props = {mark_unread: 'all' as const};
|
||||
const notify_props = TestHelper.fakeChannelNotifyProps({mark_unread: 'all'});
|
||||
const result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
|
|
@ -1628,7 +1634,7 @@ describe('observeMyChannelUnreads', () => {
|
|||
|
||||
it('should return false when all unread channels are muted', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const notify_props = {mark_unread: 'mention' as const};
|
||||
const notify_props = TestHelper.fakeChannelNotifyProps({mark_unread: General.MENTION});
|
||||
const result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
|
|
@ -1724,7 +1730,7 @@ describe('observeMyChannelUnreads', () => {
|
|||
it('should not retrigger the subscription when there are changes in other teams', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const otherTeamId = 'other_team_id';
|
||||
const notify_props = {mark_unread: 'all' as const};
|
||||
const notify_props = TestHelper.fakeChannelNotifyProps({mark_unread: General.MENTION});
|
||||
const result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import {General, Permissions} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {
|
||||
queryRoles,
|
||||
|
|
@ -17,10 +18,6 @@ import {
|
|||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type {Database} from '@nozbe/watermelondb';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
describe('Role Queries', () => {
|
||||
const serverUrl = 'baseHandler.test.com';
|
||||
|
|
@ -108,16 +105,16 @@ describe('Role Queries', () => {
|
|||
|
||||
describe('observePermissionForChannel', () => {
|
||||
it('should observe channel permissions', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_user',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
const mockChannel = {
|
||||
const mockChannel = TestHelper.fakeChannelModel({
|
||||
id: 'channel1',
|
||||
type: General.OPEN_CHANNEL,
|
||||
teamId: 'team1',
|
||||
} as ChannelModel;
|
||||
});
|
||||
|
||||
operator.handleRole({
|
||||
roles: [{
|
||||
|
|
@ -146,7 +143,7 @@ describe('Role Queries', () => {
|
|||
it('should return default value when no user', (done) => {
|
||||
observePermissionForChannel(
|
||||
database,
|
||||
{} as any,
|
||||
TestHelper.fakeChannelModel(),
|
||||
undefined,
|
||||
Permissions.CREATE_POST,
|
||||
true,
|
||||
|
|
@ -162,14 +159,14 @@ describe('Role Queries', () => {
|
|||
|
||||
describe('observePermissionForTeam', () => {
|
||||
it('should observe team permissions', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_user',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
const mockTeam = {
|
||||
const mockTeam = TestHelper.fakeTeamModel({
|
||||
id: 'team1',
|
||||
} as TeamModel;
|
||||
});
|
||||
|
||||
const myTeams: MyTeam[] = [{
|
||||
id: mockTeam.id,
|
||||
|
|
@ -214,7 +211,7 @@ describe('Role Queries', () => {
|
|||
observePermissionForTeam(
|
||||
database,
|
||||
undefined,
|
||||
{} as any,
|
||||
TestHelper.fakeUserModel(),
|
||||
Permissions.MANAGE_TEAM,
|
||||
true,
|
||||
).subscribe({
|
||||
|
|
@ -229,18 +226,18 @@ describe('Role Queries', () => {
|
|||
|
||||
describe('observeCanManageChannelMembers', () => {
|
||||
it('should observe manage members permission for public channel', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_admin',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
Promise.all([
|
||||
operator.handleChannel({
|
||||
channels: [{
|
||||
channels: [TestHelper.fakeChannel({
|
||||
id: 'channel1',
|
||||
type: General.OPEN_CHANNEL,
|
||||
delete_at: 0,
|
||||
}] as Channel[],
|
||||
})],
|
||||
prepareRecordsOnly: false,
|
||||
}),
|
||||
operator.handleRole({
|
||||
|
|
@ -266,18 +263,18 @@ describe('Role Queries', () => {
|
|||
});
|
||||
|
||||
it('should not allow managing default channel members', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_admin',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
operator.handleChannel({
|
||||
channels: [{
|
||||
channels: [TestHelper.fakeChannel({
|
||||
id: 'channel1',
|
||||
name: General.DEFAULT_CHANNEL,
|
||||
type: General.OPEN_CHANNEL,
|
||||
delete_at: 0,
|
||||
}] as Channel[],
|
||||
})],
|
||||
prepareRecordsOnly: false,
|
||||
}).then(() => {
|
||||
observeCanManageChannelMembers(
|
||||
|
|
@ -297,23 +294,23 @@ describe('Role Queries', () => {
|
|||
|
||||
describe('observePermissionForPost', () => {
|
||||
it('should observe post permissions', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_user',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
const mockPost = {
|
||||
const mockPost = TestHelper.fakePostModel({
|
||||
id: 'post1',
|
||||
channelId: 'channel1',
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
Promise.all([
|
||||
operator.handleChannel({
|
||||
channels: [{
|
||||
channels: [TestHelper.fakeChannel({
|
||||
id: 'channel1',
|
||||
type: General.OPEN_CHANNEL,
|
||||
team_id: 'team1',
|
||||
}] as Channel[],
|
||||
})],
|
||||
prepareRecordsOnly: false,
|
||||
}),
|
||||
operator.handleRole({
|
||||
|
|
@ -342,10 +339,10 @@ describe('Role Queries', () => {
|
|||
});
|
||||
|
||||
it('should return default value when no channel exists', (done) => {
|
||||
const mockPost = {
|
||||
const mockPost = TestHelper.fakePostModel({
|
||||
id: 'post1',
|
||||
channelId: 'nonexistent',
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
observePermissionForPost(
|
||||
database,
|
||||
|
|
@ -365,18 +362,18 @@ describe('Role Queries', () => {
|
|||
|
||||
describe('observeCanManageChannelSettings', () => {
|
||||
it('should observe manage settings permission', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_admin',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
Promise.all([
|
||||
operator.handleChannel({
|
||||
channels: [{
|
||||
channels: [TestHelper.fakeChannel({
|
||||
id: 'channel1',
|
||||
type: General.OPEN_CHANNEL,
|
||||
delete_at: 0,
|
||||
}] as Channel[],
|
||||
})],
|
||||
prepareRecordsOnly: false,
|
||||
}),
|
||||
operator.handleRole({
|
||||
|
|
@ -403,17 +400,17 @@ describe('Role Queries', () => {
|
|||
});
|
||||
|
||||
it('should not allow managing deleted channel settings', (done) => {
|
||||
const mockUser = {
|
||||
const mockUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
roles: 'system_admin',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
operator.handleChannel({
|
||||
channels: [{
|
||||
channels: [TestHelper.fakeChannel({
|
||||
id: 'channel1',
|
||||
type: General.OPEN_CHANNEL,
|
||||
delete_at: 123,
|
||||
}] as Channel[],
|
||||
})],
|
||||
prepareRecordsOnly: false,
|
||||
}).then(() => {
|
||||
observeCanManageChannelSettings(
|
||||
|
|
|
|||
|
|
@ -2,20 +2,19 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import {fireEvent} from '@testing-library/react-native';
|
||||
import React from 'react';
|
||||
import React, {type ComponentProps} from 'react';
|
||||
|
||||
import {renderWithIntl} from '@test/intl-test-helper';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import ProfileForm from './form';
|
||||
|
||||
import type {CustomAttributeSet} from '@typings/api/custom_profile_attributes';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
import type {UserInfo} from '@typings/screens/edit_profile';
|
||||
|
||||
describe('ProfileForm', () => {
|
||||
const baseProps = {
|
||||
const baseProps: ComponentProps<typeof ProfileForm> = {
|
||||
canSave: false,
|
||||
currentUser: {
|
||||
currentUser: TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
firstName: 'First',
|
||||
lastName: 'Last',
|
||||
|
|
@ -24,7 +23,7 @@ describe('ProfileForm', () => {
|
|||
nickname: 'nick',
|
||||
position: 'position',
|
||||
authService: '',
|
||||
} as UserModel,
|
||||
}),
|
||||
isTablet: false,
|
||||
lockedFirstName: false,
|
||||
lockedLastName: false,
|
||||
|
|
@ -40,7 +39,7 @@ describe('ProfileForm', () => {
|
|||
nickname: 'nick',
|
||||
position: 'position',
|
||||
customAttributes: {},
|
||||
} as UserInfo,
|
||||
},
|
||||
enableCustomAttributes: false,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
|
||||
import {Preferences} from '@constants';
|
||||
import {BOTTOM_TAB_PROFILE_PHOTO_SIZE, BOTTOM_TAB_STATUS_SIZE} from '@constants/view';
|
||||
import {renderWithEverything, renderWithIntl} from '@test/intl-test-helper';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
|
@ -9,20 +10,20 @@ import {changeOpacity} from '@utils/theme';
|
|||
|
||||
import {Account, default as AccountWithDatabaseObservable} from './account';
|
||||
|
||||
import type {UserModel} from '@database/models/server';
|
||||
import type Database from '@nozbe/watermelondb/Database';
|
||||
|
||||
jest.mock('@components/profile_picture', () => 'ProfilePicture');
|
||||
|
||||
const currentUser = {
|
||||
const currentUser = TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
username: 'testuser',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
const theme = {
|
||||
...Preferences.THEMES.denim,
|
||||
buttonBg: '#000',
|
||||
centerChannelColor: '#fff',
|
||||
} as Theme;
|
||||
};
|
||||
|
||||
describe('Account', () => {
|
||||
const centerChannelColorWithOpacity = changeOpacity(theme.centerChannelColor, 0.48);
|
||||
|
|
@ -64,7 +65,7 @@ describe('Account', () => {
|
|||
|
||||
const profilePicture = getByTestId('account-profile-picture');
|
||||
|
||||
expect(profilePicture.props.author).toEqual({id: 'user1', username: 'testuser'});
|
||||
expect(profilePicture.props.author).toEqual(expect.objectContaining({id: 'user1', username: 'testuser'}));
|
||||
expect(profilePicture.props.showStatus).toBe(true);
|
||||
expect(profilePicture.props.size).toBe(BOTTOM_TAB_PROFILE_PHOTO_SIZE);
|
||||
expect(profilePicture.props.statusSize).toBe(BOTTOM_TAB_STATUS_SIZE);
|
||||
|
|
|
|||
|
|
@ -1,34 +1,37 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {getMentionProps, canSaveSettings, getUniqueKeywordsFromInput, type CanSaveSettings} from './mention_settings';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
import {getMentionProps, canSaveSettings, getUniqueKeywordsFromInput, type CanSaveSettings} from './mention_settings';
|
||||
|
||||
describe('getMentionProps', () => {
|
||||
test('Should have correct return type when input is empty', () => {
|
||||
const mentionProps = getMentionProps({notifyProps: {} as UserNotifyProps} as UserModel);
|
||||
const user = TestHelper.fakeUserModel({notifyProps: null});
|
||||
const mentionProps = getMentionProps(user);
|
||||
|
||||
expect(mentionProps).toEqual({
|
||||
mentionKeywords: [],
|
||||
usernameMention: false,
|
||||
channel: false,
|
||||
first_name: false,
|
||||
comments: '',
|
||||
notifyProps: {},
|
||||
mentionKeywords: [
|
||||
`@${user.username}`,
|
||||
],
|
||||
usernameMention: true,
|
||||
channel: true,
|
||||
first_name: true,
|
||||
comments: 'any',
|
||||
notifyProps: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
test('Should have correct return type for when channel, first_name, currentUser.username are provided', () => {
|
||||
const mentionProps = getMentionProps({
|
||||
const mentionProps = getMentionProps(TestHelper.fakeUserModel({
|
||||
username: 'testUser',
|
||||
notifyProps: {
|
||||
notifyProps: TestHelper.fakeUserNotifyProps({
|
||||
comments: 'any',
|
||||
channel: 'true',
|
||||
first_name: 'true',
|
||||
mention_keys: 'testUser',
|
||||
} as UserNotifyProps,
|
||||
} as UserModel);
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(mentionProps.mentionKeywords).toEqual([]);
|
||||
expect(mentionProps.usernameMention).toEqual(true);
|
||||
|
|
@ -37,12 +40,12 @@ describe('getMentionProps', () => {
|
|||
});
|
||||
|
||||
test('Should have correct return type for mention_keys input', () => {
|
||||
const mentionProps = getMentionProps({
|
||||
const mentionProps = getMentionProps(TestHelper.fakeUserModel({
|
||||
username: 'testUser',
|
||||
notifyProps: {
|
||||
notifyProps: TestHelper.fakeUserNotifyProps({
|
||||
mention_keys: 'testUser,testUser2,testKey1,testKey2',
|
||||
} as UserNotifyProps,
|
||||
} as UserModel);
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(mentionProps.mentionKeywords).toHaveLength(3);
|
||||
expect(mentionProps.mentionKeywords).toEqual(['testUser2', 'testKey1', 'testKey2']);
|
||||
|
|
@ -50,44 +53,51 @@ describe('getMentionProps', () => {
|
|||
});
|
||||
|
||||
describe('canSaveSettings', () => {
|
||||
const getBaseCanSaveSettingParams = (): CanSaveSettings => ({
|
||||
mentionKeywords: [],
|
||||
mentionProps: {
|
||||
mentionKeywords: [],
|
||||
usernameMention: true,
|
||||
channel: true,
|
||||
first_name: true,
|
||||
comments: 'any',
|
||||
notifyProps: TestHelper.fakeUserNotifyProps(),
|
||||
},
|
||||
channelMentionOn: true,
|
||||
replyNotificationType: 'any',
|
||||
firstNameMentionOn: true,
|
||||
usernameMentionOn: true,
|
||||
});
|
||||
|
||||
test('Should return true when mentionKeywords have changed', () => {
|
||||
const canSaveSettingParams = {
|
||||
mentionKeywords: ['test1', 'test2'],
|
||||
mentionProps: {
|
||||
mentionKeywords: ['test1', 'test2', 'test3'],
|
||||
},
|
||||
} as CanSaveSettings;
|
||||
const canSaveSettingParams = getBaseCanSaveSettingParams();
|
||||
canSaveSettingParams.mentionKeywords = ['test1', 'test2'];
|
||||
canSaveSettingParams.mentionProps.mentionKeywords = ['test1', 'test2', 'test3'];
|
||||
|
||||
expect(canSaveSettings(canSaveSettingParams)).toEqual(true);
|
||||
});
|
||||
|
||||
test('Should return false when mentionKeywords have not changed', () => {
|
||||
const canSaveSettingParams = {
|
||||
mentionKeywords: ['test1', 'test2'],
|
||||
mentionProps: {
|
||||
mentionKeywords: ['test2', 'test1'],
|
||||
},
|
||||
} as CanSaveSettings;
|
||||
const canSaveSettingParams = getBaseCanSaveSettingParams();
|
||||
canSaveSettingParams.mentionKeywords = ['test1', 'test2'];
|
||||
canSaveSettingParams.mentionProps.mentionKeywords = ['test2', 'test1'];
|
||||
|
||||
expect(canSaveSettings(canSaveSettingParams)).toEqual(false);
|
||||
});
|
||||
|
||||
test('Should return true when only userName has changed', () => {
|
||||
const canSaveSettingParams = {
|
||||
channelMentionOn: true,
|
||||
replyNotificationType: 'any',
|
||||
firstNameMentionOn: true,
|
||||
usernameMentionOn: true,
|
||||
mentionKeywords: ['test1', 'test2'],
|
||||
mentionProps: {
|
||||
channel: true,
|
||||
comments: 'any' as UserNotifyProps['comments'],
|
||||
first_name: true,
|
||||
usernameMention: false,
|
||||
mentionKeywords: ['test1', 'test2'],
|
||||
notifyProps: {} as UserNotifyProps,
|
||||
},
|
||||
};
|
||||
const canSaveSettingParams = getBaseCanSaveSettingParams();
|
||||
canSaveSettingParams.channelMentionOn = true;
|
||||
canSaveSettingParams.replyNotificationType = 'any';
|
||||
canSaveSettingParams.firstNameMentionOn = true;
|
||||
canSaveSettingParams.usernameMentionOn = true;
|
||||
canSaveSettingParams.mentionKeywords = ['test1', 'test2'];
|
||||
canSaveSettingParams.mentionProps.channel = true;
|
||||
canSaveSettingParams.mentionProps.comments = 'any';
|
||||
canSaveSettingParams.mentionProps.first_name = true;
|
||||
canSaveSettingParams.mentionProps.usernameMention = false;
|
||||
canSaveSettingParams.mentionProps.mentionKeywords = ['test1', 'test2'];
|
||||
canSaveSettingParams.mentionProps.notifyProps = TestHelper.fakeUserNotifyProps();
|
||||
|
||||
expect(canSaveSettings(canSaveSettingParams)).toEqual(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ import React from 'react';
|
|||
|
||||
import {fetchCustomAttributes} from '@actions/remote/user';
|
||||
import {renderWithIntlAndTheme, screen, waitFor} from '@test/intl-test-helper';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import UserInfo from './user_info';
|
||||
|
||||
import type UserModel from '@database/models/server/user';
|
||||
|
||||
const localhost = 'http://localhost:8065';
|
||||
|
||||
jest.mock('@actions/remote/user', () => ({
|
||||
|
|
@ -23,18 +22,18 @@ jest.mock('@context/server', () => ({
|
|||
describe('screens/user_profile/UserInfo', () => {
|
||||
beforeEach(() => {
|
||||
// Reset mock before each test
|
||||
(fetchCustomAttributes as jest.Mock).mockReset();
|
||||
jest.mocked(fetchCustomAttributes).mockReset();
|
||||
});
|
||||
|
||||
const baseProps = {
|
||||
user: {
|
||||
user: TestHelper.fakeUserModel({
|
||||
id: 'user1',
|
||||
firstName: 'First',
|
||||
lastName: 'Last',
|
||||
username: 'username',
|
||||
nickname: 'nick',
|
||||
position: 'Developer',
|
||||
} as UserModel,
|
||||
}),
|
||||
isMyUser: false,
|
||||
showCustomStatus: false,
|
||||
showLocalTime: true,
|
||||
|
|
@ -65,7 +64,7 @@ describe('screens/user_profile/UserInfo', () => {
|
|||
};
|
||||
|
||||
test('should display custom attributes in sort order', async () => {
|
||||
(fetchCustomAttributes as jest.Mock).mockResolvedValue({attributes: baseCustomAttributes});
|
||||
jest.mocked(fetchCustomAttributes).mockResolvedValue({attributes: baseCustomAttributes});
|
||||
|
||||
renderWithIntlAndTheme(
|
||||
<UserInfo {...baseProps}/>,
|
||||
|
|
@ -136,7 +135,7 @@ describe('screens/user_profile/UserInfo', () => {
|
|||
sort_order: 2,
|
||||
},
|
||||
};
|
||||
(fetchCustomAttributes as jest.Mock).mockResolvedValue({attributes: withEmptyCustomAttributes});
|
||||
jest.mocked(fetchCustomAttributes).mockResolvedValue({attributes: withEmptyCustomAttributes});
|
||||
|
||||
renderWithIntlAndTheme(
|
||||
<UserInfo {...baseProps}/>,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import {Preferences} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {
|
||||
makeCategoryChannelId,
|
||||
|
|
@ -18,8 +19,6 @@ import {
|
|||
} from './categories';
|
||||
|
||||
import type {ServerDatabase} from '@typings/database/database';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type PreferenceModel from '@typings/database/models/servers/preference';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
describe('Categories utils', () => {
|
||||
|
|
@ -184,7 +183,7 @@ describe('Categories utils', () => {
|
|||
const channelModels = await db.operator.handleChannel({channels, prepareRecordsOnly: false});
|
||||
const myChannelModels = await db.operator.handleMyChannel({channels, myChannels, prepareRecordsOnly: false});
|
||||
return channelModels.map((channel, index) => {
|
||||
const myChannel = myChannelModels[index] as MyChannelModel;
|
||||
const myChannel = myChannelModels[index];
|
||||
return {
|
||||
channel,
|
||||
myChannel,
|
||||
|
|
@ -253,7 +252,7 @@ describe('Categories utils', () => {
|
|||
|
||||
const models = await db.operator.handleMyChannel({channels, myChannels, isCRTEnabled: false, prepareRecordsOnly: false});
|
||||
expect(models).toHaveLength(1);
|
||||
const myChannel = models[0] as MyChannelModel;
|
||||
const myChannel = models[0];
|
||||
let isUnread = isUnreadChannel(myChannel);
|
||||
expect(isUnread).toBe(true);
|
||||
await db.database.write(async () => {
|
||||
|
|
@ -355,11 +354,11 @@ describe('Categories utils', () => {
|
|||
const myChannelModels = await db.operator.handleMyChannel({channels, myChannels, prepareRecordsOnly: false});
|
||||
const data: ChannelWithMyChannel[] = [{
|
||||
channel: channelModels[0],
|
||||
myChannel: myChannelModels[0] as MyChannelModel,
|
||||
myChannel: myChannelModels[0],
|
||||
sortOrder: 0,
|
||||
}, {
|
||||
channel: channelModels[1],
|
||||
myChannel: myChannelModels[1] as MyChannelModel,
|
||||
myChannel: myChannelModels[1],
|
||||
sortOrder: 1,
|
||||
}];
|
||||
let archived = filterArchivedChannels(data, '');
|
||||
|
|
@ -378,19 +377,22 @@ describe('Categories utils', () => {
|
|||
const now = Date.now();
|
||||
const dt_chan1 = now - (3 * 24 * 60 * 60 * 1000);
|
||||
const dt_chan2 = now - (2 * 24 * 60 * 60 * 1000);
|
||||
const autoclosePrefs = [{
|
||||
id: 'pref1',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.CHANNEL_APPROXIMATE_VIEW_TIME,
|
||||
name: 'dm1',
|
||||
value: `${dt_chan1}`,
|
||||
}, {
|
||||
id: 'pref2',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.CHANNEL_APPROXIMATE_VIEW_TIME,
|
||||
name: 'dm2',
|
||||
value: `${dt_chan2}`,
|
||||
}] as PreferenceModel[];
|
||||
const autoclosePrefs = [
|
||||
TestHelper.fakePreferenceModel({
|
||||
id: 'pref1',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.CHANNEL_APPROXIMATE_VIEW_TIME,
|
||||
name: 'dm1',
|
||||
value: `${dt_chan1}`,
|
||||
}),
|
||||
TestHelper.fakePreferenceModel({
|
||||
id: 'pref2',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.CHANNEL_APPROXIMATE_VIEW_TIME,
|
||||
name: 'dm2',
|
||||
value: `${dt_chan2}`,
|
||||
}),
|
||||
];
|
||||
|
||||
const channels: Channel[] = [{
|
||||
id: 'dm1',
|
||||
|
|
@ -472,11 +474,11 @@ describe('Categories utils', () => {
|
|||
const myChannelModels = await db.operator.handleMyChannel({channels, myChannels, prepareRecordsOnly: false});
|
||||
const data: ChannelWithMyChannel[] = [{
|
||||
channel: channelModels[0],
|
||||
myChannel: myChannelModels[0] as MyChannelModel,
|
||||
myChannel: myChannelModels[0],
|
||||
sortOrder: 0,
|
||||
}, {
|
||||
channel: channelModels[1],
|
||||
myChannel: myChannelModels[1] as MyChannelModel,
|
||||
myChannel: myChannelModels[1],
|
||||
sortOrder: 0,
|
||||
}];
|
||||
|
||||
|
|
@ -491,10 +493,10 @@ describe('Categories utils', () => {
|
|||
|
||||
const lastViewedData: ChannelWithMyChannel[] = [{
|
||||
...data[0],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
...data[0].myChannel,
|
||||
lastViewedAt: 0,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}, data[1]];
|
||||
|
||||
const autoclosePrefsNotViewed = [autoclosePrefs[1]];
|
||||
|
|
@ -502,10 +504,10 @@ describe('Categories utils', () => {
|
|||
expect(result.length).toEqual(1);
|
||||
|
||||
const deactivated = new Map<string, UserModel>();
|
||||
deactivated.set('other1', {
|
||||
deactivated.set('other1', TestHelper.fakeUserModel({
|
||||
id: 'other1',
|
||||
deleteAt: dt_chan1 + 1,
|
||||
} as UserModel);
|
||||
}));
|
||||
|
||||
result = filterAutoclosedDMs('direct_messages', 3, 'me', '', data, autoclosePrefs, {}, deactivated);
|
||||
expect(result.length).toEqual(1);
|
||||
|
|
@ -515,29 +517,29 @@ describe('Categories utils', () => {
|
|||
|
||||
const mockNotUnread: ChannelWithMyChannel[] = [data[0], {
|
||||
...data[1],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[1].myChannel.id,
|
||||
lastViewedAt: 0,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}];
|
||||
result = filterAutoclosedDMs('direct_messages', 3, 'me', '', mockNotUnread, autoclosePrefs, {}, undefined, 'dm1');
|
||||
expect(result[0].channel.id).toEqual('dm1');
|
||||
|
||||
const mockRecent1: ChannelWithMyChannel[] = [{
|
||||
...data[0],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[0].myChannel.id,
|
||||
lastViewedAt: 2,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}, {
|
||||
...data[1],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[1].myChannel.id,
|
||||
lastViewedAt: 1,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}];
|
||||
|
||||
result = filterAutoclosedDMs('direct_messages', 3, 'me', '', mockRecent1, [], {});
|
||||
|
|
@ -545,18 +547,18 @@ describe('Categories utils', () => {
|
|||
|
||||
const mockRecent2: ChannelWithMyChannel[] = [{
|
||||
...data[0],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[0].myChannel.id,
|
||||
lastViewedAt: 1,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}, {
|
||||
...data[1],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[1].myChannel.id,
|
||||
lastViewedAt: 2,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}];
|
||||
|
||||
result = filterAutoclosedDMs('direct_messages', 3, 'me', '', mockRecent2, [], {});
|
||||
|
|
@ -564,18 +566,18 @@ describe('Categories utils', () => {
|
|||
|
||||
const mockSameLastViewed: ChannelWithMyChannel[] = [{
|
||||
...data[0],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[0].myChannel.id,
|
||||
lastViewedAt: 1,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}, {
|
||||
...data[1],
|
||||
myChannel: {
|
||||
myChannel: TestHelper.fakeMyChannelModel({
|
||||
id: data[1].myChannel.id,
|
||||
lastViewedAt: 1,
|
||||
isUnread: false,
|
||||
} as MyChannelModel,
|
||||
}),
|
||||
}];
|
||||
|
||||
result = filterAutoclosedDMs('direct_messages', 3, 'me', '', mockSameLastViewed, [], {});
|
||||
|
|
@ -585,25 +587,29 @@ describe('Categories utils', () => {
|
|||
test('filterManuallyClosedDms', async () => {
|
||||
const db = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
||||
const closedDMsPrefs = [{
|
||||
id: 'pref1',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.DIRECT_CHANNEL_SHOW,
|
||||
name: 'dm1',
|
||||
value: 'true',
|
||||
}, {
|
||||
id: 'pref2',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.DIRECT_CHANNEL_SHOW,
|
||||
name: 'dm2',
|
||||
value: 'true',
|
||||
}, {
|
||||
id: 'pref3',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.GROUP_CHANNEL_SHOW,
|
||||
name: 'gm1',
|
||||
value: 'false',
|
||||
}] as PreferenceModel[];
|
||||
const closedDMsPrefs = [
|
||||
TestHelper.fakePreferenceModel({
|
||||
id: 'pref1',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.DIRECT_CHANNEL_SHOW,
|
||||
name: 'dm1',
|
||||
value: 'true',
|
||||
}),
|
||||
TestHelper.fakePreferenceModel({
|
||||
id: 'pref2',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.DIRECT_CHANNEL_SHOW,
|
||||
name: 'dm2',
|
||||
value: 'true',
|
||||
}),
|
||||
TestHelper.fakePreferenceModel({
|
||||
id: 'pref3',
|
||||
userId: 'me',
|
||||
category: Preferences.CATEGORIES.GROUP_CHANNEL_SHOW,
|
||||
name: 'gm1',
|
||||
value: 'false',
|
||||
}),
|
||||
];
|
||||
|
||||
const {channels, myChannels} = buildChannelsData();
|
||||
const data = await createChannelsDbRecords(db, channels, myChannels);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {getUsersCountFromMentions} from '@actions/local/post';
|
|||
import {General, Post} from '@constants';
|
||||
import {DEFAULT_LOCALE, getTranslations} from '@i18n';
|
||||
import {getUserById} from '@queries/servers/user';
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {toMilliseconds} from '@utils/datetime';
|
||||
|
||||
import {
|
||||
|
|
@ -28,9 +29,6 @@ import {
|
|||
persistentNotificationsConfirmation,
|
||||
} from '.';
|
||||
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
jest.mock('@actions/local/post', () => ({
|
||||
getUsersCountFromMentions: jest.fn(),
|
||||
}));
|
||||
|
|
@ -48,32 +46,32 @@ jest.mock('@database/manager', () => ({
|
|||
describe('post utils', () => {
|
||||
describe('areConsecutivePosts', () => {
|
||||
it('should return true for consecutive posts from the same user within the collapse timeout', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
userId: 'user1',
|
||||
createAt: 1000,
|
||||
props: {},
|
||||
} as PostModel;
|
||||
const previousPost = {
|
||||
});
|
||||
const previousPost = TestHelper.fakePostModel({
|
||||
userId: 'user1',
|
||||
createAt: 500,
|
||||
props: {},
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = areConsecutivePosts(post, previousPost);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for posts from different users', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
userId: 'user1',
|
||||
createAt: 1000,
|
||||
props: {},
|
||||
} as PostModel;
|
||||
const previousPost = {
|
||||
});
|
||||
const previousPost = TestHelper.fakePostModel({
|
||||
userId: 'user2',
|
||||
createAt: 500,
|
||||
props: {},
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = areConsecutivePosts(post, previousPost);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -82,22 +80,22 @@ describe('post utils', () => {
|
|||
|
||||
describe('isFromWebhook', () => {
|
||||
it('should return true for posts from a webhook', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {
|
||||
from_webhook: 'true',
|
||||
} as Record<string, unknown>,
|
||||
} as PostModel;
|
||||
},
|
||||
});
|
||||
|
||||
const result = isFromWebhook(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for posts not from a webhook', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {
|
||||
from_webhook: 'false',
|
||||
} as Record<string, unknown>,
|
||||
} as PostModel;
|
||||
},
|
||||
});
|
||||
|
||||
const result = isFromWebhook(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -106,18 +104,18 @@ describe('post utils', () => {
|
|||
|
||||
describe('isEdited', () => {
|
||||
it('should return true if the post is edited', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
editAt: 1000,
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isEdited(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the post is not edited', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
editAt: 0,
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isEdited(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -126,18 +124,18 @@ describe('post utils', () => {
|
|||
|
||||
describe('isPostEphemeral', () => {
|
||||
it('should return true for an ephemeral post', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
type: Post.POST_TYPES.EPHEMERAL,
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostEphemeral(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for a non-ephemeral post', () => {
|
||||
const post = {
|
||||
type: 'normal',
|
||||
} as PostModel;
|
||||
const post = TestHelper.fakePostModel({
|
||||
type: '',
|
||||
});
|
||||
|
||||
const result = isPostEphemeral(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -146,38 +144,38 @@ describe('post utils', () => {
|
|||
|
||||
describe('isPostFailed', () => {
|
||||
it('should return true if the post has failed prop', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {
|
||||
failed: true,
|
||||
} as Record<string, unknown>,
|
||||
},
|
||||
pendingPostId: 'id',
|
||||
id: 'id',
|
||||
updateAt: Date.now() - Post.POST_TIME_TO_FAIL - 1000,
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostFailed(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if the post is pending and the update time has exceeded the failure time', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {},
|
||||
pendingPostId: 'id',
|
||||
id: 'id',
|
||||
updateAt: Date.now() - Post.POST_TIME_TO_FAIL - 1000,
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostFailed(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the post is not failed', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {},
|
||||
pendingPostId: 'id',
|
||||
id: 'id',
|
||||
updateAt: Date.now(),
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostFailed(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -186,34 +184,34 @@ describe('post utils', () => {
|
|||
|
||||
describe('isPostPendingOrFailed', () => {
|
||||
it('should return true if the post is pending', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
pendingPostId: 'id',
|
||||
id: 'id',
|
||||
props: {},
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostPendingOrFailed(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if the post has failed', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
pendingPostId: 'id',
|
||||
id: 'id',
|
||||
updateAt: Date.now() - Post.POST_TIME_TO_FAIL - 1000,
|
||||
props: {},
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostPendingOrFailed(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the post is neither pending nor failed', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
pendingPostId: 'differentId',
|
||||
id: 'id',
|
||||
props: {},
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = isPostPendingOrFailed(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -222,18 +220,18 @@ describe('post utils', () => {
|
|||
|
||||
describe('isSystemMessage', () => {
|
||||
it('should return true if the post is a system message', () => {
|
||||
const post = {
|
||||
type: `${Post.POST_TYPES.SYSTEM_MESSAGE_PREFIX}any_type`,
|
||||
} as PostModel;
|
||||
const post = TestHelper.fakePostModel({
|
||||
type: `${Post.POST_TYPES.SYSTEM_MESSAGE_PREFIX}any_type` as PostType,
|
||||
});
|
||||
|
||||
const result = isSystemMessage(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the post is not a system message', () => {
|
||||
const post = {
|
||||
type: 'normal_type',
|
||||
} as PostModel;
|
||||
const post = TestHelper.fakePostModel({
|
||||
type: 'add_bot_teams_channels',
|
||||
});
|
||||
|
||||
const result = isSystemMessage(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -290,18 +288,18 @@ describe('post utils', () => {
|
|||
|
||||
describe('fromAutoResponder', () => {
|
||||
it('should return true if the post is from an auto responder', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
type: Post.POST_TYPES.SYSTEM_AUTO_RESPONDER,
|
||||
} as PostModel;
|
||||
});
|
||||
|
||||
const result = fromAutoResponder(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the post is not from an auto responder', () => {
|
||||
const post = {
|
||||
type: 'normal_type',
|
||||
} as PostModel;
|
||||
const post = TestHelper.fakePostModel({
|
||||
type: 'add_bot_teams_channels',
|
||||
});
|
||||
|
||||
const result = fromAutoResponder(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -320,8 +318,8 @@ describe('post utils', () => {
|
|||
const intl = createIntl({locale: DEFAULT_LOCALE, messages: getTranslations(DEFAULT_LOCALE)});
|
||||
|
||||
it('should show alert with DM channel description when channelType is DM_CHANNEL', async () => {
|
||||
const mockUser = {username: 'teammate'};
|
||||
(getUserById as jest.Mock).mockResolvedValue(mockUser);
|
||||
const mockUser = TestHelper.fakeUserModel({username: 'teammate'});
|
||||
jest.mocked(getUserById).mockResolvedValue(mockUser);
|
||||
|
||||
await persistentNotificationsConfirmation(
|
||||
serverUrl,
|
||||
|
|
@ -376,7 +374,7 @@ describe('post utils', () => {
|
|||
});
|
||||
|
||||
it('should show alert when no mentions found', async () => {
|
||||
(getUsersCountFromMentions as jest.Mock).mockResolvedValue(0);
|
||||
jest.mocked(getUsersCountFromMentions).mockResolvedValue(0);
|
||||
|
||||
await persistentNotificationsConfirmation(
|
||||
serverUrl,
|
||||
|
|
@ -404,7 +402,7 @@ describe('post utils', () => {
|
|||
});
|
||||
|
||||
it('should show alert when mentions exceed max recipients', async () => {
|
||||
(getUsersCountFromMentions as jest.Mock).mockResolvedValue(15);
|
||||
jest.mocked(getUsersCountFromMentions).mockResolvedValue(15);
|
||||
|
||||
await persistentNotificationsConfirmation(
|
||||
serverUrl,
|
||||
|
|
@ -435,7 +433,7 @@ describe('post utils', () => {
|
|||
});
|
||||
|
||||
it('should show confirmation alert for valid mentions within limit', async () => {
|
||||
(getUsersCountFromMentions as jest.Mock).mockResolvedValue(5);
|
||||
jest.mocked(getUsersCountFromMentions).mockResolvedValue(5);
|
||||
|
||||
await persistentNotificationsConfirmation(
|
||||
serverUrl,
|
||||
|
|
@ -467,42 +465,42 @@ describe('post utils', () => {
|
|||
|
||||
describe('postUserDisplayName', () => {
|
||||
it('should return the override username if from webhook and override is enabled', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {
|
||||
from_webhook: 'true',
|
||||
override_username: 'webhook_user',
|
||||
} as Record<string, unknown>,
|
||||
} as PostModel;
|
||||
},
|
||||
});
|
||||
|
||||
const result = postUserDisplayName(post, undefined, undefined, true);
|
||||
expect(result).toBe('webhook_user');
|
||||
});
|
||||
|
||||
it('should return the author’s display name if not from webhook or override is disabled', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {
|
||||
from_webhook: 'false',
|
||||
} as Record<string, unknown>,
|
||||
} as PostModel;
|
||||
const author = {
|
||||
},
|
||||
});
|
||||
const author = TestHelper.fakeUserModel({
|
||||
username: 'user1',
|
||||
locale: 'en',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
const result = postUserDisplayName(post, author, undefined, false);
|
||||
expect(result).toBe('user1');
|
||||
});
|
||||
|
||||
it('should return the author’s display name using the teammate name display', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePostModel({
|
||||
props: {
|
||||
from_webhook: 'false',
|
||||
} as Record<string, unknown>,
|
||||
} as PostModel;
|
||||
const author = {
|
||||
},
|
||||
});
|
||||
const author = TestHelper.fakeUserModel({
|
||||
username: 'user1',
|
||||
locale: 'en',
|
||||
} as UserModel;
|
||||
});
|
||||
|
||||
const result = postUserDisplayName(post, author, 'nickname', false);
|
||||
expect(result).toBe('user1');
|
||||
|
|
@ -511,18 +509,18 @@ describe('post utils', () => {
|
|||
|
||||
describe('shouldIgnorePost', () => {
|
||||
it('should return true if the post type is in the ignore list', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePost({
|
||||
type: Post.POST_TYPES.CHANNEL_DELETED,
|
||||
} as Post;
|
||||
});
|
||||
|
||||
const result = shouldIgnorePost(post);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the post type is not in the ignore list', () => {
|
||||
const post = {
|
||||
const post = TestHelper.fakePost({
|
||||
type: Post.POST_TYPES.EPHEMERAL,
|
||||
} as Post;
|
||||
});
|
||||
|
||||
const result = shouldIgnorePost(post);
|
||||
expect(result).toBe(false);
|
||||
|
|
@ -534,17 +532,17 @@ describe('post utils', () => {
|
|||
const data = {
|
||||
order: ['post1', 'post2'],
|
||||
posts: {
|
||||
post1: {id: 'post1', message: 'First post'},
|
||||
post2: {id: 'post2', message: 'Second post'},
|
||||
post1: TestHelper.fakePost({id: 'post1', message: 'First post'}),
|
||||
post2: TestHelper.fakePost({id: 'post2', message: 'Second post'}),
|
||||
},
|
||||
prev_post_id: 'post0',
|
||||
} as unknown as PostResponse;
|
||||
};
|
||||
|
||||
const result = processPostsFetched(data);
|
||||
expect(result).toEqual({
|
||||
posts: [
|
||||
{id: 'post1', message: 'First post'},
|
||||
{id: 'post2', message: 'Second post'},
|
||||
expect.objectContaining({id: 'post1', message: 'First post'}),
|
||||
expect.objectContaining({id: 'post2', message: 'Second post'}),
|
||||
],
|
||||
order: ['post1', 'post2'],
|
||||
previousPostId: 'post0',
|
||||
|
|
@ -555,9 +553,9 @@ describe('post utils', () => {
|
|||
describe('getLastFetchedAtFromPosts', () => {
|
||||
it('should return the maximum timestamp from the posts', () => {
|
||||
const posts = [
|
||||
{create_at: 1000, update_at: 2000, delete_at: 0},
|
||||
{create_at: 1500, update_at: 2500, delete_at: 3000},
|
||||
] as Post[];
|
||||
TestHelper.fakePost({create_at: 1000, update_at: 2000, delete_at: 0}),
|
||||
TestHelper.fakePost({create_at: 1500, update_at: 2500, delete_at: 3000}),
|
||||
];
|
||||
|
||||
const result = getLastFetchedAtFromPosts(posts);
|
||||
expect(result).toBe(3000);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import DatabaseManager from '@database/manager';
|
|||
import {DEFAULT_LOCALE} from '@i18n';
|
||||
import {getUserById} from '@queries/servers/user';
|
||||
import {toMilliseconds} from '@utils/datetime';
|
||||
import {ensureString} from '@utils/types';
|
||||
import {ensureString, includes} from '@utils/types';
|
||||
import {displayUsername, getUserIdFromChannelName} from '@utils/user';
|
||||
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
|
|
@ -78,7 +78,7 @@ export function postUserDisplayName(post: PostModel, author?: UserModel, teammat
|
|||
}
|
||||
|
||||
export function shouldIgnorePost(post: Post): boolean {
|
||||
return Post.IGNORE_POST_TYPES.includes(post.type);
|
||||
return includes(Post.IGNORE_POST_TYPES, post.type);
|
||||
}
|
||||
|
||||
export const processPostsFetched = (data: PostResponse) => {
|
||||
|
|
|
|||
|
|
@ -593,8 +593,8 @@ describe('preparePostList', () => {
|
|||
|
||||
it('should combine user activity posts correctly', () => {
|
||||
const posts = [
|
||||
mockPostModel({id: 'post1', type: 'user-activity', props: {user_activity_posts: []}}),
|
||||
mockPostModel({id: 'post2', type: 'user-activity', props: {user_activity_posts: []}}),
|
||||
mockPostModel({id: 'post1', type: 'system_combined_user_activity', props: {user_activity_posts: []}}),
|
||||
mockPostModel({id: 'post2', type: 'system_combined_user_activity', props: {user_activity_posts: []}}),
|
||||
];
|
||||
|
||||
const result = preparePostList(posts, lastViewedAt, true, currentUserId, currentUsername, showJoinLeave, currentTimezone, isThreadScreen, savedPostIds);
|
||||
|
|
@ -613,7 +613,7 @@ describe('preparePostList', () => {
|
|||
id: 'deleted-post',
|
||||
deleteAt: Date.now(), // Set deleteAt to a non-zero value
|
||||
createAt: Date.now(),
|
||||
type: 'post', // Ensure it's a 'post' type
|
||||
type: '',
|
||||
userId: 'user-id',
|
||||
message: 'This is a deleted post',
|
||||
props: {},
|
||||
|
|
@ -732,7 +732,7 @@ describe('shouldFilterJoinLeavePost', () => {
|
|||
const currentUsername = 'current-username';
|
||||
|
||||
it('should not filter non-join/leave posts', () => {
|
||||
const post = mockPostModel({type: 'custom_post_type'});
|
||||
const post = mockPostModel({type: 'custom_post_type' as PostType});
|
||||
const result = shouldFilterJoinLeavePost(post, false, currentUsername);
|
||||
|
||||
// Non-join/leave posts should not be filtered regardless of showJoinLeave value
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import moment from 'moment-timezone';
|
|||
import {Post} from '@constants';
|
||||
import {toMilliseconds} from '@utils/datetime';
|
||||
import {isFromWebhook} from '@utils/post';
|
||||
import {ensureString, isArrayOf, isStringArray} from '@utils/types';
|
||||
import {ensureString, includes, isArrayOf, isStringArray, secureGetFromRecord} from '@utils/types';
|
||||
|
||||
import type {PostList, PostWithPrevAndNext} from '@typings/components/post_list';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
|
|
@ -73,7 +73,7 @@ function combineUserActivityPosts(orderedPosts: PostList) {
|
|||
lastPostIsUserActivity = false;
|
||||
combinedCount = 0;
|
||||
} else {
|
||||
const postIsUserActivity = item.type === 'post' && Post.USER_ACTIVITY_POST_TYPES.includes(item.value.currentPost.type);
|
||||
const postIsUserActivity = item.type === 'post' && includes(Post.USER_ACTIVITY_POST_TYPES, item.value.currentPost.type);
|
||||
if (postIsUserActivity && lastPostIsUserActivity && combinedCount < MAX_COMBINED_SYSTEM_POSTS) {
|
||||
out[out.length - 1].value += '_' + item.value.currentPost.id;
|
||||
} else if (postIsUserActivity) {
|
||||
|
|
@ -96,21 +96,26 @@ function combineUserActivityPosts(orderedPosts: PostList) {
|
|||
return out;
|
||||
}
|
||||
|
||||
function comparePostTypes(a: typeof postTypePriority, b: typeof postTypePriority) {
|
||||
return postTypePriority[a.postType] - postTypePriority[b.postType];
|
||||
function comparePostTypes(a: MessageData, b: MessageData) {
|
||||
const aPriority = secureGetFromRecord(postTypePriority, a.postType) ?? 99;
|
||||
const bPriority = secureGetFromRecord(postTypePriority, b.postType) ?? 99;
|
||||
return aPriority - bPriority;
|
||||
}
|
||||
|
||||
function extractUserActivityData(userActivities: any) {
|
||||
const messageData: any[] = [];
|
||||
function extractUserActivityData(userActivities: Record<PostType, UserActivityValue>): UserActivityProp {
|
||||
const messageData: MessageData[] = [];
|
||||
const allUserIds: string[] = [];
|
||||
const allUsernames: string[] = [];
|
||||
Object.entries(userActivities).forEach(([postType, values]: [string, any]) => {
|
||||
Object.entries(userActivities).forEach(([postType, values]: [PostType, UserActivityValue]) => {
|
||||
if (
|
||||
postType === Post.POST_TYPES.ADD_TO_TEAM ||
|
||||
postType === Post.POST_TYPES.ADD_TO_CHANNEL ||
|
||||
postType === Post.POST_TYPES.REMOVE_FROM_CHANNEL
|
||||
) {
|
||||
Object.keys(values).map((key) => [key, values[key]]).forEach(([actorId, users]) => {
|
||||
if (Array.isArray(values)) {
|
||||
throw new Error('Invalid Post activity data');
|
||||
}
|
||||
Object.entries(values).forEach(([actorId, users]) => {
|
||||
if (Array.isArray(users)) {
|
||||
throw new Error('Invalid Post activity data');
|
||||
}
|
||||
|
|
@ -256,10 +261,15 @@ export function selectOrderedPosts(
|
|||
return out.reverse();
|
||||
}
|
||||
|
||||
type ActivityData = {
|
||||
ids: string[];
|
||||
usernames: string[];
|
||||
}
|
||||
type UserActivityValue = string[] | Record<string, ActivityData>
|
||||
function combineUserActivitySystemPost(systemPosts: PostModel[]) {
|
||||
const userActivities = systemPosts.reduce((acc: any, post: PostModel) => {
|
||||
const userActivities = systemPosts.reduce((acc: Record<string, UserActivityValue>, post: PostModel) => {
|
||||
const postType = post.type;
|
||||
let userActivityProps = acc;
|
||||
const userActivityProps = acc;
|
||||
const combinedPostType = userActivityProps[postType];
|
||||
|
||||
if (
|
||||
|
|
@ -270,10 +280,12 @@ function combineUserActivitySystemPost(systemPosts: PostModel[]) {
|
|||
const userId = ensureString(post.props?.addedUserId) || ensureString(post.props?.removedUserId);
|
||||
const username = ensureString(post.props?.addedUsername) || ensureString(post.props?.removedUsername);
|
||||
if (combinedPostType) {
|
||||
if (Array.isArray(combinedPostType[post.userId])) {
|
||||
if (Array.isArray(combinedPostType)) {
|
||||
throw new Error('Invalid Post activity data');
|
||||
}
|
||||
const users = combinedPostType[post.userId] || {ids: [], usernames: []};
|
||||
|
||||
const userCombinedPostType = combinedPostType[post.userId];
|
||||
const users = userCombinedPostType || {ids: [], usernames: []};
|
||||
if (userId) {
|
||||
if (!users.ids.includes(userId)) {
|
||||
users.ids.push(userId);
|
||||
|
|
@ -308,7 +320,7 @@ function combineUserActivitySystemPost(systemPosts: PostModel[]) {
|
|||
userActivityProps[postType] = [...combinedPostType, propsUserId];
|
||||
}
|
||||
} else {
|
||||
userActivityProps = {...userActivityProps, [postType]: [propsUserId]};
|
||||
userActivityProps[postType] = [propsUserId];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -348,7 +360,7 @@ export function generateCombinedPost(combinedId: string, systemPosts: PostModel[
|
|||
user_activity_posts: systemPosts,
|
||||
system_post_ids: systemPosts.map((post) => post.id),
|
||||
},
|
||||
type: Post.POST_TYPES.COMBINED_USER_ACTIVITY as PostType,
|
||||
type: Post.POST_TYPES.COMBINED_USER_ACTIVITY,
|
||||
user_id: '',
|
||||
metadata: {},
|
||||
};
|
||||
|
|
@ -380,7 +392,7 @@ export function shouldFilterJoinLeavePost(post: PostModel, showJoinLeave: boolea
|
|||
}
|
||||
|
||||
// Don't filter out non-join/leave messages
|
||||
if (joinLeavePostTypes.indexOf(post.type) === -1) {
|
||||
if (!includes(joinLeavePostTypes, post.type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -390,7 +402,7 @@ export function shouldFilterJoinLeavePost(post: PostModel, showJoinLeave: boolea
|
|||
|
||||
export type MessageData = {
|
||||
actorId?: string;
|
||||
postType: string;
|
||||
postType: PostType;
|
||||
userIds: string[];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,3 +40,7 @@ export function ensureNumber(v: unknown): number {
|
|||
export function secureGetFromRecord<T>(v: Record<string, T> | undefined, key: string) {
|
||||
return typeof v === 'object' && v && Object.prototype.hasOwnProperty.call(v, key) ? v[key] : undefined;
|
||||
}
|
||||
|
||||
export function includes<T extends U, U>(array: T[], value: U) {
|
||||
return array.includes(value as T);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ describe('UrlUtils', () => {
|
|||
const SERVER_WITH_SUBPATH = `http://${URL_PATH_NO_PROTOCOL}`;
|
||||
const DEEPLINK_URL_ROOT = `mattermost://${URL_NO_PROTOCOL}`;
|
||||
|
||||
const DM_USER = TestHelper.fakeUserWithId();
|
||||
const DM_USER = TestHelper.fakeUser();
|
||||
const GM_CHANNEL_NAME = '4862db64e76a321d167fe6677f16e96e9275dabe';
|
||||
|
||||
const tests = [
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {Alert} from 'react-native';
|
|||
|
||||
import {Preferences} from '@constants';
|
||||
import {Ringtone} from '@constants/calls';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {
|
||||
confirmOutOfOfficeDisabled,
|
||||
|
|
@ -38,16 +39,15 @@ import {
|
|||
removeUserFromList,
|
||||
} from './index';
|
||||
|
||||
import type {UserModel} from '@database/models/server';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
describe('displayUsername', () => {
|
||||
const user = {
|
||||
const user = TestHelper.fakeUser({
|
||||
username: 'johndoe',
|
||||
first_name: 'John',
|
||||
last_name: 'Doe',
|
||||
nickname: 'Johnny',
|
||||
} as UserProfile;
|
||||
});
|
||||
|
||||
it('should return the nickname if teammateDisplayNameSetting is DISPLAY_PREFER_NICKNAME', () => {
|
||||
const result = displayUsername(user, 'en', Preferences.DISPLAY_PREFER_NICKNAME);
|
||||
|
|
@ -80,32 +80,32 @@ describe('displayUsername', () => {
|
|||
});
|
||||
|
||||
it('should return the username if nickname and full name are not available', () => {
|
||||
const userWithoutNicknameAndFullName = {
|
||||
const userWithoutNicknameAndFullName = TestHelper.fakeUser({
|
||||
username: 'johndoe',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
nickname: '',
|
||||
} as UserProfile;
|
||||
});
|
||||
const result = displayUsername(userWithoutNicknameAndFullName, 'en', Preferences.DISPLAY_PREFER_NICKNAME);
|
||||
expect(result).toBe('johndoe');
|
||||
});
|
||||
|
||||
it('should return the username if name is empty or whitespace', () => {
|
||||
const userWithEmptyName = {
|
||||
const userWithEmptyName = TestHelper.fakeUser({
|
||||
username: 'johndoe',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
nickname: '',
|
||||
} as UserProfile;
|
||||
});
|
||||
const result = displayUsername(userWithEmptyName, 'en', Preferences.DISPLAY_PREFER_FULL_NAME);
|
||||
expect(result).toBe('johndoe');
|
||||
});
|
||||
});
|
||||
|
||||
describe('displayGroupMessageName', () => {
|
||||
const user1 = {id: 'user1', username: 'john_doe', first_name: 'John', last_name: 'Doe'} as UserProfile;
|
||||
const user2 = {id: 'user2', username: 'jane_doe', first_name: 'Jane', last_name: 'Doe'} as UserProfile;
|
||||
const user3 = {id: 'user3', username: 'alice_smith', first_name: 'Alice', last_name: 'Smith'} as UserProfile;
|
||||
const user1 = TestHelper.fakeUser({id: 'user1', username: 'john_doe', first_name: 'John', last_name: 'Doe'});
|
||||
const user2 = TestHelper.fakeUser({id: 'user2', username: 'jane_doe', first_name: 'Jane', last_name: 'Doe'});
|
||||
const user3 = TestHelper.fakeUser({id: 'user3', username: 'alice_smith', first_name: 'Alice', last_name: 'Smith'});
|
||||
|
||||
it('should return a comma-separated list of usernames', () => {
|
||||
const users = [user1, user2, user3];
|
||||
|
|
@ -133,7 +133,7 @@ describe('displayGroupMessageName', () => {
|
|||
});
|
||||
|
||||
it('should fallback to username if full name or nickname is not available', () => {
|
||||
const userWithEmptyName = {id: 'user4', username: 'empty_name', first_name: '', last_name: ''} as UserProfile;
|
||||
const userWithEmptyName = TestHelper.fakeUser({id: 'user4', username: 'empty_name', first_name: '', last_name: ''});
|
||||
const users = [userWithEmptyName, user2, user3];
|
||||
const result = displayGroupMessageName(users, undefined, Preferences.DISPLAY_PREFER_FULL_NAME);
|
||||
expect(result).toBe('Alice Smith, empty_name, Jane Doe');
|
||||
|
|
@ -148,31 +148,31 @@ describe('displayGroupMessageName', () => {
|
|||
|
||||
describe('getFullName', () => {
|
||||
it('should return the full name if both first and last names are provided - UserProfile', () => {
|
||||
const user = {first_name: 'John', last_name: 'Doe'} as UserProfile;
|
||||
const user = TestHelper.fakeUser({first_name: 'John', last_name: 'Doe'});
|
||||
const result = getFullName(user);
|
||||
expect(result).toBe('John Doe');
|
||||
});
|
||||
|
||||
it('should return the full name if both first and last names are provided - UserModel', () => {
|
||||
const user = {firstName: 'John', lastName: 'Doe'} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({firstName: 'John', lastName: 'Doe'});
|
||||
const result = getFullName(user);
|
||||
expect(result).toBe('John Doe');
|
||||
});
|
||||
|
||||
it('should return the first name if only the first name is provided', () => {
|
||||
const user = {first_name: 'John', last_name: ''} as UserProfile;
|
||||
const user = TestHelper.fakeUser({first_name: 'John', last_name: ''});
|
||||
const result = getFullName(user);
|
||||
expect(result).toBe('John');
|
||||
});
|
||||
|
||||
it('should return the last name if only the last name is provided', () => {
|
||||
const user = {first_name: '', last_name: 'Doe'} as UserProfile;
|
||||
const user = TestHelper.fakeUser({first_name: '', last_name: 'Doe'});
|
||||
const result = getFullName(user);
|
||||
expect(result).toBe('Doe');
|
||||
});
|
||||
|
||||
it('should return an empty string if neither first nor last name is provided', () => {
|
||||
const user = {first_name: '', last_name: ''} as UserProfile;
|
||||
const user = TestHelper.fakeUser({first_name: '', last_name: ''});
|
||||
const result = getFullName(user);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
|
@ -255,8 +255,8 @@ describe('isChannelAdmin', () => {
|
|||
describe('getUsersByUsername', () => {
|
||||
it('should return a dictionary of users by username', () => {
|
||||
const users = [
|
||||
{username: 'john_doe'} as UserModel,
|
||||
{username: 'jane_doe'} as UserModel,
|
||||
TestHelper.fakeUserModel({username: 'john_doe'}),
|
||||
TestHelper.fakeUserModel({username: 'jane_doe'}),
|
||||
];
|
||||
const result = getUsersByUsername(users);
|
||||
expect(result).toEqual({
|
||||
|
|
@ -268,7 +268,7 @@ describe('getUsersByUsername', () => {
|
|||
|
||||
describe('getUserTimezoneProps', () => {
|
||||
it('should return the user timezone props if they exist', () => {
|
||||
const user = {timezone: {useAutomaticTimezone: 'true', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'}} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({timezone: {useAutomaticTimezone: 'true', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'}});
|
||||
const result = getUserTimezoneProps(user);
|
||||
expect(result).toEqual({
|
||||
useAutomaticTimezone: true,
|
||||
|
|
@ -278,7 +278,7 @@ describe('getUserTimezoneProps', () => {
|
|||
});
|
||||
|
||||
it('should return default timezone props if they do not exist', () => {
|
||||
const user = {} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({timezone: null});
|
||||
const result = getUserTimezoneProps(user);
|
||||
expect(result).toEqual({
|
||||
useAutomaticTimezone: true,
|
||||
|
|
@ -290,13 +290,13 @@ describe('getUserTimezoneProps', () => {
|
|||
|
||||
describe('getUserTimezone', () => {
|
||||
it('should return the user timezone', () => {
|
||||
const user = {timezone: {useAutomaticTimezone: 'true', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'}} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({timezone: {useAutomaticTimezone: 'true', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'}});
|
||||
const result = getUserTimezone(user);
|
||||
expect(result).toBe('America/New_York');
|
||||
});
|
||||
|
||||
it('should return an empty string if the user timezone does not exist', () => {
|
||||
const user = {} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({timezone: null});
|
||||
const result = getUserTimezone(user);
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
|
@ -304,13 +304,13 @@ describe('getUserTimezone', () => {
|
|||
|
||||
describe('getTimezone', () => {
|
||||
it('should return the automatic timezone if useAutomaticTimezone is true', () => {
|
||||
const timezone = {useAutomaticTimezone: 'true', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'} as UserTimezone;
|
||||
const timezone: UserTimezone = {useAutomaticTimezone: 'true', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'};
|
||||
const result = getTimezone(timezone);
|
||||
expect(result).toBe('America/New_York');
|
||||
});
|
||||
|
||||
it('should return the manual timezone if useAutomaticTimezone is false', () => {
|
||||
const timezone = {useAutomaticTimezone: 'false', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'} as UserTimezone;
|
||||
const timezone: UserTimezone = {useAutomaticTimezone: 'false', automaticTimezone: 'America/New_York', manualTimezone: 'America/Los_Angeles'};
|
||||
const result = getTimezone(timezone);
|
||||
expect(result).toBe('America/Los_Angeles');
|
||||
});
|
||||
|
|
@ -337,10 +337,10 @@ describe('getTimezoneRegion', () => {
|
|||
|
||||
describe('getUserCustomStatus', () => {
|
||||
it('should return the custom status if it exists', () => {
|
||||
const user = {
|
||||
const user = TestHelper.fakeUser({
|
||||
username: 'johndoe',
|
||||
props: {customStatus: '{"emoji": "smile", "text": "Happy", "duration": "today", "expires_at": "2023-12-31T23:59:59Z"}'} as UserProps,
|
||||
} as UserProfile;
|
||||
props: {customStatus: '{"emoji": "smile", "text": "Happy", "duration": "today", "expires_at": "2023-12-31T23:59:59Z"}'},
|
||||
});
|
||||
const result = getUserCustomStatus(user);
|
||||
expect(result).toEqual({
|
||||
emoji: 'smile',
|
||||
|
|
@ -351,7 +351,7 @@ describe('getUserCustomStatus', () => {
|
|||
});
|
||||
|
||||
it('should return undefined if the custom status does not exist', () => {
|
||||
const user = {} as UserModel;
|
||||
const user = TestHelper.fakeUserModel();
|
||||
const result = getUserCustomStatus(user);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
|
@ -359,23 +359,25 @@ describe('getUserCustomStatus', () => {
|
|||
|
||||
describe('isCustomStatusExpired', () => {
|
||||
it('should return true if the custom status is expired', () => {
|
||||
const user = {username: 'john_doe',
|
||||
props: {customStatus: '{"emoji": "smile", "text": "Happy", "duration": "today", "expires_at": "2020-12-31T23:59:59Z"}'} as UserProps,
|
||||
} as UserProfile;
|
||||
const user = TestHelper.fakeUser({
|
||||
username: 'john_doe',
|
||||
props: {customStatus: '{"emoji": "smile", "text": "Happy", "duration": "today", "expires_at": "2020-12-31T23:59:59Z"}'},
|
||||
});
|
||||
const result = isCustomStatusExpired(user);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the custom status is not expired', () => {
|
||||
const user = {username: 'john_doe',
|
||||
props: {customStatus: '{"emoji": "smile", "text": "Happy", "duration": "today", "expires_at": "2099-12-31T23:59:59Z"}'} as UserProps,
|
||||
} as UserProfile;
|
||||
const user = TestHelper.fakeUser({
|
||||
username: 'john_doe',
|
||||
props: {customStatus: '{"emoji": "smile", "text": "Happy", "duration": "today", "expires_at": "2099-12-31T23:59:59Z"}'},
|
||||
});
|
||||
const result = isCustomStatusExpired(user);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if the custom status does not exist', () => {
|
||||
const user = {} as UserModel;
|
||||
const user = TestHelper.fakeUserModel();
|
||||
const result = isCustomStatusExpired(user);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
|
@ -383,13 +385,13 @@ describe('isCustomStatusExpired', () => {
|
|||
|
||||
describe('isBot', () => {
|
||||
it('should return true if the user is a bot', () => {
|
||||
const user = {isBot: true} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({isBot: true});
|
||||
const result = isBot(user);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the user is not a bot', () => {
|
||||
const user = {isBot: false} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({isBot: false});
|
||||
const result = isBot(user);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
|
@ -397,13 +399,13 @@ describe('isBot', () => {
|
|||
|
||||
describe('isShared', () => {
|
||||
it('should return true if the user is shared', () => {
|
||||
const user = {remoteId: 'remote_id'} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({remoteId: 'remote_id'});
|
||||
const result = isShared(user);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the user is not shared', () => {
|
||||
const user = {remoteId: ''} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({remoteId: ''});
|
||||
const result = isShared(user);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
|
@ -437,8 +439,8 @@ describe('getSuggestionsSplitByMultiple', () => {
|
|||
|
||||
describe('filterProfilesMatchingTerm', () => {
|
||||
const users = [
|
||||
{username: 'john_doe', first_name: 'John', last_name: 'Doe', nickname: 'Johnny', email: 'john@example.com'} as UserProfile,
|
||||
{username: 'jane_doe', first_name: 'Jane', last_name: 'Doe', nickname: 'Janey', email: 'jane@example.com'} as UserProfile,
|
||||
TestHelper.fakeUser({username: 'john_doe', first_name: 'John', last_name: 'Doe', nickname: 'Johnny', email: 'john@example.com'}),
|
||||
TestHelper.fakeUser({username: 'jane_doe', first_name: 'Jane', last_name: 'Doe', nickname: 'Janey', email: 'jane@example.com'}),
|
||||
];
|
||||
|
||||
it('should filter users matching the term', () => {
|
||||
|
|
@ -468,13 +470,13 @@ describe('filterProfilesMatchingTerm', () => {
|
|||
|
||||
describe('getNotificationProps', () => {
|
||||
it('should return the user notification props if they exist', () => {
|
||||
const user = {notifyProps: {channel: 'false', comments: 'never'}} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({notifyProps: TestHelper.fakeUserNotifyProps({channel: 'false', comments: 'never'})});
|
||||
const result = getNotificationProps(user);
|
||||
expect(result).toEqual(user.notifyProps);
|
||||
});
|
||||
|
||||
it('should return default notification props if they do not exist', () => {
|
||||
const user = {} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({firstName: '', notifyProps: null});
|
||||
const result = getNotificationProps(user);
|
||||
expect(result).toEqual({
|
||||
channel: 'true',
|
||||
|
|
@ -484,7 +486,7 @@ describe('getNotificationProps', () => {
|
|||
email: 'true',
|
||||
first_name: 'false',
|
||||
mark_unread: 'all',
|
||||
mention_keys: '',
|
||||
mention_keys: `${user.username},@${user.username}`,
|
||||
highlight_keys: '',
|
||||
push: 'mention',
|
||||
push_status: 'online',
|
||||
|
|
@ -531,19 +533,19 @@ describe('getEmailIntervalTexts', () => {
|
|||
|
||||
describe('getLastPictureUpdate', () => {
|
||||
it('should return bot_last_icon_update if the user is a bot', () => {
|
||||
const user = {isBot: true, props: {bot_last_icon_update: 12345} as UserProps} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({isBot: true, props: {bot_last_icon_update: 12345}});
|
||||
const result = getLastPictureUpdate(user);
|
||||
expect(result).toBe(12345);
|
||||
});
|
||||
|
||||
it('should return lastPictureUpdate if the user is not a bot', () => {
|
||||
const user = {isBot: false, lastPictureUpdate: 67890} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({isBot: false, lastPictureUpdate: 67890});
|
||||
const result = getLastPictureUpdate(user);
|
||||
expect(result).toBe(67890);
|
||||
});
|
||||
|
||||
it('should return 0 if lastPictureUpdate is not available', () => {
|
||||
const user = {isBot: false} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({isBot: false});
|
||||
const result = getLastPictureUpdate(user);
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
|
|
@ -551,34 +553,34 @@ describe('getLastPictureUpdate', () => {
|
|||
|
||||
describe('isDeactivated', () => {
|
||||
it('should return true if the user is deactivated', () => {
|
||||
const user = {delete_at: 12345} as UserProfile;
|
||||
const user = TestHelper.fakeUser({delete_at: 12345});
|
||||
const result = isDeactivated(user);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the user is not deactivated', () => {
|
||||
const user = {delete_at: 0} as UserProfile;
|
||||
const user = TestHelper.fakeUser({delete_at: 0});
|
||||
const result = isDeactivated(user);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if the user is deactivated using deleteAt', () => {
|
||||
const user = {deleteAt: 12345} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({deleteAt: 12345});
|
||||
const result = isDeactivated(user);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the user is not deactivated using deleteAt', () => {
|
||||
const user = {deleteAt: 0} as UserModel;
|
||||
const user = TestHelper.fakeUserModel({deleteAt: 0});
|
||||
const result = isDeactivated(user);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeUserFromList', () => {
|
||||
const user1 = {id: 'user1'} as UserProfile;
|
||||
const user2 = {id: 'user2'} as UserProfile;
|
||||
const user3 = {id: 'user3'} as UserProfile;
|
||||
const user1 = TestHelper.fakeUser({id: 'user1'});
|
||||
const user2 = TestHelper.fakeUser({id: 'user2'});
|
||||
const user3 = TestHelper.fakeUser({id: 'user3'});
|
||||
|
||||
it('should remove the user from the list', () => {
|
||||
const originalList = [user1, user2, user3];
|
||||
|
|
@ -669,8 +671,8 @@ describe('confirmOutOfOfficeDisabled', () => {
|
|||
it('should call updateStatus with the correct status when OK is pressed', () => {
|
||||
confirmOutOfOfficeDisabled(intl, 'online', updateStatus);
|
||||
|
||||
const okButton = (Alert.alert as jest.Mock).mock.calls[0][2][1];
|
||||
okButton.onPress();
|
||||
const okButton = jest.mocked(Alert.alert).mock.calls[0][2]?.[1];
|
||||
okButton?.onPress?.();
|
||||
|
||||
expect(updateStatus).toHaveBeenCalledWith('online');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,7 +19,25 @@ import DatabaseManager from '@database/manager';
|
|||
import {prepareCommonSystemValues} from '@queries/servers/system';
|
||||
|
||||
import type {APIClientInterface} from '@mattermost/react-native-network-client';
|
||||
import type {Model, Query} from '@nozbe/watermelondb';
|
||||
import type {Model, Query, Relation} from '@nozbe/watermelondb';
|
||||
import type CategoryChannelModel from '@typings/database/models/servers/category_channel';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type ChannelBookmarkModel from '@typings/database/models/servers/channel_bookmark';
|
||||
import type ChannelInfoModel from '@typings/database/models/servers/channel_info';
|
||||
import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership';
|
||||
import type DraftModel from '@typings/database/models/servers/draft';
|
||||
import type FileModel from '@typings/database/models/servers/file';
|
||||
import type GroupModel from '@typings/database/models/servers/group';
|
||||
import type MyChannelModel from '@typings/database/models/servers/my_channel';
|
||||
import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings';
|
||||
import type MyTeamModel from '@typings/database/models/servers/my_team';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type PostsInChannelModel from '@typings/database/models/servers/posts_in_channel';
|
||||
import type PreferenceModel from '@typings/database/models/servers/preference';
|
||||
import type RoleModel from '@typings/database/models/servers/role';
|
||||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
import type ThreadModel from '@typings/database/models/servers/thread';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const DEFAULT_LOCALE = 'en';
|
||||
|
||||
|
|
@ -247,6 +265,19 @@ class TestHelperSingleton {
|
|||
};
|
||||
};
|
||||
|
||||
fakeChannelInfo = (overwrite: Partial<ChannelInfo>): ChannelInfo => {
|
||||
return {
|
||||
id: this.generateId(),
|
||||
guest_count: 0,
|
||||
header: '',
|
||||
member_count: 0,
|
||||
purpose: '',
|
||||
pinned_post_count: 0,
|
||||
files_count: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeChannelWithId = (teamId: string): Channel => {
|
||||
return {
|
||||
...this.fakeChannel({team_id: teamId}),
|
||||
|
|
@ -319,7 +350,7 @@ class TestHelperSingleton {
|
|||
return 'success' + this.generateId() + '@simulator.amazonses.com';
|
||||
};
|
||||
|
||||
fakePost = (overwrite: Partial<Post>): Post => {
|
||||
fakePost = (overwrite?: Partial<Post>): Post => {
|
||||
const time = Date.now();
|
||||
|
||||
return {
|
||||
|
|
@ -424,7 +455,424 @@ class TestHelperSingleton {
|
|||
};
|
||||
};
|
||||
|
||||
fakeUser = (): UserProfile => {
|
||||
fakeQuery = <T extends Model>(returnValue: T[]): Query<T> => {
|
||||
return {
|
||||
fetch: jest.fn().mockImplementation(async () => returnValue),
|
||||
observe: jest.fn().mockImplementation(() => of$(returnValue)),
|
||||
} as unknown as Query<T>;
|
||||
};
|
||||
|
||||
fakeRelation = <T extends Model>(returnValue?: T): Relation<T> => {
|
||||
return {
|
||||
fetch: jest.fn().mockImplementation(async () => returnValue!),
|
||||
_model: {} as T,
|
||||
_columnName: '',
|
||||
_relationTableName: '',
|
||||
_isImmutable: false,
|
||||
_cachedObservable: of$(returnValue!),
|
||||
id: this.generateId(),
|
||||
then: jest.fn(),
|
||||
set: jest.fn(),
|
||||
observe: jest.fn().mockImplementation(() => of$(returnValue!)),
|
||||
};
|
||||
};
|
||||
|
||||
fakeModel = () => {
|
||||
return {
|
||||
id: this.generateId(),
|
||||
_raw: {} as any,
|
||||
collection: {} as any,
|
||||
collections: {} as any,
|
||||
database: {} as any,
|
||||
db: {} as any,
|
||||
asModel: {} as any,
|
||||
_isEditing: false,
|
||||
_preparedState: 'create' as const,
|
||||
syncStatus: 'synced' as const,
|
||||
table: '',
|
||||
_subscribers: [],
|
||||
_getChanges: jest.fn(),
|
||||
update: jest.fn(),
|
||||
prepareUpdate: jest.fn(),
|
||||
cancelPrepareUpdate: jest.fn(),
|
||||
prepareMarkAsDeleted: jest.fn(),
|
||||
prepareDestroyPermanently: jest.fn(),
|
||||
markAsDeleted: jest.fn(),
|
||||
destroyPermanently: jest.fn(),
|
||||
experimentalMarkAsDeleted: jest.fn(),
|
||||
experimentalDestroyPermanently: jest.fn(),
|
||||
observe: jest.fn(),
|
||||
batch: jest.fn(),
|
||||
callWriter: jest.fn(),
|
||||
callReader: jest.fn(),
|
||||
subAction: jest.fn(),
|
||||
experimentalSubscribe: jest.fn(),
|
||||
_notifyChanged: jest.fn(),
|
||||
_notifyDestroyed: jest.fn(),
|
||||
_getRaw: jest.fn(),
|
||||
_setRaw: jest.fn(),
|
||||
_dangerouslySetRawWithoutMarkingColumnChange: jest.fn(),
|
||||
__ensureCanSetRaw: jest.fn(),
|
||||
__ensureNotDisposable: jest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
fakeUserModel = (overwrite?: Partial<UserModel>): UserModel => {
|
||||
const modelBase = this.fakeModel();
|
||||
return {
|
||||
...modelBase,
|
||||
email: this.fakeEmail(),
|
||||
locale: DEFAULT_LOCALE,
|
||||
username: this.generateId(),
|
||||
firstName: this.generateId(),
|
||||
lastName: this.generateId(),
|
||||
deleteAt: 0,
|
||||
roles: 'system_user',
|
||||
authService: '',
|
||||
id: this.generateId(),
|
||||
nickname: '',
|
||||
notifyProps: this.fakeUserNotifyProps(),
|
||||
position: '',
|
||||
updateAt: 0,
|
||||
isBot: false,
|
||||
isGuest: false,
|
||||
lastPictureUpdate: 0,
|
||||
status: 'offline',
|
||||
remoteId: null,
|
||||
props: {},
|
||||
timezone: {automaticTimezone: 'UTC', manualTimezone: '', useAutomaticTimezone: true},
|
||||
mentionKeys: [],
|
||||
userMentionKeys: [],
|
||||
highlightKeys: [],
|
||||
termsOfServiceId: '',
|
||||
termsOfServiceCreateAt: 0,
|
||||
|
||||
channelsCreated: this.fakeQuery([]),
|
||||
channels: this.fakeQuery([]),
|
||||
posts: this.fakeQuery([]),
|
||||
preferences: this.fakeQuery([]),
|
||||
reactions: this.fakeQuery([]),
|
||||
teams: this.fakeQuery([]),
|
||||
threadParticipations: this.fakeQuery([]),
|
||||
|
||||
prepareStatus: () => null,
|
||||
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeChannelModel = (overwrite?: Partial<ChannelModel>): ChannelModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
createAt: 0,
|
||||
creatorId: this.generateId(),
|
||||
deleteAt: 0,
|
||||
updateAt: 0,
|
||||
displayName: this.generateId(),
|
||||
isGroupConstrained: false,
|
||||
name: this.generateId(),
|
||||
shared: false,
|
||||
teamId: this.generateId(),
|
||||
type: 'O' as const,
|
||||
members: this.fakeQuery([]),
|
||||
drafts: this.fakeQuery([]),
|
||||
bookmarks: this.fakeQuery([]),
|
||||
posts: this.fakeQuery([]),
|
||||
postsInChannel: this.fakeQuery([]),
|
||||
team: this.fakeRelation(),
|
||||
creator: this.fakeRelation(),
|
||||
info: this.fakeRelation(),
|
||||
membership: this.fakeRelation(),
|
||||
categoryChannel: this.fakeRelation(),
|
||||
toApi: jest.fn(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeChannelMembershipModel = (overwrite?: Partial<ChannelMembershipModel>): ChannelMembershipModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channelId: this.generateId(),
|
||||
userId: this.generateId(),
|
||||
schemeAdmin: false,
|
||||
memberChannel: this.fakeRelation(),
|
||||
memberUser: this.fakeRelation(),
|
||||
getAllChannelsForUser: this.fakeQuery([]),
|
||||
getAllUsersInChannel: this.fakeQuery([]),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
fakeMyChannelMembershipModel = (overwrite?: Partial<MyChannelModel>): MyChannelModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channel: this.fakeRelation(),
|
||||
lastPostAt: 0,
|
||||
lastFetchedAt: 0,
|
||||
lastViewedAt: 0,
|
||||
manuallyUnread: false,
|
||||
mentionsCount: 0,
|
||||
messageCount: 0,
|
||||
isUnread: false,
|
||||
roles: '',
|
||||
viewedAt: 0,
|
||||
settings: this.fakeRelation(),
|
||||
resetPreparedState: jest.fn(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeCategoryChannelModel = (overwrite?: Partial<CategoryChannelModel>): CategoryChannelModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channel: this.fakeRelation(),
|
||||
categoryId: this.generateId(),
|
||||
channelId: this.generateId(),
|
||||
sortOrder: 0,
|
||||
category: this.fakeRelation(),
|
||||
myChannel: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeDraftModel = (overwrite?: Partial<DraftModel>): DraftModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channelId: this.generateId(),
|
||||
message: '',
|
||||
rootId: '',
|
||||
files: [],
|
||||
metadata: {},
|
||||
updateAt: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakePostsInChannelModel = (overwrite?: Partial<PostsInChannelModel>): PostsInChannelModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channelId: this.generateId(),
|
||||
earliest: 0,
|
||||
latest: 0,
|
||||
channel: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeChannelBookmarkModel = (overwrite?: Partial<ChannelBookmarkModel>): ChannelBookmarkModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channelId: this.generateId(),
|
||||
ownerId: this.generateId(),
|
||||
fileId: this.generateId(),
|
||||
displayName: this.generateId(),
|
||||
createAt: 0,
|
||||
updateAt: 0,
|
||||
deleteAt: 0,
|
||||
sortOrder: 0,
|
||||
type: 'file',
|
||||
channel: this.fakeRelation(),
|
||||
owner: this.fakeRelation(),
|
||||
file: this.fakeRelation(),
|
||||
toApi: jest.fn(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeFileModel = (overwrite?: Partial<FileModel>): FileModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
id: this.generateId(),
|
||||
extension: 'png',
|
||||
height: 100,
|
||||
width: 100,
|
||||
mimeType: 'image/png',
|
||||
name: 'image1',
|
||||
size: 100,
|
||||
imageThumbnail: '',
|
||||
localPath: 'path/to/image1',
|
||||
postId: this.generateId(),
|
||||
post: this.fakeRelation(),
|
||||
toFileInfo: jest.fn(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeMyChannelSettingsModel = (overwrite?: Partial<MyChannelSettingsModel>): MyChannelSettingsModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
notifyProps: this.fakeChannelNotifyProps(),
|
||||
myChannel: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeTeamModel = (overwrite?: Partial<TeamModel>): TeamModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
id: this.generateId(),
|
||||
name: this.generateId(),
|
||||
displayName: this.generateId(),
|
||||
type: 'O' as const,
|
||||
allowedDomains: '',
|
||||
inviteId: this.generateId(),
|
||||
description: '',
|
||||
updateAt: 0,
|
||||
isAllowOpenInvite: true,
|
||||
isGroupConstrained: false,
|
||||
lastTeamIconUpdatedAt: 0,
|
||||
categories: this.fakeQuery([]),
|
||||
channels: this.fakeQuery([]),
|
||||
myTeam: this.fakeRelation(),
|
||||
teamChannelHistory: this.fakeRelation(),
|
||||
members: this.fakeQuery([]),
|
||||
teamSearchHistories: this.fakeQuery([]),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeChannelInfoModel = (overwrite?: Partial<ChannelInfoModel>): ChannelInfoModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
guestCount: 0,
|
||||
header: '',
|
||||
memberCount: 0,
|
||||
pinnedPostCount: 0,
|
||||
filesCount: 0,
|
||||
purpose: '',
|
||||
channel: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakePostModel = (overwrite?: Partial<PostModel>): PostModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
channelId: this.generateId(),
|
||||
createAt: 0,
|
||||
deleteAt: 0,
|
||||
editAt: 0,
|
||||
isPinned: false,
|
||||
message: '',
|
||||
metadata: {},
|
||||
originalId: '',
|
||||
pendingPostId: '',
|
||||
props: {},
|
||||
rootId: '',
|
||||
type: '',
|
||||
updateAt: 0,
|
||||
messageSource: '',
|
||||
previousPostId: '',
|
||||
userId: this.generateId(),
|
||||
root: this.fakeQuery([]),
|
||||
drafts: this.fakeQuery([]),
|
||||
files: this.fakeQuery([]),
|
||||
postsInThread: this.fakeQuery([]),
|
||||
reactions: this.fakeQuery([]),
|
||||
author: this.fakeRelation(),
|
||||
channel: this.fakeRelation(),
|
||||
thread: this.fakeRelation(),
|
||||
hasReplies: async () => false,
|
||||
toApi: jest.fn(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeGroupModel = (overwrite?: Partial<GroupModel>): GroupModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
name: this.generateId(),
|
||||
displayName: this.generateId(),
|
||||
description: this.generateId(),
|
||||
source: this.generateId(),
|
||||
remoteId: this.generateId(),
|
||||
createdAt: 0,
|
||||
updatedAt: 0,
|
||||
deletedAt: 0,
|
||||
memberCount: 0,
|
||||
channels: this.fakeQuery([]),
|
||||
teams: this.fakeQuery([]),
|
||||
members: this.fakeQuery([]),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeMyChannelModel = (overwrite?: Partial<MyChannelModel>): MyChannelModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
lastPostAt: 0,
|
||||
lastFetchedAt: 0,
|
||||
lastViewedAt: 0,
|
||||
manuallyUnread: false,
|
||||
mentionsCount: 0,
|
||||
messageCount: 0,
|
||||
isUnread: false,
|
||||
roles: '',
|
||||
viewedAt: 0,
|
||||
channel: this.fakeRelation(),
|
||||
settings: this.fakeRelation(),
|
||||
resetPreparedState: jest.fn(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeRoleModel = (overwrite?: Partial<RoleModel>): RoleModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
name: this.generateId(),
|
||||
permissions: [],
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeThreadModel = (overwrite?: Partial<ThreadModel>): ThreadModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
lastReplyAt: 0,
|
||||
lastFetchedAt: 0,
|
||||
lastViewedAt: 0,
|
||||
replyCount: 0,
|
||||
isFollowing: false,
|
||||
unreadReplies: 0,
|
||||
unreadMentions: 0,
|
||||
viewedAt: 0,
|
||||
participants: this.fakeQuery([]),
|
||||
threadsInTeam: this.fakeQuery([]),
|
||||
post: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeMyTeamModel = (overwrite?: Partial<MyTeamModel>): MyTeamModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
roles: '',
|
||||
team: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakePreferenceModel = (overwrite?: Partial<PreferenceModel>): PreferenceModel => {
|
||||
return {
|
||||
...this.fakeModel(),
|
||||
value: '',
|
||||
category: '',
|
||||
name: '',
|
||||
userId: '',
|
||||
user: this.fakeRelation(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeRole = (overwrite?: Partial<Role>): Role => {
|
||||
return {
|
||||
id: this.generateId(),
|
||||
name: this.generateId(),
|
||||
permissions: [],
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeUser = (overwrite?: Partial<UserProfile>): UserProfile => {
|
||||
return {
|
||||
email: this.fakeEmail(),
|
||||
locale: DEFAULT_LOCALE,
|
||||
|
|
@ -437,13 +885,14 @@ class TestHelperSingleton {
|
|||
auth_service: '',
|
||||
id: this.generateId(),
|
||||
nickname: '',
|
||||
notify_props: this.fakeNotifyProps(),
|
||||
notify_props: this.fakeUserNotifyProps(),
|
||||
position: '',
|
||||
update_at: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeNotifyProps = (): UserNotifyProps => {
|
||||
fakeUserNotifyProps = (overwrite?: Partial<UserNotifyProps>): UserNotifyProps => {
|
||||
return {
|
||||
channel: 'false',
|
||||
comments: 'root',
|
||||
|
|
@ -456,41 +905,23 @@ class TestHelperSingleton {
|
|||
push: 'default',
|
||||
push_status: 'away',
|
||||
calls_desktop_sound: 'true',
|
||||
calls_mobile_notification_sound: '',
|
||||
calls_mobile_notification_sound: Ringtone.Calm,
|
||||
calls_mobile_sound: 'true',
|
||||
calls_notification_sound: '',
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeUserWithId = (id = this.generateId()): UserProfile => {
|
||||
fakeChannelNotifyProps = (overwrite?: Partial<ChannelNotifyProps>): ChannelNotifyProps => {
|
||||
return {
|
||||
...this.fakeUser(),
|
||||
id,
|
||||
create_at: 1507840900004,
|
||||
update_at: 1507840900004,
|
||||
delete_at: 0,
|
||||
auth_service: '',
|
||||
nickname: '',
|
||||
notify_props: {
|
||||
desktop: 'default',
|
||||
desktop_sound: 'true',
|
||||
email: 'true',
|
||||
mark_unread: 'all',
|
||||
push: 'default',
|
||||
push_status: 'away',
|
||||
comments: 'any',
|
||||
first_name: 'true',
|
||||
channel: 'true',
|
||||
mention_keys: '',
|
||||
highlight_keys: '',
|
||||
calls_desktop_sound: 'true',
|
||||
calls_mobile_sound: '',
|
||||
calls_notification_sound: Ringtone.Calm,
|
||||
calls_mobile_notification_sound: '',
|
||||
},
|
||||
last_picture_update: 0,
|
||||
position: '',
|
||||
is_bot: false,
|
||||
channel_auto_follow_threads: 'on',
|
||||
desktop: 'default',
|
||||
email: 'default',
|
||||
mark_unread: 'all',
|
||||
push: 'default',
|
||||
ignore_channel_mentions: 'off',
|
||||
push_threads: 'mention',
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -589,7 +1020,7 @@ class TestHelperSingleton {
|
|||
};
|
||||
|
||||
initMockEntities = () => {
|
||||
this.basicUser = this.fakeUserWithId();
|
||||
this.basicUser = this.fakeUser();
|
||||
this.basicUser.roles = 'system_user system_admin';
|
||||
this.basicTeam = this.fakeTeamWithId();
|
||||
this.basicTeamMember = this.fakeTeamMember(this.basicUser.id, this.basicTeam.id);
|
||||
|
|
|
|||
13
types/api/posts.d.ts
vendored
13
types/api/posts.d.ts
vendored
|
|
@ -16,7 +16,18 @@ type PostType =
|
|||
| 'system_join_leave'
|
||||
| 'system_leave_channel'
|
||||
| 'system_purpose_change'
|
||||
| 'system_remove_from_channel';
|
||||
| 'system_remove_from_channel'
|
||||
| 'system_ephemeral_add_to_channel'
|
||||
| 'system_guest_join_channel'
|
||||
| 'system_add_guest_to_chan'
|
||||
| 'system_join_team'
|
||||
| 'system_leave_team'
|
||||
| 'system_remove_from_team'
|
||||
| 'system_combined_user_activity'
|
||||
| 'add_bot_teams_channels'
|
||||
| 'system_auto_responder'
|
||||
| 'custom_calls'
|
||||
| 'custom_calls_recording';
|
||||
|
||||
type PostEmbedType = 'image' | 'message_attachment' | 'opengraph';
|
||||
|
||||
|
|
|
|||
|
|
@ -43,24 +43,24 @@ export type ServerDatabases = {
|
|||
[x: string]: ServerDatabase | undefined;
|
||||
};
|
||||
|
||||
export type TransformerArgs = {
|
||||
export type TransformerArgs<T extends Model, R extends RawValue> = {
|
||||
action: string;
|
||||
database: Database;
|
||||
fieldsMapper?: (model: Model) => void;
|
||||
tableName?: string;
|
||||
value: RecordPair;
|
||||
value: RecordPair<T, R>;
|
||||
};
|
||||
|
||||
export type PrepareBaseRecordArgs = TransformerArgs & {
|
||||
export type PrepareBaseRecordArgs<T extends Model, R extends RawValue> = TransformerArgs<T, R> & {
|
||||
fieldsMapper: (model: Model) => void;
|
||||
}
|
||||
|
||||
export type OperationArgs<T extends Model> = {
|
||||
export type OperationArgs<T extends Model, R extends RawValue> = {
|
||||
tableName: string;
|
||||
createRaws?: RecordPair[];
|
||||
updateRaws?: RecordPair[];
|
||||
createRaws?: Array<RecordPair<T, R>>;
|
||||
updateRaws?: Array<RecordPair<T, R>>;
|
||||
deleteRaws?: T[];
|
||||
transformer: (args: TransformerArgs) => Promise<T>;
|
||||
transformer: (args: TransformerArgs<T, R>) => Promise<T>;
|
||||
};
|
||||
|
||||
export type Models = Array<Class<Model>>;
|
||||
|
|
@ -137,9 +137,9 @@ export type SanitizePostsArgs = {
|
|||
posts: Post[];
|
||||
};
|
||||
|
||||
export type IdenticalRecordArgs = {
|
||||
existingRecord: Model;
|
||||
newValue: RawValue;
|
||||
export type IdenticalRecordArgs<T extends Model, R extends RawValue> = {
|
||||
existingRecord: T;
|
||||
newValue: R;
|
||||
tableName: string;
|
||||
};
|
||||
|
||||
|
|
@ -149,21 +149,21 @@ export type RetrieveRecordsArgs = {
|
|||
condition: Clause;
|
||||
};
|
||||
|
||||
export type ProcessRecordsArgs = {
|
||||
createOrUpdateRawValues: RawValue[];
|
||||
deleteRawValues: RawValue[];
|
||||
export type ProcessRecordsArgs<R extends RawValue> = {
|
||||
createOrUpdateRawValues: R[];
|
||||
deleteRawValues: R[];
|
||||
tableName: string;
|
||||
fieldName: string;
|
||||
buildKeyRecordBy?: (obj: Record<string, any>) => string;
|
||||
shouldUpdate?: (existing: Record<string, any>, newRaw: Record<string, any>) => boolean;
|
||||
};
|
||||
|
||||
export type HandleRecordsArgs<T extends Model> = {
|
||||
export type HandleRecordsArgs<T extends Model, R extends RawValue> = {
|
||||
buildKeyRecordBy?: (obj: Record<string, any>) => string;
|
||||
fieldName: string;
|
||||
transformer: (args: TransformerArgs) => Promise<T>;
|
||||
createOrUpdateRawValues: RawValue[];
|
||||
deleteRawValues?: RawValue[];
|
||||
transformer: (args: TransformerArgs<T, R>) => Promise<T>;
|
||||
createOrUpdateRawValues: R[];
|
||||
deleteRawValues?: R[];
|
||||
tableName: string;
|
||||
prepareRecordsOnly: boolean;
|
||||
shouldUpdate?: (existingRecord: T, newRaw: RawValue) => boolean;
|
||||
|
|
@ -174,9 +174,9 @@ export type RangeOfValueArgs = {
|
|||
fieldName: string;
|
||||
};
|
||||
|
||||
export type RecordPair = {
|
||||
record?: Model;
|
||||
raw: RawValue;
|
||||
export type RecordPair<T extends Model, R extends RawValue> = {
|
||||
record?: T;
|
||||
raw: R;
|
||||
};
|
||||
|
||||
type PrepareOnly = {
|
||||
|
|
@ -317,8 +317,8 @@ export type GetDatabaseConnectionArgs = {
|
|||
setAsActiveDatabase: boolean;
|
||||
}
|
||||
|
||||
export type ProcessRecordResults<T extends Model> = {
|
||||
createRaws: RecordPair[];
|
||||
updateRaws: RecordPair[];
|
||||
export type ProcessRecordResults<T extends Model, R extends RawValue> = {
|
||||
createRaws: Array<RecordPair<T, R>>;
|
||||
updateRaws: Array<RecordPair<T, R>>;
|
||||
deleteRaws: T[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ declare class PostModel extends Model {
|
|||
rootId: string;
|
||||
|
||||
/** type : Type of props (e.g. system message) */
|
||||
type: string;
|
||||
type: PostType;
|
||||
|
||||
/** user_id : The foreign key of the User who authored this post. */
|
||||
userId: string;
|
||||
|
|
|
|||
1
types/database/raw_values.d.ts
vendored
1
types/database/raw_values.d.ts
vendored
|
|
@ -136,4 +136,5 @@ type RawValue =
|
|||
| ThreadParticipant
|
||||
| TeamThreadsSync
|
||||
| UserProfile
|
||||
| SlashCommand
|
||||
| Pick<ChannelMembership, 'channel_id' | 'user_id'>
|
||||
|
|
|
|||
Loading…
Reference in a new issue