Add Unit tests to app/actions/local/teams.ts (#8088)
This commit is contained in:
parent
8f536f7597
commit
0698cf558d
2 changed files with 401 additions and 1 deletions
399
app/actions/local/team.test.ts
Normal file
399
app/actions/local/team.test.ts
Normal file
|
|
@ -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});
|
||||
});
|
||||
});
|
||||
|
|
@ -7,6 +7,8 @@ import {logError} from '@utils/log';
|
|||
|
||||
import type Model from '@nozbe/watermelondb/Model';
|
||||
|
||||
export const MAX_TEAM_SEARCHES = 15;
|
||||
|
||||
export async function removeUserFromTeam(serverUrl: string, teamId: string) {
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
|
|
@ -34,7 +36,6 @@ export async function removeUserFromTeam(serverUrl: string, teamId: string) {
|
|||
}
|
||||
|
||||
export async function addSearchToTeamSearchHistory(serverUrl: string, teamId: string, terms: string) {
|
||||
const MAX_TEAM_SEARCHES = 15;
|
||||
try {
|
||||
const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
|
||||
const newSearch: TeamSearchHistory = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue