Fix team sidebar not showing thread unreads (#8624)
* Fix team sidebar not showing thread unreads * Fix tests --------- Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
parent
59252d98fb
commit
b475f2bedb
20 changed files with 793 additions and 169 deletions
|
|
@ -111,7 +111,7 @@ describe('sendEphemeralPost', () => {
|
|||
});
|
||||
|
||||
describe('removePost', () => {
|
||||
const post = {...TestHelper.fakePost(channelId), id: 'postid'};
|
||||
const post = TestHelper.fakePost({id: 'postid', channel_id: channelId});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const {post: rPost, error} = await removePost('foo', post);
|
||||
|
|
@ -139,12 +139,12 @@ describe('removePost', () => {
|
|||
});
|
||||
|
||||
it('base case - system message', async () => {
|
||||
const systemPost = {...TestHelper.fakePost(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 as PostType, props: {system_post_ids: ['id1']}});
|
||||
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [post.id, 'id1'],
|
||||
posts: [systemPost, {...TestHelper.fakePost(channelId), id: 'id1'}],
|
||||
posts: [systemPost, TestHelper.fakePost({id: 'id1', channel_id: channelId})],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ describe('removePost', () => {
|
|||
});
|
||||
|
||||
describe('markPostAsDeleted', () => {
|
||||
const post = TestHelper.fakePost(channelId);
|
||||
const post = TestHelper.fakePost({channel_id: channelId});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const {model, error} = await markPostAsDeleted('foo', post);
|
||||
|
|
@ -185,8 +185,7 @@ describe('markPostAsDeleted', () => {
|
|||
});
|
||||
|
||||
describe('storePostsForChannel', () => {
|
||||
const post = TestHelper.fakePost(channelId);
|
||||
post.user_id = user.id;
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user.id});
|
||||
const teamId = 'tId1';
|
||||
const channel: Channel = {
|
||||
id: channelId,
|
||||
|
|
@ -226,7 +225,7 @@ describe('storePostsForChannel', () => {
|
|||
});
|
||||
|
||||
describe('getPosts', () => {
|
||||
const post = TestHelper.fakePost(channelId);
|
||||
const post = TestHelper.fakePost({channel_id: channelId});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const posts = await getPosts('foo', [post.id]);
|
||||
|
|
@ -249,7 +248,7 @@ describe('getPosts', () => {
|
|||
});
|
||||
|
||||
describe('addPostAcknowledgement', () => {
|
||||
const post = TestHelper.fakePost(channelId);
|
||||
const post = TestHelper.fakePost({channel_id: channelId});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const {model, error} = await addPostAcknowledgement('foo', post.id, user.id, 123, false);
|
||||
|
|
@ -292,7 +291,7 @@ describe('addPostAcknowledgement', () => {
|
|||
});
|
||||
|
||||
describe('removePostAcknowledgement', () => {
|
||||
const post = TestHelper.fakePost(channelId);
|
||||
const post = TestHelper.fakePost({channel_id: channelId});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const {model, error} = await removePostAcknowledgement('foo', post.id, user.id, false);
|
||||
|
|
@ -321,7 +320,7 @@ describe('removePostAcknowledgement', () => {
|
|||
});
|
||||
|
||||
describe('deletePosts', () => {
|
||||
const post = TestHelper.fakePost(channelId);
|
||||
const post = TestHelper.fakePost({channel_id: channelId});
|
||||
|
||||
it('handle not found database', async () => {
|
||||
const {error} = await deletePosts('foo', [post.id]);
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ describe('dataRetention', () => {
|
|||
});
|
||||
|
||||
it('rentention off - dataRetentionCleanup', async () => {
|
||||
const post = {...TestHelper.fakePost('channelid1'), id: 'postid', create_at: 1};
|
||||
const post = TestHelper.fakePost({channel_id: 'channelid1', id: 'postid', create_at: 1});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [post.id],
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ const user2: UserProfile = {
|
|||
roles: '',
|
||||
} as UserProfile;
|
||||
|
||||
const rootPost = {...TestHelper.fakePost(channelId, user.id), id: 'rootpostid', create_at: 1};
|
||||
const rootPost = TestHelper.fakePost({channel_id: channelId, user_id: user.id, id: 'rootpostid', create_at: 1});
|
||||
const threads = [
|
||||
{
|
||||
id: rootPost.id,
|
||||
|
|
@ -147,7 +147,7 @@ describe('switchToThread', () => {
|
|||
it('handle no channel', async () => {
|
||||
await operator.handleUsers({users: [user], prepareRecordsOnly: false});
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
|
||||
const post = {...TestHelper.fakePost(channelId, user2.id), id: 'postid', create_at: 1};
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user2.id, id: 'postid', create_at: 1});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [post.id],
|
||||
|
|
@ -165,7 +165,7 @@ describe('switchToThread', () => {
|
|||
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: 'teamid2'}, {id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
|
||||
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
|
||||
const post = {...TestHelper.fakePost(channelId, user2.id), id: 'postid', create_at: 1};
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user2.id, id: 'postid', create_at: 1});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [post.id],
|
||||
|
|
@ -183,7 +183,7 @@ describe('switchToThread', () => {
|
|||
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: 'teamid2'}, {id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
|
||||
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
|
||||
const post = {...TestHelper.fakePost(channelId, user2.id), id: 'postid', create_at: 1};
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user2.id, id: 'postid', create_at: 1});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [post.id],
|
||||
|
|
@ -201,7 +201,7 @@ describe('switchToThread', () => {
|
|||
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: 'teamid2'}, {id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
|
||||
await operator.handleChannel({channels: [{...channel, team_id: '', type: 'D', display_name: 'user1-user2'}], prepareRecordsOnly: false});
|
||||
const post = {...TestHelper.fakePost(channelId, user2.id), id: 'postid', create_at: 1};
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user2.id, id: 'postid', create_at: 1});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_IN_CHANNEL,
|
||||
order: [post.id],
|
||||
|
|
@ -224,7 +224,7 @@ describe('createThreadFromNewPost', () => {
|
|||
it('base case', async () => {
|
||||
await operator.handleUsers({users: [user, user2], prepareRecordsOnly: false});
|
||||
await operator.handleThreads({threads, prepareRecordsOnly: false, teamId: team.id});
|
||||
const post = {...TestHelper.fakePost(channelId, user2.id), id: 'postid', create_at: 1, root_id: rootPost.id};
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user2.id, id: 'postid', create_at: 1, root_id: rootPost.id});
|
||||
|
||||
const {models, error} = await createThreadFromNewPost(serverUrl, post, false);
|
||||
expect(error).toBeUndefined();
|
||||
|
|
@ -234,7 +234,7 @@ describe('createThreadFromNewPost', () => {
|
|||
|
||||
it('base case - no root post', async () => {
|
||||
await operator.handleUsers({users: [user2], prepareRecordsOnly: false});
|
||||
const post = {...TestHelper.fakePost(channelId, user2.id), id: 'postid', create_at: 1};
|
||||
const post = TestHelper.fakePost({channel_id: channelId, user_id: user2.id, id: 'postid', create_at: 1});
|
||||
|
||||
const {models, error} = await createThreadFromNewPost(serverUrl, post);
|
||||
expect(error).toBeUndefined();
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ describe('Performance metrics are set correctly', () => {
|
|||
expect(client).toBeTruthy();
|
||||
operator = (await TestHelper.setupServerDatabase(serverUrl)).operator;
|
||||
await DatabaseManager.setActiveServerDatabase(serverUrl);
|
||||
post = TestHelper.fakePost(TestHelper.basicChannel!.id);
|
||||
post = TestHelper.fakePost({channel_id: TestHelper.basicChannel!.id});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: [post.id],
|
||||
|
|
@ -101,8 +101,7 @@ describe('Performance metrics are set correctly', () => {
|
|||
});
|
||||
|
||||
it('thread notification', async () => {
|
||||
const commentPost = TestHelper.fakePost(TestHelper.basicChannel!.id);
|
||||
commentPost.root_id = post.id;
|
||||
const commentPost = TestHelper.fakePost({channel_id: TestHelper.basicChannel!.id, root_id: post.id});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: [commentPost.id],
|
||||
|
|
@ -134,8 +133,7 @@ describe('Performance metrics are set correctly', () => {
|
|||
});
|
||||
|
||||
it('thread notification with wrong root id', async () => {
|
||||
const commentPost = TestHelper.fakePost(TestHelper.basicChannel!.id);
|
||||
commentPost.root_id = post.id;
|
||||
const commentPost = TestHelper.fakePost({channel_id: TestHelper.basicChannel!.id, root_id: post.id});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: [commentPost.id],
|
||||
|
|
@ -167,8 +165,7 @@ describe('Performance metrics are set correctly', () => {
|
|||
});
|
||||
|
||||
it('thread notification with non crt', async () => {
|
||||
const commentPost = TestHelper.fakePost(TestHelper.basicChannel!.id);
|
||||
commentPost.root_id = post.id;
|
||||
const commentPost = TestHelper.fakePost({channel_id: TestHelper.basicChannel!.id, root_id: post.id});
|
||||
await operator.handlePosts({
|
||||
actionType: ActionType.POSTS.RECEIVED_NEW,
|
||||
order: [commentPost.id],
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const channel: Channel = {
|
|||
|
||||
const user1 = {id: 'userid1', username: 'user1', email: 'user1@mattermost.com', roles: ''} as UserProfile;
|
||||
|
||||
const post1 = {...TestHelper.fakePost(channelId), id: 'postid1'};
|
||||
const post1 = TestHelper.fakePost({channel_id: channelId, id: 'postid1'});
|
||||
|
||||
const notificationExtraData = {
|
||||
channel,
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@ const teamId = 'teamid1';
|
|||
const user1 = {id: 'userid1', username: 'user1', email: 'user1@mattermost.com', roles: ''} as UserProfile;
|
||||
const user2 = {id: 'userid2', username: 'user2', email: 'user2@mattermost.com', roles: ''} as UserProfile;
|
||||
|
||||
const post1 = {...TestHelper.fakePost(channelId), id: 'postid1', user_id: user1.id};
|
||||
const post2 = {...TestHelper.fakePost(channelId), id: 'postid2', user_id: user2.id};
|
||||
const reply1 = {...TestHelper.fakePost(channelId), id: 'replyid1', root_id: post1.id, user_id: user2.id};
|
||||
const post1 = TestHelper.fakePost({channel_id: channelId, id: 'postid1', user_id: user1.id});
|
||||
const post2 = TestHelper.fakePost({channel_id: channelId, id: 'postid2', user_id: user2.id});
|
||||
const reply1 = TestHelper.fakePost({channel_id: channelId, id: 'replyid1', root_id: post1.id, user_id: user2.id});
|
||||
|
||||
const channel1 = {
|
||||
id: channelId,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const channel: Channel = {
|
|||
const user1 = {id: 'userid1', username: 'user1', email: 'user1@mattermost.com', roles: ''} as UserProfile;
|
||||
|
||||
const preference1 = {category: 'category1', name: 'name1', user_id: user1.id, value: 'value1'} as PreferenceType;
|
||||
const post1 = {...TestHelper.fakePost(channelId), id: 'postid1'};
|
||||
const post1 = TestHelper.fakePost({channel_id: channelId, id: 'postid1'});
|
||||
|
||||
const throwFunc = () => {
|
||||
throw Error('error');
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ const team: Team = {
|
|||
|
||||
const user1 = {id: 'userid1', username: 'user1', email: 'user1@mattermost.com', roles: ''} as UserProfile;
|
||||
|
||||
const post1 = {...TestHelper.fakePost(channelId), id: 'postid1'};
|
||||
const post2 = {...TestHelper.fakePost(channelId), id: 'postid2', root_id: post1.id};
|
||||
const post1 = TestHelper.fakePost({channel_id: channelId, id: 'postid1'});
|
||||
const post2 = TestHelper.fakePost({channel_id: channelId, id: 'postid2', root_id: post1.id});
|
||||
|
||||
const thread1: Thread = {id: 'postid1',
|
||||
reply_count: 1,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const channel: Channel = {
|
|||
} as Channel;
|
||||
|
||||
const user1 = {id: 'userid1', username: 'user1', email: 'user1@mattermost.com', roles: ''} as UserProfile;
|
||||
const post1 = {...TestHelper.fakePost(channelId), id: 'postid1'};
|
||||
const post1 = TestHelper.fakePost({channel_id: channelId, id: 'postid1'});
|
||||
|
||||
const fileInfo1: FileInfo = {
|
||||
id: 'fileid1',
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ const team: Team = {
|
|||
|
||||
const user1 = {id: 'userid1', username: 'user1', email: 'user1@mattermost.com', roles: ''} as UserProfile;
|
||||
|
||||
const post1 = {...TestHelper.fakePost(channelId), id: 'postid1'};
|
||||
const post1 = TestHelper.fakePost({channel_id: channelId, id: 'postid1'});
|
||||
|
||||
const thread1: Thread = {id: 'postid1',
|
||||
reply_count: 1,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {DeviceEventEmitter, Text, TouchableOpacity, View} from 'react-native';
|
|||
import {Events} from '@constants';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import {useImageAttachments} from '@hooks/files';
|
||||
import {mockFileInfo} from '@test/api_mocks/file';
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {isImage, isVideo} from '@utils/file';
|
||||
import {fileToGalleryItem, openGalleryAtIndex} from '@utils/gallery';
|
||||
import {getViewPortWidth} from '@utils/images';
|
||||
|
|
@ -89,10 +89,10 @@ function getBaseProps(): ComponentProps<typeof Files> {
|
|||
describe('Files', () => {
|
||||
it('should render attachments, with images in the image row', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
mockFileInfo({id: '3'}),
|
||||
mockFileInfo({id: '4'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '3'}),
|
||||
TestHelper.fakeFileInfo({id: '4'}),
|
||||
];
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
return useMemo(() => ({
|
||||
|
|
@ -119,8 +119,8 @@ describe('Files', () => {
|
|||
|
||||
it('should not show the image row if no images', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '3'}),
|
||||
mockFileInfo({id: '4'}),
|
||||
TestHelper.fakeFileInfo({id: '3'}),
|
||||
TestHelper.fakeFileInfo({id: '4'}),
|
||||
];
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
return useMemo(() => ({
|
||||
|
|
@ -158,8 +158,8 @@ describe('Files', () => {
|
|||
|
||||
it('should drill all relevant props', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -210,8 +210,8 @@ describe('Files', () => {
|
|||
|
||||
it('should set layoutWidth if provided', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -239,8 +239,8 @@ describe('Files', () => {
|
|||
|
||||
it('should use ((getViewportWidth result) - 6) if layoutWidth is not provided', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -276,8 +276,8 @@ describe('Files', () => {
|
|||
|
||||
it('calling onPress on the child should open gallery', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -322,8 +322,8 @@ describe('Files', () => {
|
|||
|
||||
it('calling updateFileForGallery updates the file', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', uri: 'original'}),
|
||||
mockFileInfo({id: '2', uri: 'original'}),
|
||||
TestHelper.fakeFileInfo({id: '1', uri: 'original'}),
|
||||
TestHelper.fakeFileInfo({id: '2', uri: 'original'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -375,7 +375,7 @@ describe('Files', () => {
|
|||
/>,
|
||||
);
|
||||
const newFilesInfo = [
|
||||
mockFileInfo({id: '1', name: 'image1.png', user_id: 'user1'}),
|
||||
TestHelper.fakeFileInfo({id: '1', name: 'image1.png', user_id: 'user1'}),
|
||||
];
|
||||
rerender(
|
||||
<Files
|
||||
|
|
@ -388,8 +388,8 @@ describe('Files', () => {
|
|||
|
||||
it('should set inViewPort to true on ITEM_IN_VIEWPORT event', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', name: 'image1.png', user_id: 'user1'}),
|
||||
mockFileInfo({id: '2', name: 'image2.png', user_id: 'user2'}),
|
||||
TestHelper.fakeFileInfo({id: '1', name: 'image1.png', user_id: 'user1'}),
|
||||
TestHelper.fakeFileInfo({id: '2', name: 'image2.png', user_id: 'user2'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -418,8 +418,8 @@ describe('Files', () => {
|
|||
|
||||
it('should ignore ITEM_IN_VIEWPORT event if not for the current post or location', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', name: 'image1.png', user_id: 'user1'}),
|
||||
mockFileInfo({id: '2', name: 'image2.png', user_id: 'user2'}),
|
||||
TestHelper.fakeFileInfo({id: '1', name: 'image1.png', user_id: 'user1'}),
|
||||
TestHelper.fakeFileInfo({id: '2', name: 'image2.png', user_id: 'user2'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -464,9 +464,9 @@ describe('Files', () => {
|
|||
|
||||
it('should pass isSingleImage to the children', () => {
|
||||
let filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '3'}),
|
||||
mockFileInfo({id: '4'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '3'}),
|
||||
TestHelper.fakeFileInfo({id: '4'}),
|
||||
];
|
||||
|
||||
const selectImages = (f: FileInfo | FileModel | undefined) => f?.id === '1' || f?.id === '2';
|
||||
|
|
@ -506,10 +506,10 @@ describe('Files', () => {
|
|||
expect(getByTestId('4-isSingleImage')).toHaveTextContent('true');
|
||||
|
||||
filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
mockFileInfo({id: '3'}),
|
||||
mockFileInfo({id: '4'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '3'}),
|
||||
TestHelper.fakeFileInfo({id: '4'}),
|
||||
];
|
||||
|
||||
jest.mocked(isImage).mockImplementation((f) => selectImages(f));
|
||||
|
|
@ -544,16 +544,16 @@ describe('Files', () => {
|
|||
|
||||
it('should trim more than 4 images and properly add the non visible images count to the last image', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
mockFileInfo({id: '3'}),
|
||||
mockFileInfo({id: '4'}),
|
||||
mockFileInfo({id: '5'}),
|
||||
mockFileInfo({id: '6'}),
|
||||
mockFileInfo({id: '7'}),
|
||||
mockFileInfo({id: '8'}),
|
||||
mockFileInfo({id: '9'}),
|
||||
mockFileInfo({id: '10'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '3'}),
|
||||
TestHelper.fakeFileInfo({id: '4'}),
|
||||
TestHelper.fakeFileInfo({id: '5'}),
|
||||
TestHelper.fakeFileInfo({id: '6'}),
|
||||
TestHelper.fakeFileInfo({id: '7'}),
|
||||
TestHelper.fakeFileInfo({id: '8'}),
|
||||
TestHelper.fakeFileInfo({id: '9'}),
|
||||
TestHelper.fakeFileInfo({id: '10'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
@ -584,12 +584,12 @@ describe('Files', () => {
|
|||
|
||||
it('should add gutter to the container of to all elements but the first only on image row', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1'}),
|
||||
mockFileInfo({id: '2'}),
|
||||
mockFileInfo({id: '3'}),
|
||||
mockFileInfo({id: '4'}),
|
||||
mockFileInfo({id: '5'}),
|
||||
mockFileInfo({id: '6'}),
|
||||
TestHelper.fakeFileInfo({id: '1'}),
|
||||
TestHelper.fakeFileInfo({id: '2'}),
|
||||
TestHelper.fakeFileInfo({id: '3'}),
|
||||
TestHelper.fakeFileInfo({id: '4'}),
|
||||
TestHelper.fakeFileInfo({id: '5'}),
|
||||
TestHelper.fakeFileInfo({id: '6'}),
|
||||
];
|
||||
|
||||
jest.mocked(useImageAttachments).mockImplementation((fi) => {
|
||||
|
|
|
|||
189
app/components/team_sidebar/team_list/team_item/index.test.tsx
Normal file
189
app/components/team_sidebar/team_list/team_item/index.test.tsx
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Database} from '@nozbe/watermelondb';
|
||||
import React from 'react';
|
||||
|
||||
import {processReceivedThreads} from '@actions/local/thread';
|
||||
import {Config} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {prepareAllMyChannels} from '@queries/servers/channel';
|
||||
import {renderWithEverything, act} from '@test/intl-test-helper';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import TeamItem from './team_item';
|
||||
|
||||
import EnhancedTeamItem from './index';
|
||||
|
||||
import type ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import type MyTeamModel from '@typings/database/models/servers/my_team';
|
||||
|
||||
jest.mock('./team_item', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(),
|
||||
}));
|
||||
jest.mocked(TeamItem).mockImplementation((props) => React.createElement('TeamItem', {...props, testID: 'team-item'}));
|
||||
|
||||
describe('TeamItem enhanced component', () => {
|
||||
const serverUrl = 'server-1';
|
||||
const teamId = 'team1';
|
||||
let database: Database;
|
||||
let operator: ServerDataOperator;
|
||||
const myTeam = {id: teamId} as MyTeamModel;
|
||||
|
||||
beforeEach(async () => {
|
||||
await DatabaseManager.init([serverUrl]);
|
||||
const serverDatabaseAndOperator = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = serverDatabaseAndOperator.database;
|
||||
operator = serverDatabaseAndOperator.operator;
|
||||
|
||||
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: teamId}], prepareRecordsOnly: false});
|
||||
await operator.handleTeam({teams: [TestHelper.fakeTeam({id: teamId})], prepareRecordsOnly: false});
|
||||
await operator.handleConfigs({
|
||||
configs: [
|
||||
{id: 'CollapsedThreads', value: Config.ALWAYS_ON},
|
||||
{id: 'Version', value: '7.6.0'},
|
||||
],
|
||||
configsToDelete: [],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await DatabaseManager.destroyServerDatabase(serverUrl);
|
||||
});
|
||||
|
||||
it('should correctly show hasUnreads if we have unread channels', async () => {
|
||||
let models = await Promise.all(await prepareAllMyChannels(operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 10})],
|
||||
[TestHelper.fakeMyChannel({id: 'my_channel1', channel_id: 'channel1', msg_count: 10})],
|
||||
false,
|
||||
));
|
||||
await operator.batchRecords(models.flat(), 'test');
|
||||
|
||||
const {getByTestId} = renderWithEverything(<EnhancedTeamItem myTeam={myTeam}/>, {database});
|
||||
const teamItem = getByTestId('team-item');
|
||||
expect(teamItem.props.hasUnreads).toBe(false);
|
||||
|
||||
await act(async () => {
|
||||
models = await Promise.all(await prepareAllMyChannels(operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({id: 'my_channel1', channel_id: 'channel1', msg_count: 10})],
|
||||
false,
|
||||
));
|
||||
await operator.batchRecords(models.flat(), 'test');
|
||||
});
|
||||
|
||||
expect(teamItem.props.hasUnreads).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
models = await Promise.all(await prepareAllMyChannels(operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({id: 'my_channel1', channel_id: 'channel1', msg_count: 20})],
|
||||
false,
|
||||
));
|
||||
await operator.batchRecords(models.flat(), 'test');
|
||||
});
|
||||
|
||||
expect(teamItem.props.hasUnreads).toBe(false);
|
||||
});
|
||||
|
||||
it('should correctly show hasUnreads if we have unread threads', async () => {
|
||||
const channelId = 'channel1';
|
||||
const threadId = 'thread1';
|
||||
const channelModels = await Promise.all(await prepareAllMyChannels(operator,
|
||||
[TestHelper.fakeChannel({id: channelId, team_id: teamId, total_msg_count: 10})],
|
||||
[TestHelper.fakeMyChannel({id: 'my_channel1', channel_id: channelId, msg_count: 10})],
|
||||
false,
|
||||
));
|
||||
const threadModels = await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 0,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, true);
|
||||
await operator.batchRecords([...channelModels.flat(), ...threadModels.models!], 'test');
|
||||
|
||||
const {getByTestId} = renderWithEverything(<EnhancedTeamItem myTeam={myTeam}/>, {database});
|
||||
const teamItem = getByTestId('team-item');
|
||||
expect(teamItem.props.hasUnreads).toBe(false);
|
||||
|
||||
await act(async () => {
|
||||
await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 1,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, false);
|
||||
});
|
||||
|
||||
expect(teamItem.props.hasUnreads).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 0,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, false);
|
||||
});
|
||||
|
||||
expect(teamItem.props.hasUnreads).toBe(false);
|
||||
});
|
||||
|
||||
it('should not consider unread threads if collapsed threads is off', async () => {
|
||||
const channelId = 'channel1';
|
||||
const threadId = 'thread1';
|
||||
|
||||
await operator.handleConfigs({
|
||||
configs: [{id: 'CollapsedThreads', value: Config.DISABLED}],
|
||||
configsToDelete: [],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
|
||||
const channelModels = await Promise.all(await prepareAllMyChannels(operator,
|
||||
[TestHelper.fakeChannel({id: channelId, team_id: teamId, total_msg_count: 10})],
|
||||
[TestHelper.fakeMyChannel({id: 'my_channel1', channel_id: channelId, msg_count: 10})],
|
||||
false,
|
||||
));
|
||||
const threadModels = await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 0,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, true);
|
||||
await operator.batchRecords([...channelModels.flat(), ...threadModels.models!], 'test');
|
||||
|
||||
const {getByTestId} = renderWithEverything(<EnhancedTeamItem myTeam={myTeam}/>, {database});
|
||||
const teamItem = getByTestId('team-item');
|
||||
expect(teamItem.props.hasUnreads).toBe(false);
|
||||
|
||||
await act(async () => {
|
||||
await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 1,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, false);
|
||||
});
|
||||
|
||||
expect(teamItem.props.hasUnreads).toBe(false);
|
||||
|
||||
await act(async () => {
|
||||
const models = await Promise.all(await prepareAllMyChannels(operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({id: 'my_channel1', channel_id: 'channel1', msg_count: 10})],
|
||||
false,
|
||||
));
|
||||
await operator.batchRecords(models.flat(), 'test');
|
||||
});
|
||||
|
||||
expect(teamItem.props.hasUnreads).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -3,11 +3,10 @@
|
|||
|
||||
import {withDatabase, withObservables} from '@nozbe/watermelondb/react';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {combineLatestWith, map, switchMap, distinctUntilChanged} from 'rxjs/operators';
|
||||
import {switchMap, distinctUntilChanged} from 'rxjs/operators';
|
||||
|
||||
import {observeAllMyChannelNotifyProps, queryMyChannelsByTeam} from '@queries/servers/channel';
|
||||
import {observeCurrentTeamId} from '@queries/servers/system';
|
||||
import {observeMentionCount, observeTeam} from '@queries/servers/team';
|
||||
import {observeIsTeamUnread, observeMentionCount, observeTeam} from '@queries/servers/team';
|
||||
|
||||
import TeamItem from './team_item';
|
||||
|
||||
|
|
@ -19,17 +18,6 @@ type WithTeamsArgs = WithDatabaseArgs & {
|
|||
}
|
||||
|
||||
const enhance = withObservables(['myTeam'], ({myTeam, database}: WithTeamsArgs) => {
|
||||
const myChannels = queryMyChannelsByTeam(database, myTeam.id).observeWithColumns(['mentions_count', 'is_unread']);
|
||||
const notifyProps = observeAllMyChannelNotifyProps(database);
|
||||
const hasUnreads = myChannels.pipe(
|
||||
combineLatestWith(notifyProps),
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
map(([mycs, notify]) => mycs.reduce((acc, v) => {
|
||||
const isMuted = notify?.[v.id]?.mark_unread === 'mention';
|
||||
return acc || (v.isUnread && !isMuted);
|
||||
}, false)),
|
||||
);
|
||||
|
||||
const selected = observeCurrentTeamId(database).pipe(
|
||||
switchMap((ctid) => of$(ctid === myTeam.id)),
|
||||
distinctUntilChanged(),
|
||||
|
|
@ -39,7 +27,7 @@ const enhance = withObservables(['myTeam'], ({myTeam, database}: WithTeamsArgs)
|
|||
selected,
|
||||
team: observeTeam(database, myTeam.id),
|
||||
mentionCount: observeMentionCount(database, myTeam.id, false),
|
||||
hasUnreads,
|
||||
hasUnreads: observeIsTeamUnread(database, myTeam.id),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {renderHook} from '@testing-library/react-hooks';
|
|||
import {getLocalFileInfo} from '@actions/local/file';
|
||||
import {buildFilePreviewUrl, buildFileUrl} from '@actions/remote/file';
|
||||
import {useServerUrl} from '@context/server';
|
||||
import {mockFileInfo} from '@test/api_mocks/file';
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {isGif, isImage, isVideo} from '@utils/file';
|
||||
import {getImageSize} from '@utils/gallery';
|
||||
|
||||
|
|
@ -42,9 +42,9 @@ describe('useImageAttachments', () => {
|
|||
|
||||
it('should separate images and non-images correctly', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', localPath: 'path/to/image1', uri: `${serverUrl}/files/image1`}),
|
||||
mockFileInfo({id: '2', localPath: 'path/to/video1', uri: `${serverUrl}/files/video1`}),
|
||||
mockFileInfo({id: '3', localPath: 'path/to/file1', uri: `${serverUrl}/files/file1`}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: 'path/to/image1', uri: `${serverUrl}/files/image1`}),
|
||||
TestHelper.fakeFileInfo({id: '2', localPath: 'path/to/video1', uri: `${serverUrl}/files/video1`}),
|
||||
TestHelper.fakeFileInfo({id: '3', localPath: 'path/to/file1', uri: `${serverUrl}/files/file1`}),
|
||||
];
|
||||
|
||||
jest.mocked(isImage).mockImplementation((file) => file?.id === '1');
|
||||
|
|
@ -56,18 +56,18 @@ describe('useImageAttachments', () => {
|
|||
const {result} = renderHook(() => useImageAttachments(filesInfo));
|
||||
|
||||
expect(result.current.images).toEqual([
|
||||
mockFileInfo({id: '1', localPath: 'path/to/image1', uri: 'path/to/image1'}),
|
||||
mockFileInfo({id: '2', localPath: 'path/to/video1', uri: 'path/to/video1'}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: 'path/to/image1', uri: 'path/to/image1'}),
|
||||
TestHelper.fakeFileInfo({id: '2', localPath: 'path/to/video1', uri: 'path/to/video1'}),
|
||||
]);
|
||||
|
||||
expect(result.current.nonImages).toEqual([
|
||||
mockFileInfo({id: '3', localPath: 'path/to/file1', uri: `${serverUrl}/files/file1`}),
|
||||
TestHelper.fakeFileInfo({id: '3', localPath: 'path/to/file1', uri: `${serverUrl}/files/file1`}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use preview URL for images without localPath', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', localPath: '', uri: `${serverUrl}/files/image1`}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: '', uri: `${serverUrl}/files/image1`}),
|
||||
];
|
||||
|
||||
jest.mocked(isImage).mockReturnValue(true);
|
||||
|
|
@ -78,14 +78,14 @@ describe('useImageAttachments', () => {
|
|||
const {result} = renderHook(() => useImageAttachments(filesInfo));
|
||||
|
||||
expect(result.current.images).toEqual([
|
||||
mockFileInfo({id: '1', localPath: '', uri: 'https://example.com/preview/1'}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: '', uri: 'https://example.com/preview/1'}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should use file URL for gifs and videos without local path', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', localPath: '', uri: `${serverUrl}/files/image1`}),
|
||||
mockFileInfo({id: '2', localPath: '', uri: `${serverUrl}/files/video1`}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: '', uri: `${serverUrl}/files/image1`}),
|
||||
TestHelper.fakeFileInfo({id: '2', localPath: '', uri: `${serverUrl}/files/video1`}),
|
||||
];
|
||||
|
||||
jest.mocked(isImage).mockImplementation((file) => file?.id === '1' || file?.id === '3');
|
||||
|
|
@ -96,15 +96,15 @@ describe('useImageAttachments', () => {
|
|||
const {result} = renderHook(() => useImageAttachments(filesInfo));
|
||||
|
||||
expect(result.current.images).toEqual([
|
||||
mockFileInfo({id: '1', localPath: '', uri: 'https://example.com/file/1'}),
|
||||
mockFileInfo({id: '2', localPath: '', uri: 'https://example.com/file/2'}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: '', uri: 'https://example.com/file/1'}),
|
||||
TestHelper.fakeFileInfo({id: '2', localPath: '', uri: 'https://example.com/file/2'}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return the same values if the same arguments are passed', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '1', localPath: 'path/to/image1', uri: `${serverUrl}/files/image1`}),
|
||||
mockFileInfo({id: '2', localPath: 'path/to/video1', uri: `${serverUrl}/files/video1`}),
|
||||
TestHelper.fakeFileInfo({id: '1', localPath: 'path/to/image1', uri: `${serverUrl}/files/image1`}),
|
||||
TestHelper.fakeFileInfo({id: '2', localPath: 'path/to/video1', uri: `${serverUrl}/files/video1`}),
|
||||
];
|
||||
|
||||
jest.mocked(isImage).mockImplementation((file) => file?.id === '1');
|
||||
|
|
@ -135,8 +135,8 @@ describe('useImageAttachments', () => {
|
|||
|
||||
it('should handle files with no id', () => {
|
||||
const filesInfo = [
|
||||
mockFileInfo({id: '', localPath: 'path/to/image1', uri: `${serverUrl}/files/image1`}),
|
||||
mockFileInfo({id: '', localPath: '', uri: `${serverUrl}/files/image2`}),
|
||||
TestHelper.fakeFileInfo({id: '', localPath: 'path/to/image1', uri: `${serverUrl}/files/image1`}),
|
||||
TestHelper.fakeFileInfo({id: '', localPath: '', uri: `${serverUrl}/files/image2`}),
|
||||
];
|
||||
|
||||
jest.mocked(isImage).mockReturnValue(true);
|
||||
|
|
@ -147,7 +147,7 @@ describe('useImageAttachments', () => {
|
|||
const {result} = renderHook(() => useImageAttachments(filesInfo));
|
||||
|
||||
expect(result.current.images).toEqual([
|
||||
mockFileInfo({id: '', localPath: 'path/to/image1', uri: 'path/to/image1'}),
|
||||
TestHelper.fakeFileInfo({id: '', localPath: 'path/to/image1', uri: 'path/to/image1'}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ import {of as of$} from 'rxjs';
|
|||
|
||||
import {General, Permissions} from '@constants';
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import ServerDataOperator from '@database/operator/server_data_operator';
|
||||
import TestHelper from '@test/test_helper';
|
||||
import {hasPermission} from '@utils/role';
|
||||
|
||||
import {prepareChannels,
|
||||
|
|
@ -62,6 +64,8 @@ import {prepareChannels,
|
|||
queryChannelMembers,
|
||||
queryChannelsForAutocomplete,
|
||||
observeChannelMembers,
|
||||
observeMyChannelUnreads,
|
||||
prepareAllMyChannels,
|
||||
} from './channel';
|
||||
import {queryRoles} from './role';
|
||||
import {getCurrentChannelId, observeCurrentChannelId, observeCurrentUserId} from './system';
|
||||
|
|
@ -788,15 +792,15 @@ describe('Channel Functions', () => {
|
|||
describe('getChannelById', () => {
|
||||
it('should return the channel if found', async () => {
|
||||
const channelId = 'channel_id';
|
||||
const mockChannel = {id: channelId} as ChannelModel;
|
||||
const mockedChannel = {id: channelId} as ChannelModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockChannel),
|
||||
find: jest.fn().mockResolvedValue(mockedChannel),
|
||||
});
|
||||
|
||||
const result = await getChannelById(database, channelId);
|
||||
|
||||
expect(database.get).toHaveBeenCalledWith(MM_TABLES.SERVER.CHANNEL);
|
||||
expect(result).toEqual(mockChannel);
|
||||
expect(result).toEqual(mockedChannel);
|
||||
});
|
||||
|
||||
it('should return undefined if the channel is not found', async () => {
|
||||
|
|
@ -854,17 +858,17 @@ describe('Channel Functions', () => {
|
|||
it('should return the channel if found', async () => {
|
||||
const teamId = 'team_id';
|
||||
const channelName = 'channel_name';
|
||||
const mockChannel = {id: 'channel_id', name: channelName} as ChannelModel;
|
||||
const mockedChannel = {id: 'channel_id', name: channelName} as ChannelModel;
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
query: jest.fn().mockReturnValue({
|
||||
fetch: jest.fn().mockResolvedValue([mockChannel]),
|
||||
fetch: jest.fn().mockResolvedValue([mockedChannel]),
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await getChannelByName(database, teamId, channelName);
|
||||
|
||||
expect(database.get).toHaveBeenCalledWith(MM_TABLES.SERVER.CHANNEL);
|
||||
expect(result).toEqual(mockChannel);
|
||||
expect(result).toEqual(mockedChannel);
|
||||
});
|
||||
|
||||
it('should return undefined if the channel is not found', async () => {
|
||||
|
|
@ -1033,17 +1037,17 @@ describe('Channel Functions', () => {
|
|||
describe('getCurrentChannel', () => {
|
||||
it('should return the current channel if found', async () => {
|
||||
const currentChannelId = 'current_channel_id';
|
||||
const mockChannel = {id: currentChannelId} as ChannelModel;
|
||||
const mockedChannel = {id: currentChannelId} as ChannelModel;
|
||||
(getCurrentChannelId as jest.Mock).mockResolvedValue(currentChannelId);
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
find: jest.fn().mockResolvedValue(mockChannel),
|
||||
find: jest.fn().mockResolvedValue(mockedChannel),
|
||||
});
|
||||
|
||||
const result = await getCurrentChannel(database);
|
||||
|
||||
expect(getCurrentChannelId).toHaveBeenCalledWith(database);
|
||||
expect(database.get).toHaveBeenCalledWith(MM_TABLES.SERVER.CHANNEL);
|
||||
expect(result).toEqual(mockChannel);
|
||||
expect(result).toEqual(mockedChannel);
|
||||
});
|
||||
|
||||
it('should return undefined if no current channel is found', async () => {
|
||||
|
|
@ -1085,9 +1089,9 @@ describe('Channel Functions', () => {
|
|||
describe('observeCurrentChannel', () => {
|
||||
it('should observe the current channel', () => {
|
||||
const currentChannelId = 'current_channel_id';
|
||||
const mockChannel = {id: currentChannelId, observe: jest.fn().mockReturnValue(of$({id: currentChannelId}))} as unknown as ChannelModel;
|
||||
const mockedChannel = {id: currentChannelId, observe: jest.fn().mockReturnValue(of$({id: currentChannelId}))} as unknown as ChannelModel;
|
||||
const mockQuery = jest.fn().mockReturnValue({
|
||||
observe: jest.fn().mockReturnValue(of$([mockChannel])),
|
||||
observe: jest.fn().mockReturnValue(of$([mockedChannel])),
|
||||
});
|
||||
(database.get as jest.Mock).mockReturnValue({
|
||||
query: mockQuery,
|
||||
|
|
@ -1552,3 +1556,216 @@ describe('Channel Observations', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('observeMyChannelUnreads', () => {
|
||||
const teamId = 'team_id';
|
||||
const userId = 'user_id';
|
||||
const serverUrl = 'baseHandler.test.com';
|
||||
const waitTime = 50;
|
||||
let database: Database;
|
||||
let operator: ServerDataOperator;
|
||||
|
||||
jest.restoreAllMocks();
|
||||
|
||||
beforeEach(async () => {
|
||||
await DatabaseManager.init([serverUrl]);
|
||||
const serverDatabaseAndOperator = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = serverDatabaseAndOperator.database;
|
||||
operator = serverDatabaseAndOperator.operator;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await DatabaseManager.deleteServerDatabase(serverUrl);
|
||||
});
|
||||
|
||||
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 result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// Subscription always returns the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
let models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// No change
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(true);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 30})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it('should return false when all unread channels are muted', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const notify_props = {mark_unread: 'mention' as const};
|
||||
const result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// Subscription always returns the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
let models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// No change
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 30})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('missing notify props are considered unmuted', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const notify_props = {};
|
||||
const result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// Subscription always returns the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
let models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// No change
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(true);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 30})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
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 result = observeMyChannelUnreads(database, teamId);
|
||||
result.subscribe({next: subscriptionNext});
|
||||
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// Subscription always returns the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
let models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: otherTeamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
// No change
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: otherTeamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 20})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: otherTeamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({channel_id: 'channel1', user_id: userId, notify_props, msg_count: 30})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import {Database, Model, Q, Query, Relation} from '@nozbe/watermelondb';
|
||||
import {of as of$, Observable} from 'rxjs';
|
||||
import {map as map$, switchMap, distinctUntilChanged} from 'rxjs/operators';
|
||||
import {map as map$, switchMap, distinctUntilChanged, combineLatestWith} from 'rxjs/operators';
|
||||
|
||||
import {General, Permissions} from '@constants';
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
|
|
@ -536,6 +536,19 @@ export function observeMyChannelMentionCount(database: Database, teamId?: string
|
|||
);
|
||||
}
|
||||
|
||||
export function observeMyChannelUnreads(database: Database, teamId: string) {
|
||||
const myChannels = queryMyChannelsByTeam(database, teamId).observeWithColumns(['is_unread']);
|
||||
const notifyProps = observeAllMyChannelNotifyProps(database);
|
||||
return myChannels.pipe(
|
||||
combineLatestWith(notifyProps),
|
||||
switchMap(([mycs, notify]) => of$(mycs.reduce((acc, v) => {
|
||||
const isMuted = notify?.[v.id]?.mark_unread === 'mention';
|
||||
return acc || (v.isUnread && !isMuted);
|
||||
}, false))),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
}
|
||||
|
||||
export function queryMyRecentChannels(database: Database, take: number) {
|
||||
const count: Q.Clause[] = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@
|
|||
|
||||
/* eslint-disable max-lines */
|
||||
|
||||
import {Preferences, Screens} from '@constants';
|
||||
import {processReceivedThreads} from '@actions/local/thread';
|
||||
import {Config, Preferences, Screens} from '@constants';
|
||||
import {SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import TestHelper from '@test/test_helper';
|
||||
|
||||
import {prepareAllMyChannels} from './channel';
|
||||
import {getTeamHistory} from './system';
|
||||
import {
|
||||
getCurrentTeam,
|
||||
|
|
@ -37,6 +40,7 @@ import {
|
|||
prepareMyTeams,
|
||||
queryTeamByName,
|
||||
getDefaultTeamId,
|
||||
observeIsTeamUnread,
|
||||
observeSortedJoinedTeams,
|
||||
} from './team';
|
||||
|
||||
|
|
@ -1023,6 +1027,189 @@ describe('Team Queries', () => {
|
|||
}, 1500);
|
||||
});
|
||||
|
||||
describe('observeIsTeamUnread', () => {
|
||||
const userId = 'user_id';
|
||||
const waitTime = 50;
|
||||
|
||||
beforeEach(async () => {
|
||||
await DatabaseManager.init([serverUrl]);
|
||||
const serverDatabaseAndOperator = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
database = serverDatabaseAndOperator.database;
|
||||
operator = serverDatabaseAndOperator.operator;
|
||||
await operator.handleSystem({
|
||||
systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: userId}],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
await operator.handleConfigs({
|
||||
configs: [
|
||||
{id: 'CollapsedThreads', value: Config.ALWAYS_ON},
|
||||
{id: 'Version', value: '7.6.0'},
|
||||
],
|
||||
configsToDelete: [],
|
||||
prepareRecordsOnly: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await DatabaseManager.destroyServerDatabase(serverUrl);
|
||||
});
|
||||
|
||||
it('should return true when there are channel unreads', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const notify_props = {mark_unread: 'all' as const};
|
||||
const result = observeIsTeamUnread(database, teamId);
|
||||
|
||||
result.subscribe({next: subscriptionNext});
|
||||
await TestHelper.wait(waitTime);
|
||||
|
||||
// The subscription always return the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
// Setup initial state - channel with no unreads
|
||||
let models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({
|
||||
channel_id: 'channel1',
|
||||
user_id: userId,
|
||||
notify_props,
|
||||
msg_count: 20,
|
||||
})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
await TestHelper.wait(waitTime);
|
||||
|
||||
// No change
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
// Update channel with new messages
|
||||
models = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: 'channel1', team_id: teamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({
|
||||
channel_id: 'channel1',
|
||||
user_id: userId,
|
||||
notify_props,
|
||||
msg_count: 20,
|
||||
})],
|
||||
false,
|
||||
)))).flat();
|
||||
await operator.batchRecords(models, 'test');
|
||||
await TestHelper.wait(waitTime);
|
||||
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('should return true when there are thread unreads', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const channelId = 'channel1';
|
||||
const threadId = 'thread1';
|
||||
|
||||
const result = observeIsTeamUnread(database, teamId);
|
||||
|
||||
result.subscribe({next: subscriptionNext});
|
||||
await TestHelper.wait(waitTime);
|
||||
|
||||
// The subscription always return the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
const channelModels = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: channelId, team_id: teamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({
|
||||
channel_id: channelId,
|
||||
user_id: userId,
|
||||
msg_count: 20,
|
||||
})],
|
||||
false,
|
||||
)))).flat();
|
||||
const threadModels = await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 0,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, true);
|
||||
await operator.batchRecords([...channelModels, ...threadModels.models!], 'test');
|
||||
|
||||
// No change
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 1,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, false);
|
||||
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('changes in other teams should not trigger the subscription', async () => {
|
||||
const subscriptionNext = jest.fn();
|
||||
const channelId = 'channel1';
|
||||
const threadId = 'thread1';
|
||||
const otherTeamId = 'other_team';
|
||||
|
||||
const result = observeIsTeamUnread(database, teamId);
|
||||
|
||||
result.subscribe({next: subscriptionNext});
|
||||
await TestHelper.wait(waitTime);
|
||||
|
||||
// The subscription always return the first value
|
||||
expect(subscriptionNext).toHaveBeenCalledWith(false);
|
||||
subscriptionNext.mockClear();
|
||||
|
||||
let channelModels = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: channelId, team_id: otherTeamId, total_msg_count: 20})],
|
||||
[TestHelper.fakeMyChannel({
|
||||
channel_id: channelId,
|
||||
user_id: userId,
|
||||
msg_count: 20,
|
||||
})],
|
||||
false,
|
||||
)))).flat();
|
||||
let threadModels = await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 0,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, true);
|
||||
await operator.batchRecords([...channelModels, ...threadModels.models!], 'test');
|
||||
|
||||
await TestHelper.wait(waitTime);
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
|
||||
channelModels = (await Promise.all((await prepareAllMyChannels(
|
||||
operator,
|
||||
[TestHelper.fakeChannel({id: channelId, team_id: otherTeamId, total_msg_count: 30})],
|
||||
[TestHelper.fakeMyChannel({
|
||||
channel_id: channelId,
|
||||
user_id: userId,
|
||||
msg_count: 20,
|
||||
})],
|
||||
false,
|
||||
)))).flat();
|
||||
threadModels = await processReceivedThreads(serverUrl, [TestHelper.fakeThread({
|
||||
id: threadId,
|
||||
reply_count: 1,
|
||||
unread_replies: 1,
|
||||
post: TestHelper.fakePost({id: threadId, channel_id: channelId}),
|
||||
is_following: true,
|
||||
})], teamId, true);
|
||||
await operator.batchRecords([...channelModels, ...threadModels.models!], 'test');
|
||||
|
||||
await TestHelper.wait(waitTime);
|
||||
expect(subscriptionNext).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('observeSortedJoinedTeams', () => {
|
||||
it('should return teams sorted by preference order', (done) => {
|
||||
const teamIds = ['team1', 'team2', 'team3'];
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import {selectDefaultTeam} from '@helpers/api/team';
|
|||
import {DEFAULT_LOCALE} from '@i18n';
|
||||
|
||||
import {prepareDeleteCategory} from './categories';
|
||||
import {prepareDeleteChannel, getDefaultChannelForTeam, observeMyChannelMentionCount} from './channel';
|
||||
import {prepareDeleteChannel, getDefaultChannelForTeam, observeMyChannelMentionCount, observeMyChannelUnreads} from './channel';
|
||||
import {queryPreferencesByCategoryAndName} from './preference';
|
||||
import {patchTeamHistory, getConfig, getTeamHistory, observeCurrentTeamId, getCurrentTeamId} from './system';
|
||||
import {observeThreadMentionCount} from './thread';
|
||||
import {observeThreadMentionCount, observeUnreadsAndMentionsInTeam} from './thread';
|
||||
import {getCurrentUser} from './user';
|
||||
|
||||
import type {MyChannelModel} from '@database/models/server';
|
||||
|
|
@ -418,6 +418,19 @@ export function observeMentionCount(database: Database, teamId?: string, include
|
|||
);
|
||||
}
|
||||
|
||||
export function observeIsTeamUnread(database: Database, teamId: string): Observable<boolean> {
|
||||
const channelUnreads = observeMyChannelUnreads(database, teamId);
|
||||
const threadsUnreadsAndMentions = observeUnreadsAndMentionsInTeam(database, teamId);
|
||||
|
||||
return channelUnreads.pipe(
|
||||
combineLatestWith(threadsUnreadsAndMentions),
|
||||
map$(([channels, threads]) => {
|
||||
return channels || threads.unreads;
|
||||
}),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
}
|
||||
|
||||
export function observeSortedJoinedTeams(database: Database) {
|
||||
const myTeams = queryMyTeams(database).observe();
|
||||
const teams = queryJoinedTeams(database).observe();
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export function mockFileInfo(overwrite: Partial<FileInfo> = {}): FileInfo {
|
||||
return {
|
||||
id: '1',
|
||||
localPath: 'path/to/image1',
|
||||
uri: '',
|
||||
has_preview_image: true,
|
||||
extension: 'png',
|
||||
height: 100,
|
||||
width: 100,
|
||||
mime_type: 'image/png',
|
||||
name: 'image1',
|
||||
size: 100,
|
||||
user_id: '1',
|
||||
...overwrite,
|
||||
};
|
||||
}
|
||||
|
|
@ -220,10 +220,10 @@ class TestHelperSingleton {
|
|||
};
|
||||
};
|
||||
|
||||
fakeChannel = (teamId: string): Channel => {
|
||||
fakeChannel = (overwrite: Partial<Channel>): Channel => {
|
||||
return {
|
||||
name: 'channel',
|
||||
team_id: teamId,
|
||||
team_id: this.generateId(),
|
||||
|
||||
// @to-do: Make tests more detriministic;
|
||||
// https://jestjs.io/docs/snapshot-testing#2-tests-should-be-deterministic
|
||||
|
|
@ -243,12 +243,13 @@ class TestHelperSingleton {
|
|||
create_at: 1507840900004,
|
||||
update_at: 1507840900004,
|
||||
id: '',
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeChannelWithId = (teamId: string): Channel => {
|
||||
return {
|
||||
...this.fakeChannel(teamId),
|
||||
...this.fakeChannel({team_id: teamId}),
|
||||
id: this.generateId(),
|
||||
};
|
||||
};
|
||||
|
|
@ -266,11 +267,11 @@ class TestHelperSingleton {
|
|||
};
|
||||
};
|
||||
|
||||
fakeChannelMember = (userId: string, channelId: string): ChannelMembership => {
|
||||
fakeChannelMember = (overwrite: Partial<ChannelMembership>): ChannelMembership => {
|
||||
return {
|
||||
id: channelId,
|
||||
user_id: userId,
|
||||
channel_id: channelId,
|
||||
id: this.generateId(),
|
||||
user_id: this.generateId(),
|
||||
channel_id: this.generateId(),
|
||||
notify_props: {},
|
||||
roles: 'system_user',
|
||||
msg_count: 0,
|
||||
|
|
@ -279,13 +280,15 @@ class TestHelperSingleton {
|
|||
scheme_admin: false,
|
||||
last_viewed_at: 0,
|
||||
last_update_at: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeMyChannel = (userId: string, channelId: string): ChannelMembership => {
|
||||
fakeMyChannel = (overwrite: Partial<ChannelMembership>): ChannelMembership => {
|
||||
return {
|
||||
id: channelId,
|
||||
channel_id: channelId,
|
||||
id: this.generateId(),
|
||||
user_id: this.generateId(),
|
||||
channel_id: this.generateId(),
|
||||
last_post_at: 0,
|
||||
last_viewed_at: 0,
|
||||
manually_unread: false,
|
||||
|
|
@ -293,15 +296,15 @@ class TestHelperSingleton {
|
|||
msg_count: 0,
|
||||
is_unread: false,
|
||||
roles: '',
|
||||
user_id: userId,
|
||||
notify_props: {},
|
||||
last_update_at: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeMyChannelSettings = (userId: string, channelId: string): ChannelMembership => {
|
||||
return {
|
||||
...this.fakeMyChannel(userId, channelId),
|
||||
...this.fakeMyChannel({user_id: userId, channel_id: channelId}),
|
||||
notify_props: {
|
||||
desktop: 'default',
|
||||
email: 'default',
|
||||
|
|
@ -316,12 +319,12 @@ class TestHelperSingleton {
|
|||
return 'success' + this.generateId() + '@simulator.amazonses.com';
|
||||
};
|
||||
|
||||
fakePost = (channelId: string, userId?: string): Post => {
|
||||
fakePost = (overwrite: Partial<Post>): Post => {
|
||||
const time = Date.now();
|
||||
|
||||
return {
|
||||
id: this.generateId(),
|
||||
channel_id: channelId,
|
||||
channel_id: this.generateId(),
|
||||
create_at: time,
|
||||
update_at: time,
|
||||
message: `Unit Test ${this.generateId()}`,
|
||||
|
|
@ -336,21 +339,40 @@ class TestHelperSingleton {
|
|||
props: {},
|
||||
reply_count: 0,
|
||||
root_id: '',
|
||||
user_id: userId || this.generateId(),
|
||||
user_id: this.generateId(),
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakePostWithId = (channelId: string) => {
|
||||
return {
|
||||
...this.fakePost(channelId),
|
||||
id: this.generateId(),
|
||||
create_at: 1507840900004,
|
||||
update_at: 1507840900004,
|
||||
delete_at: 0,
|
||||
...this.fakePost({
|
||||
channel_id: channelId,
|
||||
id: this.generateId(),
|
||||
create_at: 1507840900004,
|
||||
update_at: 1507840900004,
|
||||
delete_at: 0,
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
fakeTeam = (): Team => {
|
||||
fakeThread = (overwrite: Partial<Thread>): Thread => {
|
||||
const id = overwrite.id ?? this.generateId();
|
||||
return {
|
||||
id,
|
||||
delete_at: 0,
|
||||
participants: [],
|
||||
post: this.fakePost({id}),
|
||||
last_reply_at: 0,
|
||||
last_viewed_at: 0,
|
||||
reply_count: 0,
|
||||
unread_mentions: 0,
|
||||
unread_replies: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
fakeTeam = (overwrite?: Partial<Team>): Team => {
|
||||
const name = this.generateId();
|
||||
let inviteId = this.generateId();
|
||||
if (inviteId.length > 32) {
|
||||
|
|
@ -374,6 +396,7 @@ class TestHelperSingleton {
|
|||
create_at: 0,
|
||||
delete_at: 0,
|
||||
update_at: 0,
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -526,6 +549,23 @@ class TestHelperSingleton {
|
|||
};
|
||||
};
|
||||
|
||||
fakeFileInfo = (overwrite: Partial<FileInfo> = {}): FileInfo => {
|
||||
return {
|
||||
id: '1',
|
||||
localPath: 'path/to/image1',
|
||||
uri: '',
|
||||
has_preview_image: true,
|
||||
extension: 'png',
|
||||
height: 100,
|
||||
width: 100,
|
||||
mime_type: 'image/png',
|
||||
name: 'image1',
|
||||
size: 100,
|
||||
user_id: '1',
|
||||
...overwrite,
|
||||
};
|
||||
};
|
||||
|
||||
mockLogin = () => {
|
||||
nock(this.basicClient?.getBaseRoute() || '').
|
||||
post('/users/login').
|
||||
|
|
@ -556,8 +596,8 @@ class TestHelperSingleton {
|
|||
this.basicCategory = this.fakeCategoryWithId(this.basicTeam.id);
|
||||
this.basicChannel = this.fakeChannelWithId(this.basicTeam.id);
|
||||
this.basicCategoryChannel = this.fakeCategoryChannelWithId(this.basicTeam.id, this.basicCategory.id, this.basicChannel.id);
|
||||
this.basicChannelMember = this.fakeChannelMember(this.basicUser.id, this.basicChannel.id);
|
||||
this.basicMyChannel = this.fakeMyChannel(this.basicUser.id, this.basicChannel.id);
|
||||
this.basicChannelMember = this.fakeChannelMember({user_id: this.basicUser.id, channel_id: this.basicChannel.id});
|
||||
this.basicMyChannel = this.fakeMyChannel({user_id: this.basicUser.id, channel_id: this.basicChannel.id});
|
||||
this.basicMyChannelSettings = this.fakeMyChannelSettings(this.basicUser.id, this.basicChannel.id);
|
||||
this.basicPost = {...this.fakePostWithId(this.basicChannel.id), create_at: 1507841118796} as Post;
|
||||
this.basicRoles = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue