mattermost-mobile/app/actions/websocket/threads.test.ts
Joram Wilander 575a689407
Add tests to remaining actions/websocket files (#8495)
* test: Add comprehensive tests for websocket roles actions

* test: Add comprehensive tests for websocket category actions

* test: Add comprehensive tests for websocket preferences actions

* test: Add comprehensive tests for websocket threads actions

* test: Add comprehensive tests for websocket reactions actions

* test: Add comprehensive tests for websocket system actions

* test: Add comprehensive tests for websocket integrations actions
2025-01-21 08:42:09 -05:00

221 lines
6.9 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {markTeamThreadsAsRead, processReceivedThreads, updateThread} from '@actions/local/thread';
import DatabaseManager from '@database/manager';
import {getCurrentTeamId} from '@queries/servers/system';
import EphemeralStore from '@store/ephemeral_store';
import {handleThreadUpdatedEvent, handleThreadReadChangedEvent, handleThreadFollowChangedEvent} from './threads';
jest.mock('@actions/local/thread');
jest.mock('@database/manager');
jest.mock('@queries/servers/system');
jest.mock('@store/ephemeral_store');
describe('WebSocket Threads Actions', () => {
const serverUrl = 'baseHandler.test.com';
const teamId = 'team-id';
const threadId = 'thread-id';
beforeEach(async () => {
jest.clearAllMocks();
await DatabaseManager.init([serverUrl]);
DatabaseManager.getServerDatabaseAndOperator = jest.fn().mockReturnValue({
database: {},
operator: {},
});
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
describe('handleThreadUpdatedEvent', () => {
it('should process received thread', async () => {
const mockThread = {
id: threadId,
reply_count: 3,
};
const msg = {
data: {
thread: JSON.stringify(mockThread),
},
broadcast: {
team_id: teamId,
},
} as WebSocketMessage;
jest.mocked(getCurrentTeamId).mockResolvedValue(teamId);
jest.mocked(processReceivedThreads);
await handleThreadUpdatedEvent(serverUrl, msg);
expect(processReceivedThreads).toHaveBeenCalledWith(
serverUrl,
[{...mockThread, is_following: true}],
teamId,
);
});
it('should handle missing team_id', async () => {
const mockThread = {
id: threadId,
reply_count: 3,
};
const msg = {
data: {
thread: JSON.stringify(mockThread),
},
broadcast: {},
} as WebSocketMessage;
jest.mocked(getCurrentTeamId).mockResolvedValue(teamId);
await handleThreadUpdatedEvent(serverUrl, msg);
expect(processReceivedThreads).toHaveBeenCalledWith(
serverUrl,
[{...mockThread, is_following: true}],
teamId,
);
});
it('should handle error gracefully', async () => {
const msg = {
data: {
thread: 'invalid-json',
},
broadcast: {},
} as WebSocketMessage;
await handleThreadUpdatedEvent(serverUrl, msg);
expect(processReceivedThreads).not.toHaveBeenCalled();
});
});
describe('handleThreadReadChangedEvent', () => {
it('should update thread when thread_id is present', async () => {
const timestamp = 1234567890;
const msg = {
data: {
thread_id: threadId,
timestamp,
unread_mentions: 2,
unread_replies: 5,
},
broadcast: {
team_id: teamId,
},
} as WebSocketMessage<ThreadReadChangedData>;
jest.mocked(EphemeralStore.getCurrentThreadId).mockReturnValue('different-thread');
await handleThreadReadChangedEvent(serverUrl, msg);
expect(updateThread).toHaveBeenCalledWith(serverUrl, threadId, {
unread_mentions: 2,
unread_replies: 5,
last_viewed_at: timestamp,
viewed_at: timestamp,
});
});
it('should not update viewed_at when thread is currently visible', async () => {
const timestamp = 1234567890;
const msg = {
data: {
thread_id: threadId,
timestamp,
unread_mentions: 2,
unread_replies: 5,
},
broadcast: {
team_id: teamId,
},
} as WebSocketMessage<ThreadReadChangedData>;
jest.mocked(EphemeralStore.getCurrentThreadId).mockReturnValue(threadId);
await handleThreadReadChangedEvent(serverUrl, msg);
expect(updateThread).toHaveBeenCalledWith(serverUrl, threadId, {
unread_mentions: 2,
unread_replies: 5,
last_viewed_at: timestamp,
});
});
it('should mark team threads as read when thread_id is missing', async () => {
const msg = {
data: {
timestamp: 1234567890,
},
broadcast: {
team_id: teamId,
},
} as WebSocketMessage<ThreadReadChangedData>;
await handleThreadReadChangedEvent(serverUrl, msg);
expect(markTeamThreadsAsRead).toHaveBeenCalledWith(serverUrl, teamId);
});
it('should handle error gracefully', async () => {
jest.mocked(updateThread).mockRejectedValue(new Error('test error'));
const msg = {
data: {
thread_id: threadId,
timestamp: 1234567890,
},
broadcast: {
team_id: teamId,
},
} as WebSocketMessage<ThreadReadChangedData>;
await handleThreadReadChangedEvent(serverUrl, msg);
expect(updateThread).toHaveBeenCalled();
});
});
describe('handleThreadFollowChangedEvent', () => {
it('should update thread following state', async () => {
const msg = {
data: {
thread_id: threadId,
state: true,
reply_count: 5,
},
} as WebSocketMessage;
await handleThreadFollowChangedEvent(serverUrl, msg);
expect(updateThread).toHaveBeenCalledWith(serverUrl, threadId, {
is_following: true,
reply_count: 5,
});
});
it('should handle error gracefully', async () => {
jest.mocked(updateThread).mockRejectedValue(new Error('test error'));
const msg = {
data: {
thread_id: threadId,
state: false,
reply_count: 3,
},
} as WebSocketMessage;
await handleThreadFollowChangedEvent(serverUrl, msg);
expect(updateThread).toHaveBeenCalled();
});
});
});