From 1b54e1ebe3f4505b25074eee35ccfc72216b37d2 Mon Sep 17 00:00:00 2001 From: Sudheer Date: Mon, 15 Oct 2018 21:00:11 +0530 Subject: [PATCH] Fix for LHS populating you next to current user (#2263) * Fix for LHS populating you next to current user * Add test cases * Refactor to use avaiable props conditions in component instead of passing flags from connector --- .../__snapshots__/channel_item.test.js.snap | 597 ++++++++++++++---- .../channel_item/channel_item.js | 35 +- .../channel_item/channel_item.test.js | 149 ++++- .../main/channels_list/channel_item/index.js | 10 +- test/setup.js | 4 + 5 files changed, 642 insertions(+), 153 deletions(-) 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 d15d5a495..cafe69d88 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 @@ -94,14 +94,356 @@ exports[`ChannelItem should match snapshot 1`] = ` }, ] } - /> + > + display_name + `; -exports[`ChannelItem should match snapshot for deactivated user 1`] = `null`; +exports[`ChannelItem should match snapshot for current user i.e currentUser (you) 1`] = ` + + + + + + + + {displayName} (you) + + + + + +`; + +exports[`ChannelItem should match snapshot for current user i.e currentUser (you) when isSearchResult 1`] = ` + + + + + + + + {displayName} (you) + + + + + +`; + +exports[`ChannelItem should match snapshot for deactivated user and is currentChannel 1`] = ` + + + + + + + + display_name + + + + + +`; exports[`ChannelItem should match snapshot for deactivated user and is searchResult 1`] = ` @@ -197,126 +539,20 @@ exports[`ChannelItem should match snapshot for deactivated user and is searchRes }, ] } - /> + > + display_name + `; -exports[`ChannelItem should match snapshot if channel is archived 1`] = `null`; +exports[`ChannelItem should match snapshot for deactivated user and not searchResults or currentChannel 1`] = `null`; -exports[`ChannelItem should match snapshot if channel is archived and is currentChannel 1`] = ` - - - - - - - - - - - -`; +exports[`ChannelItem should match snapshot for no displayName 1`] = `null`; + +exports[`ChannelItem should match snapshot for showUnreadForMsgs 1`] = `null`; exports[`ChannelItem should match snapshot with draft 1`] = ` @@ -412,6 +648,137 @@ exports[`ChannelItem should match snapshot with draft 1`] = ` }, ] } + > + display_name + + + + + +`; + +exports[`ChannelItem should match snapshot with mentions and muted 1`] = ` + + + + + + + display_name + + 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 64a4c7558..edc3f6b5d 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 @@ -2,6 +2,8 @@ // See LICENSE.txt for license information. import React, {PureComponent} from 'react'; +import {General} from 'mattermost-redux/constants'; + import PropTypes from 'prop-types'; import { Animated, @@ -22,11 +24,11 @@ const {View: AnimatedView} = Animated; export default class ChannelItem extends PureComponent { static propTypes = { channelId: PropTypes.string.isRequired, + channel: PropTypes.object, currentChannelId: PropTypes.string.isRequired, displayName: PropTypes.string.isRequired, - fake: PropTypes.bool, isChannelMuted: PropTypes.bool, - isMyUser: PropTypes.bool, + currentUserId: PropTypes.string.isRequired, isUnread: PropTypes.bool, hasDraft: PropTypes.bool, mentions: PropTypes.number.isRequired, @@ -34,11 +36,8 @@ export default class ChannelItem extends PureComponent { onSelectChannel: PropTypes.func.isRequired, shouldHideChannel: PropTypes.bool, showUnreadForMsgs: PropTypes.bool.isRequired, - status: PropTypes.string, - type: PropTypes.string.isRequired, theme: PropTypes.object.isRequired, unreadMsgs: PropTypes.number.isRequired, - isArchived: PropTypes.bool.isRequired, isSearchResult: PropTypes.bool, }; @@ -51,7 +50,8 @@ export default class ChannelItem extends PureComponent { }; onPress = preventDoubleTap(() => { - const {channelId, currentChannelId, displayName, fake, onSelectChannel, type} = this.props; + const {channelId, currentChannelId, displayName, onSelectChannel, channel} = this.props; + const {type, fake} = channel; requestAnimationFrame(() => { onSelectChannel({id: channelId, display_name: displayName, fake, type}, currentChannelId); }); @@ -91,18 +91,18 @@ export default class ChannelItem extends PureComponent { currentChannelId, displayName, isChannelMuted, - isMyUser, + currentUserId, isUnread, hasDraft, mentions, shouldHideChannel, - status, theme, - type, - isArchived, isSearchResult, + channel, } = this.props; + const isArchived = channel.delete_at > 0; + // Only ever show an archived channel if it's the currently viewed channel. // It should disappear as soon as one navigates to another channel. if (isArchived && (currentChannelId !== channelId) && !isSearchResult) { @@ -120,7 +120,16 @@ export default class ChannelItem extends PureComponent { const {intl} = this.context; let channelDisplayName = displayName; - if (isMyUser) { + let isCurrenUser = false; + + if (channel.type === General.DM_CHANNEL) { + if (isSearchResult) { + isCurrenUser = channel.id === currentUserId; + } else { + isCurrenUser = channel.teammate_id === currentUserId; + } + } + if (isCurrenUser) { channelDisplayName = intl.formatMessage({ id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)', @@ -172,9 +181,9 @@ export default class ChannelItem extends PureComponent { hasDraft={hasDraft && channelId !== currentChannelId} membersCount={displayName.split(',').length} size={16} - status={status} + status={channel.status} theme={theme} - type={type} + type={channel.type} isArchived={isArchived} /> ); 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 ba7d445ce..a073e88b4 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 @@ -3,21 +3,31 @@ import React from 'react'; import {shallow} from 'enzyme'; +import {TouchableHighlight} from 'react-native'; import Preferences from 'mattermost-redux/constants/preferences'; import ChannelItem from './channel_item.js'; +jest.useFakeTimers(); jest.mock('react-intl'); describe('ChannelItem', () => { + const channel = { + id: 'channel_id', + delete_at: 0, + type: 'O', + fake: false, + status: 'online', + }; + const baseProps = { channelId: 'channel_id', + channel, currentChannelId: 'current_channel_id', displayName: 'display_name', - fake: false, isChannelMuted: false, - isMyUser: true, + currentUserId: 'currentUser', isUnread: true, hasDraft: false, mentions: 0, @@ -25,11 +35,9 @@ describe('ChannelItem', () => { onSelectChannel: () => {}, // eslint-disable-line no-empty-function shouldHideChannel: false, showUnreadForMsgs: true, - status: 'online', - type: 'O', theme: Preferences.THEMES.default, unreadMsgs: 1, - isArchived: false, + isSearchResult: false, }; test('should match snapshot', () => { @@ -41,12 +49,33 @@ describe('ChannelItem', () => { expect(wrapper.getElement()).toMatchSnapshot(); }); - test('should match snapshot for deactivated user', () => { + test('should match snapshot with mentions and muted', () => { const newProps = { ...baseProps, - type: 'D', - isArchived: true, + mentions: 1, + isChannelMuted: true, }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should match snapshot for deactivated user and not searchResults or currentChannel', () => { + const channelObj = { + ...channel, + type: 'D', + delete_at: 123, + }; + + const newProps = { + ...baseProps, + channel: channelObj, + }; + const wrapper = shallow( , {context: {intl: {formatMessage: jest.fn()}}}, @@ -55,12 +84,18 @@ describe('ChannelItem', () => { }); test('should match snapshot for deactivated user and is searchResult', () => { + const channelObj = { + ...channel, + type: 'D', + delete_at: 123, + }; + const newProps = { ...baseProps, - type: 'D', - isArchived: true, isSearchResult: true, + channel: channelObj, }; + const wrapper = shallow( , {context: {intl: {formatMessage: jest.fn()}}}, @@ -68,6 +103,81 @@ describe('ChannelItem', () => { expect(wrapper.getElement()).toMatchSnapshot(); }); + test('should match snapshot for deactivated user and is currentChannel', () => { + const channelObj = { + ...channel, + type: 'D', + delete_at: 123, + }; + + const newProps = { + ...baseProps, + channel: channelObj, + currentChannelId: 'channel_id', + }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should match snapshot for no displayName', () => { + const newProps = { + ...baseProps, + displayName: '', + }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: jest.fn()}}}, + ); + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should match snapshot for current user i.e currentUser (you)', () => { + const channelObj = { + ...channel, + type: 'D', + teammate_id: 'currentUser', + }; + + const newProps = { + ...baseProps, + channel: channelObj, + currentChannelId: 'channel_id', + }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: (intlId) => intlId.defaultMessage}}}, + ); + expect(wrapper.getElement()).toMatchSnapshot(); + }); + + test('should match snapshot for current user i.e currentUser (you) when isSearchResult', () => { + const channelObj = { + ...channel, + id: 'currentUser', + type: 'D', + teammate_id: 'somethingElse', + }; + + const newProps = { + ...baseProps, + channel: channelObj, + currentChannelId: 'channel_id', + isSearchResult: true, + }; + + const wrapper = shallow( + , + {context: {intl: {formatMessage: (intlId) => intlId.defaultMessage}}}, + ); + expect(wrapper.getElement()).toMatchSnapshot(); + }); + test('should match snapshot with draft', () => { const wrapper = shallow( { expect(wrapper.getElement()).toMatchSnapshot(); }); - test('should match snapshot if channel is archived', () => { + test('should match snapshot for showUnreadForMsgs', () => { const wrapper = shallow( , {context: {intl: {formatMessage: jest.fn()}}}, ); @@ -92,16 +204,21 @@ describe('ChannelItem', () => { expect(wrapper.getElement()).toMatchSnapshot(); }); - test('should match snapshot if channel is archived and is currentChannel', () => { + test('Should call onPress', () => { + const onSelectChannel = jest.fn(); + const wrapper = shallow( , {context: {intl: {formatMessage: jest.fn()}}}, ); - expect(wrapper.getElement()).toMatchSnapshot(); + wrapper.find(TouchableHighlight).simulate('press'); + jest.runAllTimers(); + + const expectedChannelParams = {id: baseProps.channelId, display_name: baseProps.displayName, fake: channel.fake, type: channel.type}; + expect(onSelectChannel).toHaveBeenCalledWith(expectedChannelParams, baseProps.currentChannelId); }); }); 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 9a2d0ea90..3c381669d 100644 --- a/app/components/sidebars/main/channels_list/channel_item/index.js +++ b/app/components/sidebars/main/channels_list/channel_item/index.js @@ -28,13 +28,9 @@ function makeMapStateToProps() { const currentUserId = getCurrentUserId(state); const channelDraft = getDraftForChannel(state, channel.id); - let isMyUser = false; let displayName = channel.display_name; - const isArchived = channel.delete_at > 0; if (channel.type === General.DM_CHANNEL) { - isMyUser = channel.id === currentUserId; - if (!ownProps.isSearchResult) { const teammate = getUser(state, channel.teammate_id); const teammateNameDisplay = getTeammateNameDisplaySetting(state); @@ -69,18 +65,14 @@ function makeMapStateToProps() { channel, currentChannelId, displayName, - fake: channel.fake, isChannelMuted: isChannelMuted(member), - isMyUser, + currentUserId, hasDraft: Boolean(channelDraft.draft.trim() || channelDraft.files.length), mentions: member ? member.mention_count : 0, shouldHideChannel, showUnreadForMsgs, - status: channel.status, theme: getTheme(state), - type: channel.type, unreadMsgs, - isArchived, }; }; } diff --git a/test/setup.js b/test/setup.js index 8c416b1dd..c5543cfa2 100644 --- a/test/setup.js +++ b/test/setup.js @@ -67,3 +67,7 @@ jest.mock('rn-fetch-blob/fs', () => ({ CacheDir: () => jest.fn(), }, })); + +global.requestAnimationFrame = (callback) => { + setTimeout(callback, 0); +};