diff --git a/.changeset/selfish-bulldogs-fold.md b/.changeset/selfish-bulldogs-fold.md new file mode 100644 index 00000000000..1f2f0e5a11c --- /dev/null +++ b/.changeset/selfish-bulldogs-fold.md @@ -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. diff --git a/apps/meteor/app/livechat/lib/messageTypes.ts b/apps/meteor/app/livechat/lib/messageTypes.ts index 8a1931a300d..a5e40ad51dd 100644 --- a/apps/meteor/app/livechat/lib/messageTypes.ts +++ b/apps/meteor/app/livechat/lib/messageTypes.ts @@ -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, }; }, }); diff --git a/apps/meteor/client/components/message/variants/SystemMessage.spec.tsx b/apps/meteor/client/components/message/variants/SystemMessage.spec.tsx new file mode 100644 index 00000000000..c0482e831db --- /dev/null +++ b/apps/meteor/client/components/message/variants/SystemMessage.spec.tsx @@ -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: () =>
attachments
, +})); + +jest.mock('../content/MessageActions', () => ({ + default: () =>
message actions
, +})); + +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(, { 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(, { legacyRoot: true, wrapper: wrapper.build() }); + + expect(screen.getByText('changed room description to: & test &')).toBeInTheDocument(); + expect(screen.queryByText('changed room description to: & test &')).not.toBeInTheDocument(); + }); + + it('should not inject html', () => { + const message = createBaseMessage(''); + + render(, { legacyRoot: true, wrapper: wrapper.build() }); + + expect(screen.queryByTitle('test-title')).not.toBeInTheDocument(); + expect(screen.getByText('changed room description to: ')).toBeInTheDocument(); + }); +}); diff --git a/apps/meteor/client/startup/messageTypes.ts b/apps/meteor/client/startup/messageTypes.ts index 481ab49568a..467e7694bb9 100644 --- a/apps/meteor/client/startup/messageTypes.ts +++ b/apps/meteor/client/startup/messageTypes.ts @@ -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()})`, }; }, }); diff --git a/ee/packages/omnichannel-services/src/livechatSystemMessages.ts b/ee/packages/omnichannel-services/src/livechatSystemMessages.ts index 48e313cfa4c..e6e42a02b65 100644 --- a/ee/packages/omnichannel-services/src/livechatSystemMessages.ts +++ b/ee/packages/omnichannel-services/src/livechatSystemMessages.ts @@ -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, }; }, });