fix(MM-60645): missing bookmark emoji (#8518)

* fix(MM-60645): missing bookmark emoji
* add test
This commit is contained in:
Rahim Rahman 2025-01-27 11:01:08 -07:00 committed by GitHub
parent 167d8a37b9
commit 11022322d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 129 additions and 3 deletions

View file

@ -0,0 +1,117 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {act, renderWithIntl} from '@test/intl-test-helper';
import BookmarkIcon from './bookmark_icon';
jest.mock('@context/theme', () => ({
useTheme: () => ({
centerChannelColor: '#000',
}),
}));
jest.mock('@components/emoji', () => 'Emoji');
describe('components/channel_bookmarks/channel_bookmark/BookmarkIcon', () => {
const baseProps = {
emojiSize: 24,
iconSize: 22,
genericStyle: {},
};
it('renders default bookmark icon when no specific content provided', () => {
const {getByTestId} = renderWithIntl(
<BookmarkIcon {...baseProps}/>,
);
expect(getByTestId('bookmark-generic-icon')).toBeOnTheScreen();
});
it('renders FileIcon when file prop is provided', () => {
const props = {
...baseProps,
file: {
id: 'file1',
name: 'test.pdf',
extension: 'pdf',
} as unknown as FileInfo,
};
const {getByTestId} = renderWithIntl(
<BookmarkIcon {...props}/>,
);
expect(getByTestId('bookmark-file-icon')).toBeOnTheScreen();
});
it('renders Image when imageUrl is provided', () => {
const props = {
...baseProps,
imageUrl: 'https://example.com/image.jpg',
imageStyle: {width: 40, height: 40},
};
const {getByTestId} = renderWithIntl(
<BookmarkIcon {...props}/>,
);
expect(getByTestId('bookmark-image')).toBeOnTheScreen();
});
it('renders Emoji when emoji prop is provided', () => {
const props = {
...baseProps,
emoji: 'smile',
emojiStyle: {fontSize: 20},
};
const {getByTestId} = renderWithIntl(
<BookmarkIcon {...props}/>,
);
const emojiComponent = getByTestId('bookmark-emoji');
expect(emojiComponent).toBeOnTheScreen();
expect(emojiComponent.props.emojiName).toBe('smile');
});
it('renders Emoji when emoji prop with `:` is provided', () => {
const props = {
...baseProps,
emoji: ':computer-rage:',
emojiStyle: {fontSize: 20},
};
const {getByTestId} = renderWithIntl(
<BookmarkIcon {...props}/>,
);
const emojiComponent = getByTestId('bookmark-emoji');
expect(emojiComponent).toBeOnTheScreen();
expect(emojiComponent.props.emojiName).toBe('computer-rage');
});
it('falls back to default icon when image fails to load', () => {
const props = {
...baseProps,
imageUrl: 'https://example.com/invalid.jpg',
};
const {getByTestId} = renderWithIntl(
<BookmarkIcon {...props}/>,
);
const image = getByTestId('bookmark-image');
const mockErrorEvent = {
nativeEvent: {
error: new Error('Image failed to load'),
},
};
act(() => {
image.props.onError(mockErrorEvent);
});
expect(getByTestId('bookmark-generic-icon')).toBeOnTheScreen();
});
});

View file

@ -32,6 +32,7 @@ const BookmarkIcon = ({emoji, emojiSize, emojiStyle, file, genericStyle, iconSiz
if (file && !emoji && !hasImageError) {
return (
<FileIcon
testID='bookmark-file-icon'
file={file}
iconSize={iconSize}
smallImage={true}
@ -40,15 +41,18 @@ const BookmarkIcon = ({emoji, emojiSize, emojiStyle, file, genericStyle, iconSiz
} else if (imageUrl && !emoji && !hasImageError) {
return (
<Image
testID='bookmark-image'
source={{uri: imageUrl}}
style={imageStyle}
onError={handleImageError}
/>
);
} else if (emoji) {
const sanitizedEmoji = emoji.replace(/:/g, '');
return (
<Emoji
emojiName={emoji!}
testID='bookmark-emoji'
emojiName={sanitizedEmoji}
size={emojiSize}
textStyle={emojiStyle}
/>
@ -61,6 +65,7 @@ const BookmarkIcon = ({emoji, emojiSize, emojiStyle, file, genericStyle, iconSiz
size={22}
color={theme.centerChannelColor}
style={genericStyle}
testID='bookmark-generic-icon'
/>
);
};

View file

@ -16,6 +16,7 @@ type FileIconProps = {
iconColor?: string;
iconSize?: number;
smallImage?: boolean;
testID?: string;
}
const BLUE_ICON = '#338AFF';
@ -49,7 +50,7 @@ const styles = StyleSheet.create({
const FileIcon = ({
backgroundColor, defaultImage = false, failed = false, file,
iconColor, iconSize = 48, smallImage = false,
iconColor, iconSize = 48, smallImage = false, testID = 'file-icon',
}: FileIconProps) => {
const theme = useTheme();
const getFileIconNameAndColor = () => {
@ -78,7 +79,10 @@ const FileIcon = ({
const bgColor = backgroundColor || theme?.centerChannelBg || 'transparent';
return (
<View style={[styles.fileIconWrapper, {backgroundColor: bgColor}]}>
<View
style={[styles.fileIconWrapper, {backgroundColor: bgColor}]}
testID={testID}
>
<CompassIcon
name={iconName}
size={iconSize}