From fbd909b116b0139801db751c0154352cbb88442f Mon Sep 17 00:00:00 2001 From: martincupela Date: Wed, 17 Sep 2025 12:06:11 +0200 Subject: [PATCH] fix: render html as text in ChannelPreview --- .../ChannelPreview/__tests__/utils.test.js | 34 ++++++++++++++++++- src/components/ChannelPreview/utils.tsx | 12 ++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/components/ChannelPreview/__tests__/utils.test.js b/src/components/ChannelPreview/__tests__/utils.test.js index d46c8ddf2f..c71f345aeb 100644 --- a/src/components/ChannelPreview/__tests__/utils.test.js +++ b/src/components/ChannelPreview/__tests__/utils.test.js @@ -1,3 +1,5 @@ +import React from 'react'; +import ReactMarkdown from 'react-markdown'; import '@testing-library/jest-dom'; import { nanoid } from 'nanoid'; @@ -14,6 +16,7 @@ import { import { getDisplayImage, getDisplayTitle, getLatestMessagePreview } from '../utils'; import { generateStaticLocationResponse } from '../../../mock-builders'; +import { render } from '@testing-library/react'; describe('ChannelPreview utils', () => { const clientUser = generateUser(); @@ -55,16 +58,45 @@ describe('ChannelPreview utils', () => { }), ], }); + const channelWithHTMLInMessage = generateChannel({ + messages: [ + generateMessage({ + attachments: [generateImageAttachment()], + text: + '

Hello, world!

\n' + + '

This is my first web page.

\n' + + '

It contains a main heading and paragraph .

', + }), + ], + }); + + const expectedTextWithHTMLRendering = + '

Hello, world!

This is my first web page.

It contains a main heading and paragraph .

'; + + function isReactMarkdownElement(x) { + return React.isValidElement(x) && x.type === ReactMarkdown; + } it.each([ ['Nothing yet...', 'channelWithEmptyMessage', channelWithEmptyMessage], ['Message deleted', 'channelWithDeletedMessage', channelWithDeletedMessage], ['🏙 Attachment...', 'channelWithAttachmentMessage', channelWithAttachmentMessage], ['📍Shared location', 'channelWithLocationMessage', channelWithLocationMessage], + [ + expectedTextWithHTMLRendering, + 'channelWithHTMLInMessage', + channelWithHTMLInMessage, + ], ])('should return %s for %s', async (expectedValue, testCaseName, c) => { const t = (text) => text; const channel = await getQueriedChannelInstance(c); - expect(getLatestMessagePreview(channel, t)).toBe(expectedValue); + const preview = getLatestMessagePreview(channel, t); + if (isReactMarkdownElement(preview)) { + const { container } = render(preview); + expect(container).toHaveTextContent(expectedValue); + } else { + expect(getLatestMessagePreview(channel, t)).toBe(expectedValue); + } }); }); diff --git a/src/components/ChannelPreview/utils.tsx b/src/components/ChannelPreview/utils.tsx index bf39b94528..1a3e09c488 100644 --- a/src/components/ChannelPreview/utils.tsx +++ b/src/components/ChannelPreview/utils.tsx @@ -5,9 +5,19 @@ import type { Channel, PollVote, TranslationLanguages, UserResponse } from 'stre import type { TranslationContextValue } from '../../context/TranslationContext'; import type { ChatContextValue } from '../../context'; +import type { PluggableList } from 'unified'; +import { htmlToTextPlugin } from '../Message'; +import remarkGfm from 'remark-gfm'; + +const remarkPlugins: PluggableList = [ + htmlToTextPlugin, + [remarkGfm, { singleTilde: false }], +]; export const renderPreviewText = (text: string) => ( - {text} + + {text} + ); const getLatestPollVote = (latestVotesByOption: Record) => {