-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Unit tests to app/actions/local/teams.ts (#8088)
- Loading branch information
1 parent
8f536f7
commit 0698cf5
Showing
2 changed files
with
401 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,399 @@ | ||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||
// See LICENSE.txt for license information. | ||
import ServerDataOperator from '@app/database/operator/server_data_operator'; | ||
import DatabaseManager from '@database/manager'; | ||
import {getMyTeamById, getTeamById, getTeamSearchHistoryById, prepareDeleteTeam, removeTeamFromTeamHistory} from '@queries/servers/team'; | ||
import {logError} from '@utils/log'; | ||
|
||
import {queryTeamSearchHistoryByTeamId} from '../../queries/servers/team'; | ||
|
||
import {addSearchToTeamSearchHistory, removeSearchFromTeamSearchHistory, removeUserFromTeam, MAX_TEAM_SEARCHES} from './team'; | ||
|
||
jest.mock('@database/manager'); | ||
jest.mock('@queries/servers/team'); | ||
jest.mock('@utils/log'); | ||
|
||
let operator: ServerDataOperator; | ||
const serverUrl = 'baseHandler.test.com'; | ||
const teamId = 'teamId123'; | ||
const database = { | ||
write: jest.fn(async (callback) => callback()), | ||
}; | ||
|
||
describe('removeSearchFromTeamSearchHistory', () => { | ||
const searchId = 'searchId123'; | ||
|
||
beforeEach(async () => { | ||
jest.clearAllMocks(); | ||
await DatabaseManager.init([serverUrl]); | ||
operator = DatabaseManager.serverDatabases[serverUrl]!.operator; | ||
DatabaseManager.getServerDatabaseAndOperator = jest.fn(); | ||
(DatabaseManager.getServerDatabaseAndOperator as jest.Mock).mockReturnValue({ | ||
database, | ||
operator, | ||
}); | ||
}); | ||
|
||
afterEach(async () => { | ||
await DatabaseManager.destroyServerDatabase(serverUrl); | ||
}); | ||
|
||
it('should remove search from team search history successfully', async () => { | ||
const teamSearch = { | ||
destroyPermanently: jest.fn(), | ||
}; | ||
(getTeamSearchHistoryById as jest.Mock).mockResolvedValue(teamSearch); | ||
|
||
const result = await removeSearchFromTeamSearchHistory(serverUrl, searchId); | ||
|
||
expect(getTeamSearchHistoryById).toHaveBeenCalledWith(database, searchId); | ||
expect(database.write).toHaveBeenCalledWith(expect.any(Function)); | ||
expect(database.write).toHaveBeenCalledTimes(1); | ||
expect(teamSearch.destroyPermanently).toHaveBeenCalledTimes(1); | ||
expect(result).toEqual({teamSearch}); | ||
}); | ||
|
||
it('should handle case when team search history is not found', async () => { | ||
(getTeamSearchHistoryById as jest.Mock).mockResolvedValue(undefined); | ||
|
||
const result = await removeSearchFromTeamSearchHistory(serverUrl, searchId); | ||
|
||
expect(getTeamSearchHistoryById).toHaveBeenCalledWith(database, searchId); | ||
expect(database.write).not.toHaveBeenCalled(); | ||
expect(result).toEqual({teamSearch: undefined}); | ||
}); | ||
|
||
it('should handle errors and log them', async () => { | ||
const error = new Error('Test error'); | ||
(getTeamSearchHistoryById as jest.Mock).mockRejectedValue(error); | ||
|
||
const result = await removeSearchFromTeamSearchHistory(serverUrl, searchId); | ||
|
||
expect(getTeamSearchHistoryById).toHaveBeenCalledWith(database, searchId); | ||
expect(logError).toHaveBeenCalledWith('Failed removeSearchFromTeamSearchHistory', error); | ||
expect(result).toEqual({error}); | ||
}); | ||
|
||
it('should handle database write errors', async () => { | ||
const teamSearch = { | ||
destroyPermanently: jest.fn(), | ||
}; | ||
const writeError = new Error('Database write error'); | ||
(getTeamSearchHistoryById as jest.Mock).mockResolvedValue(teamSearch); | ||
(database.write as jest.Mock).mockRejectedValue(writeError); | ||
|
||
const result = await removeSearchFromTeamSearchHistory(serverUrl, searchId); | ||
|
||
expect(getTeamSearchHistoryById).toHaveBeenCalledWith(database, searchId); | ||
expect(database.write).toHaveBeenCalledWith(expect.any(Function)); | ||
expect(logError).toHaveBeenCalledWith('Failed removeSearchFromTeamSearchHistory', writeError); | ||
expect(result).toEqual({error: writeError}); | ||
}); | ||
}); | ||
|
||
describe('removeUserFromTeam', () => { | ||
beforeEach(async () => { | ||
jest.clearAllMocks(); | ||
await DatabaseManager.init([serverUrl]); | ||
operator = DatabaseManager.serverDatabases[serverUrl]!.operator; | ||
DatabaseManager.getServerDatabaseAndOperator = jest.fn(); | ||
(DatabaseManager.getServerDatabaseAndOperator as jest.Mock).mockReturnValue({ | ||
database, | ||
operator, | ||
}); | ||
|
||
operator.batchRecords = jest.fn(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await DatabaseManager.destroyServerDatabase(serverUrl); | ||
}); | ||
|
||
it('should remove user from team successfully', async () => { | ||
const myTeam = {id: 'myTeamId'}; | ||
const team = {id: 'myTeamId'}; | ||
const preparedModels = [ | ||
{id: 'model1', _preparedState: 'markAsDeleted'}, | ||
{id: 'model2', _preparedState: 'markAsDeleted'}, | ||
]; | ||
const systemModels = [ | ||
{id: 'systemModel1', _preparedState: 'update', value: []}, | ||
]; | ||
|
||
(getMyTeamById as jest.Mock).mockResolvedValue(myTeam); | ||
(getTeamById as jest.Mock).mockResolvedValue(team); | ||
(prepareDeleteTeam as jest.Mock).mockResolvedValue(preparedModels); | ||
(removeTeamFromTeamHistory as jest.Mock).mockResolvedValue(systemModels); | ||
|
||
const result = await removeUserFromTeam(serverUrl, team.id); | ||
|
||
expect(getMyTeamById).toHaveBeenCalledWith(database, team.id); | ||
expect(getTeamById).toHaveBeenCalledWith(database, myTeam.id); | ||
expect(prepareDeleteTeam).toHaveBeenCalledWith(team); | ||
expect(removeTeamFromTeamHistory).toHaveBeenCalledWith(operator, team.id, true); | ||
expect(operator.batchRecords).toHaveBeenCalledWith(preparedModels, 'removeUserFromTeam'); | ||
|
||
// Verify team id is not present | ||
systemModels.forEach((model) => { | ||
expect(model.value).not.toContain(team.id); | ||
}); | ||
|
||
// Check if preparedModels contain systemModels | ||
expect(preparedModels).toEqual(expect.arrayContaining(systemModels)); | ||
|
||
expect(result).toEqual({error: undefined}); | ||
}); | ||
|
||
it('should handle errors during database write', async () => { | ||
const myTeam = {id: 'myTeamId'}; | ||
const team = {id: 'teamId'}; | ||
const preparedModels = [ | ||
{id: 'model1', _preparedState: 'markAsDeleted'}, | ||
{id: 'model2', _preparedState: 'markAsDeleted'}, | ||
]; | ||
const systemModels = [ | ||
{id: 'systemModel1', _preparedState: 'update', value: [team.id]}, | ||
]; | ||
const writeError = new Error('Database write error'); | ||
|
||
(getMyTeamById as jest.Mock).mockResolvedValue(myTeam); | ||
(getTeamById as jest.Mock).mockResolvedValue(team); | ||
(prepareDeleteTeam as jest.Mock).mockResolvedValue(preparedModels); | ||
(removeTeamFromTeamHistory as jest.Mock).mockResolvedValue(systemModels); | ||
(operator.batchRecords as jest.Mock).mockRejectedValue(writeError); | ||
|
||
const result = await removeUserFromTeam(serverUrl, teamId); | ||
|
||
expect(getMyTeamById).toHaveBeenCalledWith(database, teamId); | ||
expect(getTeamById).toHaveBeenCalledWith(database, myTeam.id); | ||
expect(prepareDeleteTeam).toHaveBeenCalledWith(team); | ||
expect(removeTeamFromTeamHistory).toHaveBeenCalledWith(operator, team.id, true); | ||
expect(operator.batchRecords).toHaveBeenCalledWith(preparedModels, 'removeUserFromTeam'); | ||
expect(logError).toHaveBeenCalledWith('Failed removeUserFromTeam', writeError); | ||
|
||
// Verify team id is present | ||
systemModels.forEach((model) => { | ||
expect(model.value).toContain(team.id); | ||
}); | ||
|
||
// Check if preparedModels contain systemModels | ||
expect(preparedModels).toEqual(expect.arrayContaining(systemModels)); | ||
|
||
expect(result).toEqual({error: writeError}); | ||
}); | ||
|
||
it('should handle case when myTeam is not found', async () => { | ||
(getMyTeamById as jest.Mock).mockResolvedValue(null); | ||
|
||
const result = await removeUserFromTeam(serverUrl, teamId); | ||
|
||
expect(getMyTeamById).toHaveBeenCalledWith(database, teamId); | ||
expect(getTeamById).not.toHaveBeenCalled(); | ||
expect(prepareDeleteTeam).not.toHaveBeenCalled(); | ||
expect(removeTeamFromTeamHistory).not.toHaveBeenCalled(); | ||
expect(operator.batchRecords).not.toHaveBeenCalled(); | ||
expect(result).toEqual({error: undefined}); | ||
}); | ||
|
||
it('should handle case when team is not found', async () => { | ||
const myTeam = {id: 'myTeamId'}; | ||
|
||
(getMyTeamById as jest.Mock).mockResolvedValue(myTeam); | ||
(getTeamById as jest.Mock).mockResolvedValue(null); | ||
|
||
const result = await removeUserFromTeam(serverUrl, teamId); | ||
|
||
expect(getMyTeamById).toHaveBeenCalledWith(database, teamId); | ||
expect(getTeamById).toHaveBeenCalledWith(database, myTeam.id); | ||
expect(result.error).toEqual(new Error('Team not found')); | ||
}); | ||
|
||
it('should handle errors and log them', async () => { | ||
const error = new Error('Test error'); | ||
(DatabaseManager.getServerDatabaseAndOperator as jest.Mock).mockImplementation(() => { | ||
throw error; | ||
}); | ||
|
||
const result = await removeUserFromTeam(serverUrl, teamId); | ||
|
||
expect(DatabaseManager.getServerDatabaseAndOperator).toHaveBeenCalled(); | ||
expect(logError).toHaveBeenCalledWith('Failed removeUserFromTeam', error); | ||
expect(result).toEqual({error}); | ||
}); | ||
|
||
it('should handle when removeTeamFromTeamHistory returns undefined or empty array', async () => { | ||
const myTeam = {id: 'myTeamId'}; | ||
const team = {id: 'teamId'}; | ||
const preparedModels = [ | ||
{id: 'model1', _preparedState: 'markAsDeleted'}, | ||
{id: 'model2', _preparedState: 'markAsDeleted'}, | ||
]; | ||
|
||
(getMyTeamById as jest.Mock).mockResolvedValue(myTeam); | ||
(getTeamById as jest.Mock).mockResolvedValue(team); | ||
(prepareDeleteTeam as jest.Mock).mockResolvedValue(preparedModels); | ||
(removeTeamFromTeamHistory as jest.Mock).mockResolvedValue(undefined); | ||
|
||
const result = await removeUserFromTeam(serverUrl, teamId); | ||
|
||
expect(getMyTeamById).toHaveBeenCalledWith(database, teamId); | ||
expect(getTeamById).toHaveBeenCalledWith(database, myTeam.id); | ||
expect(prepareDeleteTeam).toHaveBeenCalledWith(team); | ||
expect(removeTeamFromTeamHistory).toHaveBeenCalledWith(operator, team.id, true); | ||
expect(operator.batchRecords).toHaveBeenCalledWith(preparedModels, 'removeUserFromTeam'); | ||
expect(result).toEqual({error: undefined}); | ||
}); | ||
|
||
it('should handle when models length is 0', async () => { | ||
const myTeam = {id: 'myTeamId'}; | ||
const team = {id: 'teamId'}; | ||
const models: never[] = []; | ||
|
||
(getMyTeamById as jest.Mock).mockResolvedValue(myTeam); | ||
(getTeamById as jest.Mock).mockResolvedValue(team); | ||
(prepareDeleteTeam as jest.Mock).mockResolvedValue([]); | ||
(removeTeamFromTeamHistory as jest.Mock).mockResolvedValue(models); | ||
|
||
const result = await removeUserFromTeam(serverUrl, teamId); | ||
|
||
expect(getMyTeamById).toHaveBeenCalledWith(database, teamId); | ||
expect(getTeamById).toHaveBeenCalledWith(database, myTeam.id); | ||
expect(prepareDeleteTeam).toHaveBeenCalledWith(team); | ||
expect(removeTeamFromTeamHistory).toHaveBeenCalledWith(operator, team.id, true); | ||
expect(operator.batchRecords).not.toHaveBeenCalled(); | ||
expect(result).toEqual({error: undefined}); | ||
}); | ||
}); | ||
|
||
describe('addSearchToTeamSearchHistory', () => { | ||
const terms = 'search terms'; | ||
|
||
beforeEach(async () => { | ||
jest.clearAllMocks(); | ||
await DatabaseManager.init([serverUrl]); | ||
operator = DatabaseManager.serverDatabases[serverUrl]!.operator; | ||
DatabaseManager.getServerDatabaseAndOperator = jest.fn(); | ||
(DatabaseManager.getServerDatabaseAndOperator as jest.Mock).mockReturnValue({ | ||
database, | ||
operator, | ||
}); | ||
|
||
operator.handleTeamSearchHistory = jest.fn(); | ||
operator.batchRecords = jest.fn(); | ||
}); | ||
|
||
afterEach(async () => { | ||
await DatabaseManager.destroyServerDatabase(serverUrl); | ||
}); | ||
|
||
it('should add search to team search history successfully', async () => { | ||
const newSearch = { | ||
created_at: Date.now(), | ||
display_term: terms, | ||
term: terms, | ||
team_id: teamId, | ||
}; | ||
const searchModel = {id: 'searchModelId', _raw: {_changed: 'created_at'}}; | ||
(operator.handleTeamSearchHistory as jest.Mock).mockResolvedValue([searchModel]); | ||
|
||
const result = await addSearchToTeamSearchHistory(serverUrl, teamId, terms); | ||
|
||
expect(operator.handleTeamSearchHistory).toHaveBeenCalledWith({ | ||
teamSearchHistories: [newSearch], | ||
prepareRecordsOnly: true, | ||
}); | ||
expect(operator.batchRecords).toHaveBeenCalledWith([searchModel], 'addSearchToTeamHistory'); | ||
expect(result).toEqual({searchModel}); | ||
}); | ||
|
||
it('should delete the oldest entry if team search history exceeds the limit', async () => { | ||
const newSearch = { | ||
created_at: Date.now(), | ||
display_term: terms, | ||
term: terms, | ||
team_id: teamId, | ||
}; | ||
const searchModel = {id: 'searchModelId', _raw: {_changed: ''}}; | ||
const oldSearchModel = {id: 'oldSearchModelId', prepareDestroyPermanently: jest.fn().mockReturnValue(undefined)}; | ||
const teamSearchHistory = new Array(MAX_TEAM_SEARCHES + 1).fill(oldSearchModel); | ||
|
||
(operator.handleTeamSearchHistory as jest.Mock).mockResolvedValue([searchModel]); | ||
(queryTeamSearchHistoryByTeamId as jest.Mock).mockReturnValue({ | ||
fetch: jest.fn().mockResolvedValue(teamSearchHistory), | ||
}); | ||
|
||
const result = await addSearchToTeamSearchHistory(serverUrl, teamId, terms); | ||
|
||
expect(operator.handleTeamSearchHistory).toHaveBeenCalledWith({ | ||
teamSearchHistories: [newSearch], | ||
prepareRecordsOnly: true, | ||
}); | ||
expect(queryTeamSearchHistoryByTeamId).toHaveBeenCalledWith(database, teamId); | ||
expect(oldSearchModel.prepareDestroyPermanently).toHaveBeenCalledTimes(1); | ||
expect(operator.batchRecords).toHaveBeenCalledWith([searchModel], 'addSearchToTeamHistory'); | ||
expect(result).toEqual({searchModel}); | ||
}); | ||
|
||
it('should handle case when searchModel._raw._changed is "created_at"', async () => { | ||
const newSearch = { | ||
created_at: Date.now(), | ||
display_term: terms, | ||
term: terms, | ||
team_id: teamId, | ||
}; | ||
const searchModel = {id: 'searchModelId', _raw: {_changed: 'created_at'}}; | ||
(operator.handleTeamSearchHistory as jest.Mock).mockResolvedValue([searchModel]); | ||
|
||
const result = await addSearchToTeamSearchHistory(serverUrl, teamId, terms); | ||
|
||
expect(operator.handleTeamSearchHistory).toHaveBeenCalledWith({ | ||
teamSearchHistories: [newSearch], | ||
prepareRecordsOnly: true, | ||
}); | ||
expect(queryTeamSearchHistoryByTeamId).not.toHaveBeenCalled(); | ||
expect(operator.batchRecords).toHaveBeenCalledWith([searchModel], 'addSearchToTeamHistory'); | ||
expect(result).toEqual({searchModel}); | ||
}); | ||
|
||
it('should handle case when teamSearchHistory length is less than or equal to MAX_TEAM_SEARCHES', async () => { | ||
const newSearch = { | ||
created_at: Date.now(), | ||
display_term: terms, | ||
term: terms, | ||
team_id: teamId, | ||
}; | ||
const searchModel = {id: 'searchModelId', _raw: {_changed: ''}}; | ||
const oldSearchModel = {id: 'oldSearchModelId', prepareDestroyPermanently: jest.fn().mockReturnValue(undefined)}; | ||
const teamSearchHistory = new Array(MAX_TEAM_SEARCHES).fill(searchModel); | ||
|
||
(operator.handleTeamSearchHistory as jest.Mock).mockResolvedValue([searchModel]); | ||
(queryTeamSearchHistoryByTeamId as jest.Mock).mockReturnValue({ | ||
fetch: jest.fn().mockResolvedValue(teamSearchHistory), | ||
}); | ||
|
||
const result = await addSearchToTeamSearchHistory(serverUrl, teamId, terms); | ||
|
||
expect(operator.handleTeamSearchHistory).toHaveBeenCalledWith({ | ||
teamSearchHistories: [newSearch], | ||
prepareRecordsOnly: true, | ||
}); | ||
expect(queryTeamSearchHistoryByTeamId).toHaveBeenCalledWith(database, teamId); | ||
expect(operator.batchRecords).toHaveBeenCalledWith([searchModel], 'addSearchToTeamHistory'); | ||
expect(result).toEqual({searchModel}); | ||
expect(oldSearchModel.prepareDestroyPermanently).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle errors and log them', async () => { | ||
const error = new Error('Test error'); | ||
(operator.handleTeamSearchHistory as jest.Mock).mockRejectedValue(error); | ||
|
||
const result = await addSearchToTeamSearchHistory(serverUrl, teamId, terms); | ||
|
||
expect(operator.handleTeamSearchHistory).toHaveBeenCalledWith({ | ||
teamSearchHistories: [{created_at: expect.any(Number), display_term: terms, term: terms, team_id: teamId}], | ||
prepareRecordsOnly: true, | ||
}); | ||
expect(logError).toHaveBeenCalledWith('Failed addSearchToTeamSearchHistory', error); | ||
expect(result).toEqual({error}); | ||
}); | ||
}); |
Oops, something went wrong.