fix: character escaping in channel description notifications (#35927)

This commit is contained in:
Abhinav Kumar 2025-05-17 05:56:24 +05:30 committed by GitHub
parent aea500e01a
commit b6b11f3115
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 91 additions and 8 deletions

View File

@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes incorrect character escaping in system messages by removing unnecessary escaping logic to ensure accurate rendering of special characters.

View File

@ -1,5 +1,4 @@
import type { IOmnichannelSystemMessage } from '@rocket.chat/core-typings';
import { escapeHTML } from '@rocket.chat/string-helpers';
import formatDistance from 'date-fns/formatDistance';
import moment from 'moment';
@ -124,7 +123,7 @@ MessageTypes.registerType({
};
}
return {
message: escapeHTML(message.msg),
message: message.msg,
};
},
});

View File

@ -0,0 +1,81 @@
import { faker } from '@faker-js/faker';
import type { IMessage } from '@rocket.chat/core-typings';
import { mockAppRoot } from '@rocket.chat/mock-providers';
import { Random } from '@rocket.chat/random';
import { render, screen } from '@testing-library/react';
import SystemMessage from './SystemMessage';
import '../../../startup/messageTypes';
jest.mock('../../../../app/ui-utils/client', () => {
const actual = jest.requireActual('../../../../app/ui-utils/lib/MessageTypes');
return {
MessageTypes: actual.MessageTypes,
};
});
jest.mock('../content/Attachments', () => ({
default: () => <div>attachments</div>,
}));
jest.mock('../content/MessageActions', () => ({
default: () => <div>message actions</div>,
}));
jest.mock('meteor/meteor', () => {
const actual = jest.requireActual('meteor/meteor');
return {
...actual,
Meteor: {
...actual.Meteor,
startup: (callback: () => void) => callback(),
},
};
});
const wrapper = mockAppRoot().withTranslations('en', 'core', {
changed_room_description_to__room_description_: 'changed room description to: {{room_description}}',
});
const createBaseMessage = (msg: string): IMessage => ({
_id: Random.id(),
t: 'room_changed_description',
rid: Random.id(),
ts: new Date(),
msg,
u: {
_id: Random.id(),
username: faker.person.firstName().toLocaleLowerCase(),
name: faker.person.fullName(),
},
groupable: false,
_updatedAt: new Date(),
});
describe('SystemMessage', () => {
it('should render system message', () => {
const message = createBaseMessage('& test &');
render(<SystemMessage message={message} showUserAvatar />, { legacyRoot: true, wrapper: wrapper.build() });
expect(screen.getByText('changed room description to: & test &')).toBeInTheDocument();
});
it('should not show escaped html while rendering system message', () => {
const message = createBaseMessage('& test &');
render(<SystemMessage message={message} showUserAvatar />, { legacyRoot: true, wrapper: wrapper.build() });
expect(screen.getByText('changed room description to: & test &')).toBeInTheDocument();
expect(screen.queryByText('changed room description to: &amp; test &amp;')).not.toBeInTheDocument();
});
it('should not inject html', () => {
const message = createBaseMessage('<button title="test-title">OK</button>');
render(<SystemMessage message={message} showUserAvatar />, { legacyRoot: true, wrapper: wrapper.build() });
expect(screen.queryByTitle('test-title')).not.toBeInTheDocument();
expect(screen.getByText('changed room description to: <button title="test-title">OK</button>')).toBeInTheDocument();
});
});

View File

@ -1,5 +1,4 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { escapeHTML } from '@rocket.chat/string-helpers';
import { Meteor } from 'meteor/meteor';
import { MessageTypes } from '../../app/ui-utils/client';
@ -23,7 +22,7 @@ Meteor.startup(() => {
message: 'room_changed_topic_to',
data(message: IMessage) {
return {
room_topic: escapeHTML(message.msg || `(${t('None').toLowerCase()})`),
room_topic: message.msg || `(${t('None').toLowerCase()})`,
};
},
});
@ -40,7 +39,7 @@ Meteor.startup(() => {
message: 'changed_room_announcement_to__room_announcement_',
data(message: IMessage) {
return {
room_announcement: escapeHTML(message.msg || `(${t('None').toLowerCase()})`),
room_announcement: message.msg || `(${t('None').toLowerCase()})`,
};
},
});
@ -51,7 +50,7 @@ Meteor.startup(() => {
message: 'changed_room_description_to__room_description_',
data(message: IMessage) {
return {
room_description: escapeHTML(message.msg || `(${t('None').toLowerCase()})`),
room_description: message.msg || `(${t('None').toLowerCase()})`,
};
},
});

View File

@ -1,5 +1,4 @@
import type { IOmnichannelSystemMessage, MessageTypesValues } from '@rocket.chat/core-typings';
import { escapeHTML } from '@rocket.chat/string-helpers';
import formatDistance from 'date-fns/formatDistance';
import moment from 'moment';
@ -152,7 +151,7 @@ addType('livechat_webrtc_video_call', {
};
}
return {
message: escapeHTML(message.msg),
message: message.msg,
};
},
});