From d486f4861aea9884b3c5fe990e09d3dd19cfc675 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Thu, 3 Oct 2024 08:18:27 -0400 Subject: [PATCH] Add tests to actions/remote/team (#8241) --- app/actions/remote/team.test.ts | 293 ++++++++++++++++++++++++++++++++ app/actions/remote/team.ts | 12 +- 2 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 app/actions/remote/team.test.ts diff --git a/app/actions/remote/team.test.ts b/app/actions/remote/team.test.ts new file mode 100644 index 000000000..9f34f7262 --- /dev/null +++ b/app/actions/remote/team.test.ts @@ -0,0 +1,293 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +/* eslint-disable max-lines */ + +import {SYSTEM_IDENTIFIERS} from '@constants/database'; +import DatabaseManager from '@database/manager'; +import NetworkManager from '@managers/network_manager'; +import {getActiveServerUrl} from '@queries/app/servers'; + +import { + addCurrentUserToTeam, + addUserToTeam, + addUsersToTeam, + sendEmailInvitesToTeam, + fetchMyTeams, + fetchMyTeam, + fetchAllTeams, + fetchTeamsForComponent, + updateCanJoinTeams, + fetchTeamsChannelsAndUnreadPosts, + fetchTeamByName, + removeCurrentUserFromTeam, + removeUserFromTeam, + handleTeamChange, + handleKickFromTeam, + getTeamMembersByIds, + buildTeamIconUrl, +} from './team'; + +import type ServerDataOperator from '@database/operator/server_data_operator'; + +const serverUrl = 'baseHandler.test.com'; +let operator: ServerDataOperator; + +const user: UserProfile = { + id: 'userid', + username: 'username', + roles: '', +} as UserProfile; + +let mockIsTablet: jest.Mock; +jest.mock('@utils/helpers', () => { + const original = jest.requireActual('@utils/helpers'); + mockIsTablet = jest.fn(() => false); + return { + ...original, + isTablet: mockIsTablet, + }; +}); + +let mockGetActiveServer: jest.Mock; +jest.mock('@queries/app/servers', () => { + const original = jest.requireActual('@queries/app/servers'); + mockGetActiveServer = jest.fn(() => false); + return { + ...original, + getActiveServer: mockGetActiveServer, + }; +}); + +jest.mock('@queries/app/servers', () => ({ + getActiveServerUrl: jest.fn(), +})); + +const channelId = 'channelid1'; +const teamId = 'teamid1'; + +const team: Team = { + id: teamId, + name: 'team1', +} as Team; + +const mockClient = { + getTeam: jest.fn((id: string) => ({id, name: 'team1'})), + getTeamMember: jest.fn((id: string, userId: string) => ({id: userId + '-' + id, user_id: userId === 'me' ? 'userid1' : userId, team_id: id, roles: ''})), + addToTeam: jest.fn((id: string, userId: string) => ({id: userId + '-' + id, user_id: userId, team_id: id, roles: ''})), + addUsersToTeamGracefully: jest.fn((id: string, userIds: string[]) => (userIds.map((userId) => ({member: {id: userId + '-' + id, user_id: userId, team_id: id, roles: ''}, error: undefined, user_id: userId})))), + sendEmailInvitesToTeamGracefully: jest.fn((id: string, emails: string[]) => (emails.map((email) => ({email, error: undefined})))), + getRolesByNames: jest.fn((roles: string[]) => roles.map((r) => ({id: r, name: r} as Role))), + getMyTeams: jest.fn(() => ([{id: teamId, name: 'team1'}])), + getMyTeamMembers: jest.fn(() => ([{id: 'userid1-' + teamId, user_id: 'userid1', team_id: teamId, roles: ''}])), + getTeams: jest.fn(() => ([{id: teamId, name: 'team1'}])), + getMyChannels: jest.fn((id: string) => ([{id: channelId, name: 'channel1', creatorId: user.id, team_id: id}])), + getMyChannelMembers: jest.fn(() => ([{id: user.id + '-' + channelId, user_id: user.id, channel_id: channelId, roles: ''}])), + getCategories: jest.fn((userId: string, id: string) => ({categories: [{id: 'categoryid', channel_id: [channelId], team_id: id}], order: ['categoryid']})), + getTeamByName: jest.fn((name: string) => ({id: teamId, name})), + removeFromTeam: jest.fn(), + getTeamMembersByIds: jest.fn((id: string, userIds: string[]) => (userIds.map((userId) => ({id: userId + '-' + id, user_id: userId, team_id: id, roles: ''})))), +}; + +beforeAll(() => { + // eslint-disable-next-line + // @ts-ignore + NetworkManager.getClient = () => mockClient; +}); + +beforeEach(async () => { + await DatabaseManager.init([serverUrl]); + operator = DatabaseManager.serverDatabases[serverUrl]!.operator; +}); + +afterEach(async () => { + await DatabaseManager.destroyServerDatabase(serverUrl); +}); + +describe('teamMember', () => { + it('addCurrentUserToTeam - handle not found database', async () => { + const result = await addCurrentUserToTeam('foo', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('addCurrentUserToTeam - no current user', async () => { + const result = await addCurrentUserToTeam(serverUrl, teamId); + expect(result?.error).toBeDefined(); + expect(result.error).toBe('no current user'); + }); + + it('addCurrentUserToTeam - base case', async () => { + await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_USER_ID, value: user.id}, {id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: teamId}], prepareRecordsOnly: false}); + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await addCurrentUserToTeam(serverUrl, teamId) as {member: TeamMembership}; + expect(result).toBeDefined(); + expect(result.member).toBeDefined(); + }); + + it('addUserToTeam - handle not found database', async () => { + const result = await addUserToTeam('foo', '', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('addUserToTeam - base case', async () => { + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await addUserToTeam(serverUrl, teamId, 'userid1') as {member: TeamMembership}; + expect(result).toBeDefined(); + expect(result.member).toBeDefined(); + }); + + it('addUsersToTeam - handle not found database', async () => { + const result = await addUsersToTeam('foo', '', []) as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('addUsersToTeam - base case', async () => { + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await addUsersToTeam(serverUrl, teamId, ['userid1']) as {members: TeamMemberWithError[]}; + expect(result).toBeDefined(); + expect(result.members).toBeDefined(); + }); + + it('sendEmailInvitesToTeam - base case', async () => { + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await sendEmailInvitesToTeam(serverUrl, teamId, ['user1@mattermost.com']) as {members: TeamInviteWithError[]}; + expect(result).toBeDefined(); + expect(result.members).toBeDefined(); + }); + + it('handleKickFromTeam - handle not found database', async () => { + const result = await handleKickFromTeam('foo', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('removeCurrentUserFromTeam - handle not found database', async () => { + const result = await removeCurrentUserFromTeam('foo', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('removeCurrentUserFromTeam - base case', async () => { + const result = await removeCurrentUserFromTeam(serverUrl, teamId); + expect(result).toBeDefined(); + }); + + it('removeUserFromTeam - base case', async () => { + const result = await removeUserFromTeam(serverUrl, 'userid1', teamId); + expect(result).toBeDefined(); + }); + + it('getTeamMembersByIds - handle not found database', async () => { + const result = await getTeamMembersByIds('foo', '', []) as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('getTeamMembersByIds - base case', async () => { + const result = await getTeamMembersByIds(serverUrl, teamId, ['userid1']); + expect(result).toBeDefined(); + expect(result?.members).toBeDefined(); + }); +}); + +describe('teams', () => { + it('fetchMyTeams - handle not found database', async () => { + const result = await fetchMyTeams('foo') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('fetchMyTeams - base case', async () => { + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await fetchMyTeams(serverUrl); + expect(result).toBeDefined(); + expect(result.teams).toBeDefined(); + expect(result.memberships).toBeDefined(); + }); + + it('fetchMyTeam - handle not found database', async () => { + const result = await fetchMyTeam('foo', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('fetchMyTeam - base case', async () => { + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await fetchMyTeam(serverUrl, teamId); + expect(result).toBeDefined(); + expect(result.teams).toBeDefined(); + expect(result.memberships).toBeDefined(); + }); + + it('fetchAllTeams - base case', async () => { + const result = await fetchAllTeams(serverUrl); + expect(result).toBeDefined(); + expect(result.teams).toBeDefined(); + }); + + it('fetchTeamsForComponent - base case', async () => { + await operator.handleTeam({teams: [team], prepareRecordsOnly: false}); + + const result = await fetchTeamsForComponent(serverUrl, 0); + expect(result).toBeDefined(); + expect(result.teams).toBeDefined(); + expect(result.hasMore).toBeFalsy(); + }); + + it('updateCanJoinTeams - handle not found database', async () => { + const result = await updateCanJoinTeams('foo') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('updateCanJoinTeams - base case', async () => { + const result = await updateCanJoinTeams(serverUrl); + expect(result).toBeDefined(); + }); + + it('fetchTeamsChannelsAndUnreadPosts - handle not found database', async () => { + const result = await fetchTeamsChannelsAndUnreadPosts('foo', 0, [], []) as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('fetchTeamsChannelsAndUnreadPosts - base case', async () => { + const result = await fetchTeamsChannelsAndUnreadPosts(serverUrl, 0, [team], [{team_id: teamId, user_id: 'userid1'} as TeamMembership]); + expect(result).toBeDefined(); + }); + + it('fetchTeamByName - handle not found database', async () => { + const result = await fetchTeamByName('foo', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('fetchTeamByName - base case', async () => { + const result = await fetchTeamByName(serverUrl, teamId); + expect(result).toBeDefined(); + expect(result.team).toBeDefined(); + }); + + it('handleTeamChange - handle not found database', async () => { + const result = await handleTeamChange('foo', '') as {error: unknown}; + expect(result?.error).toBeDefined(); + }); + + it('handleTeamChange - base case', async () => { + const result = await handleTeamChange(serverUrl, teamId); + expect(result).toBeDefined(); + expect(result?.error).toBeUndefined(); + }); + + it('handleKickFromTeam - base case', async () => { + await operator.handleSystem({systems: [{id: SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID, value: teamId}], prepareRecordsOnly: false}); + (getActiveServerUrl as jest.Mock).mockResolvedValueOnce(serverUrl); + + const result = await handleKickFromTeam(serverUrl, teamId); + expect(result).toBeDefined(); + expect(result?.error).toBeUndefined(); + }); + + it('buildTeamIconUrl - base case', async () => { + const url = await buildTeamIconUrl(serverUrl, teamId); + expect(url).toBeDefined(); + }); +}); diff --git a/app/actions/remote/team.ts b/app/actions/remote/team.ts index bcb901e3e..3d62a0231 100644 --- a/app/actions/remote/team.ts +++ b/app/actions/remote/team.ts @@ -383,14 +383,14 @@ export const removeUserFromTeam = async (serverUrl: string, teamId: string, user export async function handleTeamChange(serverUrl: string, teamId: string) { const operator = DatabaseManager.serverDatabases[serverUrl]?.operator; if (!operator) { - return; + return {error: 'no database'}; } const {database} = operator; const currentTeamId = await getCurrentTeamId(database); if (currentTeamId === teamId) { - return; + return {}; } let channelId = ''; @@ -400,7 +400,7 @@ export async function handleTeamChange(serverUrl: string, teamId: string) { if (channelId) { await switchToChannelById(serverUrl, channelId, teamId); DeviceEventEmitter.emit(Events.TEAM_SWITCH, false); - return; + return {}; } } @@ -421,6 +421,7 @@ export async function handleTeamChange(serverUrl: string, teamId: string) { // Fetch Groups + GroupTeams fetchGroupsForTeamIfConstrained(serverUrl, teamId); + return {}; } export async function handleKickFromTeam(serverUrl: string, teamId: string) { @@ -428,7 +429,7 @@ export async function handleKickFromTeam(serverUrl: string, teamId: string) { const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl); const currentTeamId = await getCurrentTeamId(database); if (currentTeamId !== teamId) { - return; + return {}; } const currentServer = await getActiveServerUrl(); @@ -444,9 +445,12 @@ export async function handleKickFromTeam(serverUrl: string, teamId: string) { await handleTeamChange(serverUrl, teamToJumpTo); } + return {}; + // Resetting to team select handled by the home screen } catch (error) { logDebug('Failed to kick user from team', error); + return {error}; } }