Bor handle burned ws event (#9346)

* handled the websocket event when a user burns a BoR post as receiver

* test: add comprehensive tests for handleBoRPostBurnedEvent function

* Added tests

* reset unintended changes

* Minor fix
This commit is contained in:
Harshil Sharma 2025-12-16 08:39:30 +01:00 committed by GitHub
parent 397efd790b
commit 49efb4f470
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 118 additions and 5 deletions

View file

@ -1,15 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {removePost} from '@actions/local/post';
import {handleNewPostEvent, handlePostEdited} from '@actions/websocket/posts';
import {PostTypes} from '@constants/post';
import DatabaseManager from '@database/manager';
import {getPostById} from '@queries/servers/post';
import TestHelper from '@test/test_helper';
import {handleBoRPostRevealedEvent} from './burn_on_read';
import {handleBoRPostRevealedEvent, handleBoRPostBurnedEvent} from './burn_on_read';
jest.mock('@actions/websocket/posts');
jest.mock('@queries/servers/post');
jest.mock('@actions/local/post');
const serverUrl = 'burnOnRead.test.com';
@ -19,6 +22,7 @@ describe('WebSocket Burn on Read Actions', () => {
const mockedGetPostById = jest.mocked(getPostById);
const mockedHandleNewPostEvent = jest.mocked(handleNewPostEvent);
const mockedHandlePostEdited = jest.mocked(handlePostEdited);
const mockedRemovePost = jest.mocked(removePost);
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
@ -99,10 +103,87 @@ describe('WebSocket Burn on Read Actions', () => {
const result = await handleBoRPostRevealedEvent(serverUrl, invalidJsonMsg);
expect(result).toBeNull();
expect(result).toEqual({});
expect(mockedGetPostById).not.toHaveBeenCalled();
expect(mockedHandleNewPostEvent).not.toHaveBeenCalled();
expect(mockedHandlePostEdited).not.toHaveBeenCalled();
});
});
describe('handleBoRPostBurnedEvent', () => {
const burnOnReadPost = TestHelper.fakePostModel({
id: 'post1',
type: PostTypes.BURN_ON_READ,
});
const regularPost = TestHelper.fakePostModel({
id: 'post2',
type: '',
});
const msg = {
data: {
post_id: 'post1',
},
} as WebSocketMessage;
it('should remove burn-on-read post when it exists locally', async () => {
mockedGetPostById.mockResolvedValue(burnOnReadPost);
const result = await handleBoRPostBurnedEvent(serverUrl, msg);
expect(mockedGetPostById).toHaveBeenCalledWith(expect.any(Object), 'post1');
expect(mockedRemovePost).toHaveBeenCalledWith(serverUrl, burnOnReadPost);
expect(result).toEqual({});
});
it('should not remove post when post does not exist locally', async () => {
mockedGetPostById.mockResolvedValue(undefined);
const result = await handleBoRPostBurnedEvent(serverUrl, msg);
expect(mockedGetPostById).toHaveBeenCalledWith(expect.any(Object), 'post1');
expect(mockedRemovePost).not.toHaveBeenCalled();
expect(result).toBeNull();
});
it('should not remove post when post is not burn-on-read type', async () => {
mockedGetPostById.mockResolvedValue(regularPost);
const result = await handleBoRPostBurnedEvent(serverUrl, msg);
expect(mockedGetPostById).toHaveBeenCalledWith(expect.any(Object), 'post1');
expect(mockedRemovePost).not.toHaveBeenCalled();
expect(result).toBeNull();
});
it('should handle missing server database gracefully', async () => {
const result = await handleBoRPostBurnedEvent('invalid-server-url', msg);
expect(mockedGetPostById).not.toHaveBeenCalled();
expect(mockedRemovePost).not.toHaveBeenCalled();
expect(result).toBeNull();
});
it('should handle missing operator gracefully', async () => {
// Mock a server database without an operator
DatabaseManager.serverDatabases[serverUrl] = {} as any;
const result = await handleBoRPostBurnedEvent(serverUrl, msg);
expect(mockedGetPostById).not.toHaveBeenCalled();
expect(mockedRemovePost).not.toHaveBeenCalled();
expect(result).toBeNull();
});
it('should handle errors gracefully and return error object', async () => {
mockedGetPostById.mockRejectedValue(new Error('Database error'));
const result = await handleBoRPostBurnedEvent(serverUrl, msg);
expect(result).toHaveProperty('error');
expect(result!.error).toBeInstanceOf(Error);
expect(mockedRemovePost).not.toHaveBeenCalled();
});
});
});

View file

@ -1,7 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {removePost} from '@actions/local/post';
import {handleNewPostEvent, handlePostEdited} from '@actions/websocket/posts';
import {PostTypes} from '@constants/post';
import DatabaseManager from '@database/manager';
import {getPostById} from '@queries/servers/post';
import {logError} from '@utils/log';
@ -10,7 +12,7 @@ export async function handleBoRPostRevealedEvent(serverUrl: string, msg: WebSock
try {
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
if (!operator) {
return null;
return {};
}
const {database} = operator;
@ -18,7 +20,7 @@ export async function handleBoRPostRevealedEvent(serverUrl: string, msg: WebSock
try {
post = JSON.parse(msg.data.post);
} catch {
return null;
return {};
}
const existingPost = await getPostById(database, post.id);
@ -34,3 +36,29 @@ export async function handleBoRPostRevealedEvent(serverUrl: string, msg: WebSock
return {error};
}
}
export async function handleBoRPostBurnedEvent(serverUrl: string, msg: WebSocketMessage) {
try {
const postId = msg.data.post_id;
const operator = DatabaseManager.serverDatabases[serverUrl]?.operator;
if (!operator) {
return null;
}
const {database} = operator;
const post = await getPostById(database, postId);
if (!post) {
return null;
}
if (post.type !== PostTypes.BURN_ON_READ) {
return null;
}
await removePost(serverUrl, post);
return {};
} catch (error) {
logError('handleBoRPostBurnedEvent could not handle websocket event for burned burn-on-read post', error);
return {error};
}
}

View file

@ -4,7 +4,7 @@
import {handleAgentPostUpdate} from '@agents/actions/websocket';
import * as bookmark from '@actions/local/channel_bookmark';
import {handleBoRPostRevealedEvent} from '@actions/websocket/burn_on_read';
import {handleBoRPostBurnedEvent, handleBoRPostRevealedEvent} from '@actions/websocket/burn_on_read';
import * as scheduledPost from '@actions/websocket/scheduled_post';
import * as calls from '@calls/connection/websocket_event_handlers';
import {WebsocketEvents} from '@constants';
@ -314,6 +314,9 @@ export async function handleWebSocketEvent(serverUrl: string, msg: WebSocketMess
case WebsocketEvents.BOR_POST_REVEALED:
handleBoRPostRevealedEvent(serverUrl, msg);
break;
case WebsocketEvents.BOR_POST_BURNED:
handleBoRPostBurnedEvent(serverUrl, msg);
break;
}
handlePlaybookEvents(serverUrl, msg);
}

View file

@ -111,6 +111,7 @@ const WebsocketEvents = {
// Burn on Read
BOR_POST_REVEALED: 'post_revealed',
BOR_POST_BURNED: 'post_burned',
};
export default WebsocketEvents;