diff --git a/app/components/autocomplete/at_mention_item/at_mention_item.js b/app/components/autocomplete/at_mention_item/at_mention_item.js
index d0d630425..63c1f40dd 100644
--- a/app/components/autocomplete/at_mention_item/at_mention_item.js
+++ b/app/components/autocomplete/at_mention_item/at_mention_item.js
@@ -10,6 +10,7 @@ import {
} from 'react-native';
import ProfilePicture from 'app/components/profile_picture';
+import BotTag from 'app/components/bot_tag';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
export default class AtMentionItem extends PureComponent {
@@ -19,6 +20,7 @@ export default class AtMentionItem extends PureComponent {
onPress: PropTypes.func.isRequired,
userId: PropTypes.string.isRequired,
username: PropTypes.string,
+ isBot: PropTypes.bool,
theme: PropTypes.object.isRequired,
};
@@ -34,6 +36,7 @@ export default class AtMentionItem extends PureComponent {
userId,
username,
theme,
+ isBot,
} = this.props;
const style = getStyleFromTheme(theme);
@@ -54,6 +57,10 @@ export default class AtMentionItem extends PureComponent {
/>
{`@${username}`}
+
{hasFullName && {' - '}}
{hasFullName && {`${firstName} ${lastName}`}}
diff --git a/app/components/autocomplete/at_mention_item/index.js b/app/components/autocomplete/at_mention_item/index.js
index 1d7c70c78..355d7dce2 100644
--- a/app/components/autocomplete/at_mention_item/index.js
+++ b/app/components/autocomplete/at_mention_item/index.js
@@ -16,6 +16,7 @@ function mapStateToProps(state, ownProps) {
firstName: user.first_name,
lastName: user.last_name,
username: user.username,
+ isBot: Boolean(user.is_bot),
theme: getTheme(state),
};
}
diff --git a/app/components/autocomplete/channel_mention_item/channel_mention_item.js b/app/components/autocomplete/channel_mention_item/channel_mention_item.js
index 6bdfcc7f7..867b14d5f 100644
--- a/app/components/autocomplete/channel_mention_item/channel_mention_item.js
+++ b/app/components/autocomplete/channel_mention_item/channel_mention_item.js
@@ -9,6 +9,7 @@ import {
} from 'react-native';
import {General} from 'mattermost-redux/constants';
+import BotTag from 'app/components/bot_tag';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
@@ -18,6 +19,7 @@ export default class ChannelMentionItem extends PureComponent {
displayName: PropTypes.string,
name: PropTypes.string,
type: PropTypes.string,
+ isBot: PropTypes.bool.isRequired,
onPress: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
};
@@ -38,6 +40,7 @@ export default class ChannelMentionItem extends PureComponent {
name,
theme,
type,
+ isBot,
} = this.props;
const style = getStyleFromTheme(theme);
@@ -53,6 +56,10 @@ export default class ChannelMentionItem extends PureComponent {
style={style.row}
>
{'@' + displayName}
+
);
}
diff --git a/app/components/autocomplete/channel_mention_item/index.js b/app/components/autocomplete/channel_mention_item/index.js
index 30b590167..a1b57f86a 100644
--- a/app/components/autocomplete/channel_mention_item/index.js
+++ b/app/components/autocomplete/channel_mention_item/index.js
@@ -3,6 +3,8 @@
import {connect} from 'react-redux';
+import {General} from 'mattermost-redux/constants';
+
import {getChannel} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
@@ -11,14 +13,25 @@ import {getChannelNameForSearchAutocomplete} from 'app/selectors/channel';
import ChannelMentionItem from './channel_mention_item';
+import {getUser} from 'mattermost-redux/selectors/entities/users';
+
function mapStateToProps(state, ownProps) {
const channel = getChannel(state, ownProps.channelId);
const displayName = getChannelNameForSearchAutocomplete(state, ownProps.channelId);
+ let isBot = false;
+ if (channel.type === General.DM_CHANNEL) {
+ const teammate = getUser(state, channel.teammate_id);
+ if (teammate && teammate.is_bot) {
+ isBot = true;
+ }
+ }
+
return {
displayName,
name: channel.name,
type: channel.type,
+ isBot,
theme: getTheme(state),
};
}
diff --git a/app/components/bot_tag.js b/app/components/bot_tag.js
new file mode 100644
index 000000000..84ad5062a
--- /dev/null
+++ b/app/components/bot_tag.js
@@ -0,0 +1,50 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React, {PureComponent} from 'react';
+import PropTypes from 'prop-types';
+import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
+import FormattedText from 'app/components/formatted_text';
+
+export default class BotTag extends PureComponent {
+ static defaultProps = {
+ show: true,
+ };
+
+ static propTypes = {
+ show: PropTypes.bool,
+ theme: PropTypes.object.isRequired,
+ };
+
+ render() {
+ if (!this.props.show) {
+ return null;
+ }
+ const style = createStyleSheet(this.props.theme);
+
+ return (
+
+ );
+ }
+}
+
+const createStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ bot: {
+ alignSelf: 'center',
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.15),
+ borderRadius: 2,
+ color: theme.centerChannelColor,
+ fontSize: 10,
+ fontWeight: '600',
+ marginRight: 5,
+ marginLeft: 5,
+ paddingVertical: 2,
+ paddingHorizontal: 4,
+ },
+ };
+});
diff --git a/app/components/channel_icon.js b/app/components/channel_icon.js
index f448f557b..9a2422ae2 100644
--- a/app/components/channel_icon.js
+++ b/app/components/channel_icon.js
@@ -8,7 +8,7 @@ import {
Text,
View,
} from 'react-native';
-import Icon from 'react-native-vector-icons/FontAwesome';
+import Icon from 'react-native-vector-icons/FontAwesome5';
import {General} from 'mattermost-redux/constants';
@@ -26,6 +26,7 @@ export default class ChannelIcon extends React.PureComponent {
theme: PropTypes.object.isRequired,
type: PropTypes.string.isRequired,
isArchived: PropTypes.bool.isRequired,
+ isBot: PropTypes.bool.isRequired,
};
static defaultProps = {
@@ -47,6 +48,7 @@ export default class ChannelIcon extends React.PureComponent {
theme,
type,
isArchived,
+ isBot,
} = this.props;
const style = getStyleSheet(theme);
@@ -85,6 +87,13 @@ export default class ChannelIcon extends React.PureComponent {
style={[style.icon, unreadIcon, activeIcon, {fontSize: size}]}
/>
);
+ } else if (isBot) {
+ icon = (
+
+ );
} else if (hasDraft) {
icon = (
{
iconInfo: {
color: theme.centerChannelColor,
},
+ iconBot: {
+ marginLeft: -5,
+ },
groupBox: {
alignSelf: 'flex-start',
alignItems: 'center',
diff --git a/app/components/channel_intro/channel_intro.js b/app/components/channel_intro/channel_intro.js
index 80ad62ed3..b852ccbe0 100644
--- a/app/components/channel_intro/channel_intro.js
+++ b/app/components/channel_intro/channel_intro.js
@@ -14,6 +14,7 @@ import {General} from 'mattermost-redux/constants';
import {injectIntl, intlShape} from 'react-intl';
import ProfilePicture from 'app/components/profile_picture';
+import BotTag from 'app/components/bot_tag';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {t} from 'app/utils/i18n';
@@ -91,16 +92,24 @@ class ChannelIntro extends PureComponent {
const {currentChannelMembers, theme} = this.props;
const style = getStyleSheet(theme);
- return currentChannelMembers.map((member, index) => (
- this.goToUserProfile(member.id))}
- >
-
- {index === currentChannelMembers.length - 1 ? this.getDisplayName(member) : `${this.getDisplayName(member)}, `}
-
-
- ));
+ return currentChannelMembers.map((member, index) => {
+ return (
+ this.goToUserProfile(member.id))}
+ >
+
+
+ {index === currentChannelMembers.length - 1 ? this.getDisplayName(member) : `${this.getDisplayName(member)}, `}
+
+
+
+
+ );
+ });
};
buildDMContent = () => {
@@ -382,6 +391,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
flexWrap: 'wrap',
justifyContent: 'flex-start',
},
+ indicatorContainer: {
+ flexDirection: 'row',
+ },
};
});
diff --git a/app/components/custom_list/user_list_row/__snapshots__/user_list_test.test.js.snap b/app/components/custom_list/user_list_row/__snapshots__/user_list_test.test.js.snap
index 583e4a898..da2d83785 100644
--- a/app/components/custom_list/user_list_row/__snapshots__/user_list_test.test.js.snap
+++ b/app/components/custom_list/user_list_row/__snapshots__/user_list_test.test.js.snap
@@ -41,18 +41,57 @@ exports[`UserListRow should match snapshot 1`] = `
}
>
-
- @user
-
+
+ @user
+
+
+
@@ -100,16 +139,55 @@ exports[`UserListRow should match snapshot for currentUser with (you) populated
}
>
-
+ >
+
+
+
@@ -157,18 +235,57 @@ exports[`UserListRow should match snapshot for deactivated user 1`] = `
}
>
-
- @user
-
+
+ @user
+
+
+
-
- {usernameDisplay}
-
+
+
+ {usernameDisplay}
+
+
+
{showTeammateDisplay &&
@@ -140,6 +147,9 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
fontSize: 15,
color: theme.centerChannelColor,
},
+ indicatorContainer: {
+ flexDirection: 'row',
+ },
deactivated: {
marginTop: 2,
fontSize: 12,
diff --git a/app/components/post_header/index.js b/app/components/post_header/index.js
index 3f852b2a5..fcc84fc9f 100644
--- a/app/components/post_header/index.js
+++ b/app/components/post_header/index.js
@@ -44,6 +44,7 @@ function makeMapStateToProps() {
overrideUsername: post?.props?.override_username, // eslint-disable-line camelcase
theme: getTheme(state),
username: user.username,
+ isBot: user.is_bot || false,
userTimezone,
};
};
diff --git a/app/components/post_header/post_header.js b/app/components/post_header/post_header.js
index a4a90ff11..f5bde134e 100644
--- a/app/components/post_header/post_header.js
+++ b/app/components/post_header/post_header.js
@@ -14,6 +14,7 @@ import FormattedText from 'app/components/formatted_text';
import FormattedTime from 'app/components/formatted_time';
import FormattedDate from 'app/components/formatted_date';
import ReplyIcon from 'app/components/reply_icon';
+import BotTag from 'app/components/bot_tag';
import {emptyFunction} from 'app/utils/general';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
@@ -38,6 +39,7 @@ export default class PostHeader extends PureComponent {
showFullDate: PropTypes.bool,
theme: PropTypes.object.isRequired,
username: PropTypes.string,
+ isBot: PropTypes.bool,
userTimezone: PropTypes.string,
enableTimezone: PropTypes.bool,
};
@@ -61,6 +63,7 @@ export default class PostHeader extends PureComponent {
isSystemMessage,
fromAutoResponder,
overrideUsername,
+ isBot,
} = this.props;
if (fromWebHook) {
@@ -74,13 +77,24 @@ export default class PostHeader extends PureComponent {
{name}
-
);
+ } else if (isBot) {
+ return (
+
+
+
+ {this.props.displayName}
+
+
+
+
+ );
} else if (fromAutoResponder) {
let name = this.props.displayName;
if (overrideUsername && enablePostUsernameOverride) {
@@ -291,17 +305,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
indicatorContainer: {
flexDirection: 'row',
},
- bot: {
- alignSelf: 'center',
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.15),
- borderRadius: 2,
- color: theme.centerChannelColor,
- fontSize: 10,
- fontWeight: '600',
- marginRight: 5,
- paddingVertical: 2,
- paddingHorizontal: 4,
- },
displayName: {
color: theme.centerChannelColor,
fontSize: 15,
diff --git a/app/components/profile_picture/profile_picture.js b/app/components/profile_picture/profile_picture.js
index a079c89da..61a20bcbc 100644
--- a/app/components/profile_picture/profile_picture.js
+++ b/app/components/profile_picture/profile_picture.js
@@ -111,7 +111,7 @@ export default class ProfilePicture extends PureComponent {
}
render() {
- const {edit, showStatus, theme} = this.props;
+ const {edit, showStatus, theme, user} = this.props;
const {pictureUrl} = this.state;
const style = getStyleSheet(theme);
@@ -172,7 +172,7 @@ export default class ProfilePicture extends PureComponent {
return (
{image}
- {(showStatus || edit) &&
+ {(showStatus || edit) && (user && !user.is_bot) &&
{statusIcon}
diff --git a/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap b/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
index 874631f9e..c413377ea 100644
--- a/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
+++ b/app/components/sidebars/main/channels_list/channel_item/__snapshots__/channel_item.test.js.snap
@@ -39,6 +39,7 @@ exports[`ChannelItem should match snapshot 1`] = `
hasDraft={false}
isActive={false}
isArchived={false}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
@@ -153,6 +154,7 @@ exports[`ChannelItem should match snapshot for current user i.e currentUser (you
hasDraft={false}
isActive={true}
isArchived={false}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
@@ -267,6 +269,7 @@ exports[`ChannelItem should match snapshot for current user i.e currentUser (you
hasDraft={false}
isActive={true}
isArchived={false}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
@@ -381,6 +384,7 @@ exports[`ChannelItem should match snapshot for deactivated user and is currentCh
hasDraft={false}
isActive={true}
isArchived={true}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
@@ -484,6 +488,7 @@ exports[`ChannelItem should match snapshot for deactivated user and is searchRes
hasDraft={false}
isActive={false}
isArchived={true}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
@@ -593,6 +598,7 @@ exports[`ChannelItem should match snapshot with draft 1`] = `
hasDraft={true}
isActive={false}
isArchived={false}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
@@ -698,6 +704,7 @@ exports[`ChannelItem should match snapshot with mentions and muted 1`] = `
hasDraft={false}
isActive={false}
isArchived={false}
+ isBot={false}
isInfo={false}
isUnread={true}
membersCount={1}
diff --git a/app/components/sidebars/main/channels_list/channel_item/channel_item.js b/app/components/sidebars/main/channels_list/channel_item/channel_item.js
index ff7c9c71c..b82c91845 100644
--- a/app/components/sidebars/main/channels_list/channel_item/channel_item.js
+++ b/app/components/sidebars/main/channels_list/channel_item/channel_item.js
@@ -39,6 +39,7 @@ export default class ChannelItem extends PureComponent {
theme: PropTypes.object.isRequired,
unreadMsgs: PropTypes.number.isRequired,
isSearchResult: PropTypes.bool,
+ isBot: PropTypes.bool.isRequired,
};
static defaultProps = {
@@ -99,6 +100,7 @@ export default class ChannelItem extends PureComponent {
theme,
isSearchResult,
channel,
+ isBot,
} = this.props;
const isArchived = channel.delete_at > 0;
@@ -183,6 +185,7 @@ export default class ChannelItem extends PureComponent {
theme={theme}
type={channel.type}
isArchived={isArchived}
+ isBot={isBot}
/>
);
diff --git a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
index a073e88b4..8774c4614 100644
--- a/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
+++ b/app/components/sidebars/main/channels_list/channel_item/channel_item.test.js
@@ -38,6 +38,7 @@ describe('ChannelItem', () => {
theme: Preferences.THEMES.default,
unreadMsgs: 1,
isSearchResult: false,
+ isBot: false,
};
test('should match snapshot', () => {
diff --git a/app/components/sidebars/main/channels_list/channel_item/index.js b/app/components/sidebars/main/channels_list/channel_item/index.js
index 3c381669d..d2f748c98 100644
--- a/app/components/sidebars/main/channels_list/channel_item/index.js
+++ b/app/components/sidebars/main/channels_list/channel_item/index.js
@@ -12,7 +12,7 @@ import {
} from 'mattermost-redux/selectors/entities/channels';
import {getTheme, getTeammateNameDisplaySetting} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId, getUser} from 'mattermost-redux/selectors/entities/users';
-import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
+import {getUserIdFromChannelName, isChannelMuted} from 'mattermost-redux/utils/channel_utils';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
import {getDraftForChannel} from 'app/selectors/views';
@@ -29,12 +29,19 @@ function makeMapStateToProps() {
const channelDraft = getDraftForChannel(state, channel.id);
let displayName = channel.display_name;
+ let isBot = false;
if (channel.type === General.DM_CHANNEL) {
- if (!ownProps.isSearchResult) {
- const teammate = getUser(state, channel.teammate_id);
+ if (ownProps.isSearchResult) {
+ isBot = channel.isBot;
+ } else {
+ const teammateId = getUserIdFromChannelName(currentUserId, channel.name);
+ const teammate = getUser(state, teammateId);
const teammateNameDisplay = getTeammateNameDisplaySetting(state);
displayName = displayUsername(teammate, teammateNameDisplay, false);
+ if (teammate && teammate.is_bot) {
+ isBot = true;
+ }
}
}
@@ -73,6 +80,7 @@ function makeMapStateToProps() {
showUnreadForMsgs,
theme: getTheme(state),
unreadMsgs,
+ isBot,
};
};
}
diff --git a/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js b/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js
index e2966e46e..9006deee2 100644
--- a/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js
+++ b/app/components/sidebars/main/channels_list/filtered_list/filtered_list.js
@@ -218,6 +218,7 @@ class FilteredList extends Component {
nickname: u.nickname,
fullname: `${u.first_name} ${u.last_name}`,
delete_at: u.delete_at,
+ isBot: u.is_bot,
// need name key for DM's as we use it for sortChannelsByDisplayName with same display_name
name: displayName,
@@ -263,6 +264,7 @@ class FilteredList extends Component {
nickname: u.nickname,
fullname: `${u.first_name} ${u.last_name}`,
delete_at: u.delete_at,
+ isBot: u.is_bot,
};
});
diff --git a/app/screens/channel_info/channel_info.js b/app/screens/channel_info/channel_info.js
index a6ed97a98..ed90a3226 100644
--- a/app/screens/channel_info/channel_info.js
+++ b/app/screens/channel_info/channel_info.js
@@ -58,6 +58,7 @@ export default class ChannelInfo extends PureComponent {
canManageUsers: PropTypes.bool.isRequired,
canEditChannel: PropTypes.bool.isRequired,
ignoreChannelMentions: PropTypes.bool.isRequired,
+ isBot: PropTypes.bool.isRequired,
};
static contextTypes = {
@@ -510,6 +511,7 @@ export default class ChannelInfo extends PureComponent {
navigator,
status,
theme,
+ isBot,
} = this.props;
const style = getStyleSheet(theme);
@@ -548,6 +550,7 @@ export default class ChannelInfo extends PureComponent {
theme={theme}
type={currentChannel.type}
isArchived={currentChannel.delete_at !== 0}
+ isBot={isBot}
/>
}
diff --git a/app/screens/channel_info/channel_info_header.js b/app/screens/channel_info/channel_info_header.js
index 2cc7f9472..237680e04 100644
--- a/app/screens/channel_info/channel_info_header.js
+++ b/app/screens/channel_info/channel_info_header.js
@@ -29,6 +29,7 @@ export default class ChannelInfoHeader extends React.PureComponent {
theme: PropTypes.object.isRequired,
type: PropTypes.string.isRequired,
isArchived: PropTypes.bool.isRequired,
+ isBot: PropTypes.bool.isRequired,
};
render() {
@@ -45,6 +46,7 @@ export default class ChannelInfoHeader extends React.PureComponent {
theme,
type,
isArchived,
+ isBot,
} = this.props;
const style = getStyleSheet(theme);
@@ -62,6 +64,7 @@ export default class ChannelInfoHeader extends React.PureComponent {
theme={theme}
type={type}
isArchived={isArchived}
+ isBot={isBot}
/>
+
+
+ fred
+
+
+
- @undefined
+ @fred
+
+
+ USERNAME
+
+
+ fred
+
+
{
const {navigator, theme} = this.props;
@@ -78,7 +87,17 @@ export default class UserProfile extends PureComponent {
const displayName = displayUsername(user, teammateNameDisplay);
if (displayName) {
- return {displayName};
+ return (
+
+
+ {displayName}
+
+
+
+ );
}
return null;
@@ -198,8 +217,34 @@ export default class UserProfile extends PureComponent {
return additionalOptions;
};
+ renderDetailsBlock = (style) => {
+ if (this.props.user.is_bot) {
+ if (!this.props.bot) {
+ return null;
+ }
+ return (
+
+
+ {'DESCRIPTION'}
+ {this.props.bot.description || ''}
+
+
+ );
+ }
+
+ return (
+
+ {this.props.enableTimezone && this.buildTimezoneBlock()}
+ {this.buildDisplayBlock('username')}
+ {this.props.config.ShowEmailAddress === 'true' && this.buildDisplayBlock('email')}
+ {this.buildDisplayBlock('nickname')}
+ {this.buildDisplayBlock('position')}
+
+ );
+ }
+
render() {
- const {config, theme, user, enableTimezone} = this.props;
+ const {theme, user} = this.props;
const style = createStyleSheet(theme);
if (!user) {
@@ -222,13 +267,7 @@ export default class UserProfile extends PureComponent {
{this.getDisplayName()}
{`@${user.username}`}
-
- {enableTimezone && this.buildTimezoneBlock()}
- {this.buildDisplayBlock('username')}
- {config.ShowEmailAddress === 'true' && this.buildDisplayBlock('email')}
- {this.buildDisplayBlock('nickname')}
- {this.buildDisplayBlock('position')}
-
+ {this.renderDetailsBlock(style)}
{
marginHorizontal: 15,
},
displayName: {
- marginTop: 15,
color: theme.centerChannelColor,
fontSize: 17,
fontWeight: '600',
@@ -284,6 +322,10 @@ const createStyleSheet = makeStyleSheetFromTheme((theme) => {
color: theme.centerChannelColor,
fontSize: 15,
},
+ indicatorContainer: {
+ marginTop: 15,
+ flexDirection: 'row',
+ },
};
});
diff --git a/app/screens/user_profile/user_profile.test.js b/app/screens/user_profile/user_profile.test.js
index c1b5a551a..6b61fe051 100644
--- a/app/screens/user_profile/user_profile.test.js
+++ b/app/screens/user_profile/user_profile.test.js
@@ -6,6 +6,7 @@ import {shallow} from 'enzyme';
import Preferences from 'mattermost-redux/constants/preferences';
import UserProfile from './user_profile.js';
+import BotTag from 'app/components/bot_tag';
jest.mock('react-intl');
jest.mock('app/utils/theme', () => {
@@ -20,6 +21,7 @@ describe('user_profile', () => {
const actions = {
setChannelDisplayName: jest.fn(),
makeDirectChannel: jest.fn(),
+ loadBot: jest.fn(),
};
const baseProps = {
actions,
@@ -33,21 +35,53 @@ describe('user_profile', () => {
teams: [],
theme: Preferences.THEMES.default,
enableTimezone: false,
- user: {
+ militaryTime: false,
+ };
+
+ const user = {
+ email: 'test@test.com',
+ first_name: 'test',
+ id: '4hzdnk6mg7gepe7yze6m3domnc',
+ last_name: 'fake',
+ nickname: 'nick',
+ username: 'fred',
+ is_bot: false,
+ };
+
+ test('should match snapshot', async () => {
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage: jest.fn()}}},
+ );
+ expect(wrapper.getElement()).toMatchSnapshot();
+ });
+
+ test('should contain bot tag', async () => {
+ const botUser = {
email: 'test@test.com',
first_name: 'test',
id: '4hzdnk6mg7gepe7yze6m3domnc',
last_name: 'fake',
nickname: 'nick',
- },
- militaryTime: false,
- };
+ username: 'fred',
+ is_bot: true,
+ };
- test('should match snapshot', async () => {
const wrapper = shallow(
- ,
+ ,
{context: {intl: {formatMessage: jest.fn()}}},
);
- expect(wrapper.getElement()).toMatchSnapshot();
+ expect(wrapper.containsMatchingElement(
+
+ )).toEqual(true);
});
});
diff --git a/package-lock.json b/package-lock.json
index 7fb98652a..d5411d304 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2688,6 +2688,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"dev": true,
+ "optional": true,
"requires": {
"is-extendable": "^0.1.0"
}
@@ -2732,7 +2733,8 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"is-glob": {
"version": "4.0.0",
@@ -4359,7 +4361,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -4377,11 +4380,13 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4394,15 +4399,18 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -4505,7 +4513,8 @@
},
"inherits": {
"version": "2.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -4515,6 +4524,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -4527,17 +4537,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -4554,6 +4567,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -4626,7 +4640,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -4636,6 +4651,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -4711,7 +4727,8 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -4741,6 +4758,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -4758,6 +4776,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -4796,11 +4815,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
},
@@ -12338,7 +12359,8 @@
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"braces": {
"version": "2.3.2",
@@ -12624,7 +12646,8 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"micromatch": {
"version": "3.1.10",
diff --git a/package.json b/package.json
index 672edd94a..58339b76d 100644
--- a/package.json
+++ b/package.json
@@ -109,7 +109,8 @@
"postinstall": "make post-install",
"test": "jest --forceExit --detectOpenHandles",
"test:watch": "jest --watch",
- "test:coverage": "jest --coverage"
+ "test:coverage": "jest --coverage",
+ "updatesnapshot": "jest --updateSnapshot"
},
"rnpm": {
"assets": [