Add unit tests for app/actions/local/channel (#8063)

* Add tests for actions/local/channel/removeCurrentUserFromChannel

* Add tests for actions/local/channel/setChannelDeleteAt

* Add tests for actions/local/channel/selectAllMyChannelIds

* Add tests for actions/local/channel/markChannelAsUnread

* Add tests for actions/local/channel/resetMessageCount

* Add tests for actions/local/channel/storeMyChannelsForTeam

* Fix test names

* Add tests for actions/local/channel/updateMyChannelFromWebsocket

* Add tests for actions/local/channel/updateChannelInfoFromChannel

* Add tests for actions/local/channel/updateLastPostAt

* Add tests for actions/local/channel/updateChannelsDisplayName

* Add tests for actions/local/channel/showUnreadChannelsOnly

* Add tests for actions/local/channel/updateDmGmDisplayName

* Remove unnecessary spying
This commit is contained in:
Joram Wilander 2024-07-08 08:30:12 -04:00 committed by GitHub
parent 2c29172135
commit dd3a38b5fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 701 additions and 2 deletions

View file

@ -1,6 +1,8 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
/* eslint-disable max-lines */
import {DeviceEventEmitter} from 'react-native';
import {Navigation} from '@constants';
@ -11,8 +13,23 @@ import {getCommonSystemValues, getTeamHistory} from '@queries/servers/system';
import {getTeamChannelHistory} from '@queries/servers/team';
import {dismissAllModalsAndPopToRoot, dismissAllModalsAndPopToScreen} from '@screens/navigation';
import {switchToChannel} from './channel';
import {
switchToChannel,
removeCurrentUserFromChannel,
setChannelDeleteAt,
selectAllMyChannelIds,
markChannelAsUnread,
resetMessageCount,
storeMyChannelsForTeam,
updateMyChannelFromWebsocket,
updateChannelInfoFromChannel,
updateLastPostAt,
updateChannelsDisplayName,
showUnreadChannelsOnly,
updateDmGmDisplayName,
} from './channel';
import type {ChannelModel, MyChannelModel, SystemModel} from '@app/database/models/server';
import type ServerDataOperator from '@database/operator/server_data_operator';
import type {Database} from '@nozbe/watermelondb';
@ -436,3 +453,683 @@ describe('switchToChannel', () => {
expect(listenerCallback).toHaveBeenCalledTimes(1);
});
});
describe('removeCurrentUserFromChannel', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const team: Team = {
id: teamId,
} as Team;
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
channel_id: channelId,
msg_count: 0,
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {error} = await removeCurrentUserFromChannel('foo', 'channelId');
expect(error).toBeTruthy();
});
it('handle no member', async () => {
const {models, error} = await removeCurrentUserFromChannel(serverUrl, 'channelId');
expect(error).toBeUndefined();
expect(models?.length).toBe(0);
});
it('handle no channel', async () => {
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: teamId}, {id: SYSTEM_IDENTIFIERS.CURRENT_CHANNEL_ID, value: channelId}], prepareRecordsOnly: false});
const {models, error} = await removeCurrentUserFromChannel(serverUrl, channelId);
expect(error).toBeTruthy();
expect(models).toBeUndefined();
});
it('remove user from current channel', async () => {
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: teamId}, {id: SYSTEM_IDENTIFIERS.CURRENT_CHANNEL_ID, value: channelId}], prepareRecordsOnly: false});
const {models, error} = await removeCurrentUserFromChannel(serverUrl, channelId);
const {member} = await queryDatabaseValues(operator.database, teamId, channelId);
expect(error).toBeUndefined();
expect(member).toBeUndefined();
expect(models?.length).toBe(2); // Deleted my channel and channel
});
});
describe('setChannelDeleteAt', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {error} = await setChannelDeleteAt('foo', channelId, 0);
expect(error).toBeTruthy();
});
it('handle no channel', async () => {
const {models, error} = await setChannelDeleteAt(serverUrl, channelId, 0);
expect(error).toBeDefined();
expect(error).toBe(`channel with id ${channelId} not found`);
expect(models).toBeUndefined();
});
it('set channel delete at', async () => {
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
const {models, error} = await setChannelDeleteAt(serverUrl, channelId, 123);
expect(error).toBeUndefined();
expect(models?.length).toBe(1); // Deleted channel
expect(models![0].deleteAt).toBe(123);
});
});
describe('selectAllMyChannelIds', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
channel_id: channelId,
msg_count: 0,
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const result = await selectAllMyChannelIds('foo');
expect(result.length).toBe(0);
});
it('handle no my channels', async () => {
const result = await selectAllMyChannelIds(serverUrl);
expect(result.length).toBe(0);
});
it('select my channels', async () => {
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
const result = await selectAllMyChannelIds(serverUrl);
expect(result.length).toBe(1); // My channel
expect(result[0]).toBe(channelId);
});
});
describe('markChannelAsUnread', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
channel_id: channelId,
msg_count: 0,
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {member, error} = await markChannelAsUnread('foo', channelId, 10, 1, 123, false);
expect(error).toBeTruthy();
expect(member).toBeUndefined();
});
it('handle no member', async () => {
const {member, error} = await markChannelAsUnread(serverUrl, channelId, 10, 1, 123, false);
expect(error).toBe('not a member');
expect(member).toBeUndefined();
});
it('mark channel as unread', async () => {
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
const {member, error} = await markChannelAsUnread(serverUrl, channelId, 10, 1, 123, false);
expect(error).toBeUndefined();
expect(member).toBeDefined();
expect(member?.viewedAt).toBe(122);
expect(member?.lastViewedAt).toBe(122);
expect(member?.messageCount).toBe(10);
expect(member?.mentionsCount).toBe(1);
});
});
describe('resetMessageCount', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 10,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
channel_id: channelId,
msg_count: 10,
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const result = await resetMessageCount('foo', channelId);
expect((result as { error: unknown }).error).toBeDefined();
});
it('handle no member', async () => {
const result = await resetMessageCount(serverUrl, channelId);
expect((result as { error: unknown }).error).toBe('not a member');
});
it('reset message count', async () => {
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
const member = await resetMessageCount(serverUrl, channelId);
expect((member as { error: unknown }).error).toBeUndefined();
expect(member).toBeDefined();
expect((member as MyChannelModel).messageCount).toBe(0);
});
});
describe('storeMyChannelsForTeam', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const team: Team = {
id: teamId,
} as Team;
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: channelId,
msg_count: 0,
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {models, error} = await storeMyChannelsForTeam('foo', teamId, [channel], [channelMember], false, false);
expect(models).toBeUndefined();
expect(error).toBeTruthy();
});
it('handle no member', async () => {
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: 'userid'}], prepareRecordsOnly: false});
const {models, error} = await storeMyChannelsForTeam(serverUrl, teamId, [], [], false, false);
expect(error).toBeUndefined();
expect(models).toBeDefined();
expect(models!.length).toBe(0);
});
it('store my channels for team', async () => {
await operator.handleTeam({teams: [team], prepareRecordsOnly: false});
const {models: prepModels, error: prepError} = await storeMyChannelsForTeam(serverUrl, teamId, [channel], [channelMember], true, false);
expect(prepError).toBeUndefined();
expect(prepModels).toBeDefined();
expect(prepModels!.length).toBe(5); // Channel, channel info, member, settings and my channel
const {models, error} = await storeMyChannelsForTeam(serverUrl, teamId, [channel], [channelMember], false, false);
expect(error).toBeUndefined();
expect(models).toBeDefined();
expect(models!.length).toBe(5);
});
});
describe('updateMyChannelFromWebsocket', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: channelId,
msg_count: 0,
roles: '',
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {model, error} = await updateMyChannelFromWebsocket('foo', channelMember, false);
expect(model).toBeUndefined();
expect(error).toBeTruthy();
});
it('update my channel from websocket', async () => {
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
const {model, error} = await updateMyChannelFromWebsocket(serverUrl, {...channelMember, roles: 'channel_user'}, false);
expect(error).toBeUndefined();
expect(model).toBeDefined();
expect(model?.roles).toBe('channel_user');
});
});
describe('updateChannelInfoFromChannel', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {model, error} = await updateChannelInfoFromChannel('foo', channel, false);
expect(model).toBeUndefined();
expect(error).toBeTruthy();
});
it('update channel info from channel', async () => {
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
const {model, error} = await updateChannelInfoFromChannel(serverUrl, {...channel, header: 'newheader'}, false);
expect(error).toBeUndefined();
expect(model).toBeDefined();
expect(model?.length).toBe(1);
expect(model![0].header).toBe('newheader');
});
});
describe('updateLastPostAt', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: channelId,
msg_count: 0,
roles: '',
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {member, error} = await updateLastPostAt('foo', channelId, 123, false);
expect(member).toBeUndefined();
expect(error).toBeTruthy();
});
it('handle no member', async () => {
const {member, error} = await updateLastPostAt(serverUrl, channelId, 123, false);
expect(error).toBeDefined();
expect(error).toBe('not a member');
expect(member).toBeUndefined();
});
it('update last post at', async () => {
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
const {member, error} = await updateLastPostAt(serverUrl, channelId, 123, false);
expect(error).toBeUndefined();
expect(member).toBeDefined();
expect(member?.lastPostAt).toBe(123);
});
});
describe('updateChannelsDisplayName', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const dmChannel: Channel = {
id: channelId,
name: 'userid__userid2',
display_name: '',
team_id: '',
total_msg_count: 0,
delete_at: 0,
type: 'D',
} as Channel;
const dmChannelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: dmChannel.id,
msg_count: 0,
roles: '',
} as ChannelMembership;
const gmChannel: Channel = {
id: 'id2',
name: 'name',
display_name: '',
team_id: '',
total_msg_count: 0,
delete_at: 0,
type: 'G',
} as Channel;
const gmChannelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: gmChannel.id,
msg_count: 0,
roles: '',
} as ChannelMembership;
const user: UserProfile = {
id: 'userid',
username: 'username',
roles: '',
} as UserProfile;
const user2: UserProfile = {
id: 'userid2',
username: 'username2',
first_name: 'first',
last_name: 'last',
roles: '',
} as UserProfile;
const user3: UserProfile = {
id: 'userid3',
username: 'username3',
first_name: 'first',
last_name: 'last',
roles: '',
} as UserProfile;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {models, error} = await updateChannelsDisplayName('foo', [], [], false);
expect(models).toBeUndefined();
expect(error).toBeTruthy();
});
it('handle no currnet user', async () => {
const {models, error} = await updateChannelsDisplayName(serverUrl, [], [], false);
expect(models).toBeUndefined();
expect(error).toBeUndefined();
});
it('update channels display name', async () => {
const channelModels = await operator.handleChannel({channels: [dmChannel, gmChannel], prepareRecordsOnly: false});
await operator.handleUsers({users: [user, user2, user3], prepareRecordsOnly: false});
await operator.handleChannelMembership({channelMemberships: [{...gmChannelMember, user_id: user2.id}, {...gmChannelMember, user_id: user3.id}], prepareRecordsOnly: false});
await operator.handleMyChannel({channels: [dmChannel, gmChannel], myChannels: [dmChannelMember, gmChannelMember], prepareRecordsOnly: false});
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
const {models, error} = await updateChannelsDisplayName(serverUrl, channelModels, [user, user2], false);
expect(error).toBeUndefined();
expect(models).toBeDefined();
expect(models?.length).toBe(2);
expect((models![0] as ChannelModel).displayName).toBe(user2.username);
expect((models![1] as ChannelModel).displayName).toBe(`${user2.username}, ${user3.username}`);
});
});
describe('showUnreadChannelsOnly', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const teamId = 'tId1';
const channel: Channel = {
id: channelId,
team_id: teamId,
total_msg_count: 0,
delete_at: 0,
} as Channel;
const channelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: channelId,
msg_count: 0,
roles: '',
} as ChannelMembership;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const result = await showUnreadChannelsOnly('foo', true);
expect((result as { error: unknown}).error).toBeTruthy();
});
it('show unread channels only', async () => {
await operator.handleChannel({channels: [channel], prepareRecordsOnly: false});
await operator.handleMyChannel({channels: [channel], myChannels: [channelMember], prepareRecordsOnly: false});
const result = await showUnreadChannelsOnly(serverUrl, true);
expect((result as { error: unknown}).error).toBeUndefined();
const models = (result as SystemModel[]);
expect(models).toBeDefined();
expect(models?.length).toBe(1);
expect(models![0].id).toBe(SYSTEM_IDENTIFIERS.ONLY_UNREADS);
expect(models![0].value).toBe(true);
});
});
describe('updateDmGmDisplayName', () => {
let operator: ServerDataOperator;
const serverUrl = 'baseHandler.test.com';
const channelId = 'id1';
const dmChannel: Channel = {
id: channelId,
name: 'userid__userid2',
display_name: '',
team_id: '',
total_msg_count: 0,
delete_at: 0,
type: 'D',
} as Channel;
const dmChannelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: dmChannel.id,
msg_count: 0,
roles: '',
} as ChannelMembership;
const gmChannel: Channel = {
id: 'id2',
name: 'name',
display_name: '',
team_id: '',
total_msg_count: 0,
delete_at: 0,
type: 'G',
} as Channel;
const gmChannelMember: ChannelMembership = {
id: 'id',
user_id: 'userid',
channel_id: gmChannel.id,
msg_count: 0,
roles: '',
} as ChannelMembership;
const user: UserProfile = {
id: 'userid',
username: 'username',
roles: '',
} as UserProfile;
const user2: UserProfile = {
id: 'userid2',
username: 'username2',
first_name: 'first',
last_name: 'last',
roles: '',
} as UserProfile;
const user3: UserProfile = {
id: 'userid3',
username: 'username3',
first_name: 'first',
last_name: 'last',
roles: '',
} as UserProfile;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
operator = DatabaseManager.serverDatabases[serverUrl]!.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
it('handle not found database', async () => {
const {channels, error} = await updateDmGmDisplayName('foo');
expect(channels).toBeUndefined();
expect(error).toBeTruthy();
});
it('handle no currnet user', async () => {
const {channels, error} = await updateDmGmDisplayName(serverUrl);
expect(channels).toBeUndefined();
expect(error).toBeDefined();
expect(error).toBe('The current user id could not be retrieved from the database');
});
it('update dm gm display name', async () => {
await operator.handleChannel({channels: [dmChannel, gmChannel], prepareRecordsOnly: false});
await operator.handleUsers({users: [user, user2, user3], prepareRecordsOnly: false});
await operator.handleChannelMembership({channelMemberships: [gmChannelMember, dmChannelMember, {...gmChannelMember, user_id: user2.id}, {...gmChannelMember, user_id: user3.id}], prepareRecordsOnly: false});
await operator.handleMyChannel({channels: [dmChannel, gmChannel], myChannels: [dmChannelMember, gmChannelMember], prepareRecordsOnly: false});
await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}], prepareRecordsOnly: false});
const {channels, error} = await updateDmGmDisplayName(serverUrl);
expect(error).toBeUndefined();
expect(channels).toBeDefined();
expect(channels?.length).toBe(2);
expect((channels![0] as ChannelModel).displayName).toBe(user2.username);
expect((channels![1] as ChannelModel).displayName).toBe(`${user2.username}, ${user3.username}`);
});
});

View file

@ -139,15 +139,17 @@ export async function setChannelDeleteAt(serverUrl: string, channelId: string, d
const {operator, database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
const channel = await getChannelById(database, channelId);
if (!channel) {
return;
return {error: `channel with id ${channelId} not found`};
}
const model = channel.prepareUpdate((c) => {
c.deleteAt = deleteAt;
});
await operator.batchRecords([model], 'setChannelDeleteAt');
return {models: [model]};
} catch (error) {
logError('FAILED TO BATCH CHANGES FOR CHANNEL DELETE AT', error);
return {error};
}
}