diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/admin_channel_shared_indicator.test.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/admin_channel_shared_indicator.test.tsx new file mode 100644 index 00000000000..42749dd1f33 --- /dev/null +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/admin_channel_shared_indicator.test.tsx @@ -0,0 +1,73 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; + +import {renderWithContext} from 'tests/react_testing_utils'; + +import AdminChannelSharedIndicator from './admin_channel_shared_indicator'; + +jest.mock('mattermost-redux/actions/shared_channels', () => ({ + fetchChannelRemotes: jest.fn(() => ({type: 'MOCK_FETCH_CHANNEL_REMOTES'})), +})); + +jest.mock('mattermost-redux/selectors/entities/shared_channels', () => ({ + getRemoteNamesForChannel: jest.fn(() => [] as string[]), +})); + +jest.mock('components/shared_channel_indicator', () => { + return jest.fn(() => ); +}); + +describe('admin_console/team_channel_settings/channel/list/AdminChannelSharedIndicator', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('fetches remotes on mount when remoteNames is empty', () => { + const {getRemoteNamesForChannel} = require('mattermost-redux/selectors/entities/shared_channels'); + const {fetchChannelRemotes} = require('mattermost-redux/actions/shared_channels'); + getRemoteNamesForChannel.mockReturnValue([]); + + renderWithContext(); + + expect(fetchChannelRemotes).toHaveBeenCalledTimes(1); + expect(fetchChannelRemotes).toHaveBeenCalledWith('channel-1'); + }); + + test('does not fetch remotes when remoteNames is already populated', () => { + const {getRemoteNamesForChannel} = require('mattermost-redux/selectors/entities/shared_channels'); + const {fetchChannelRemotes} = require('mattermost-redux/actions/shared_channels'); + getRemoteNamesForChannel.mockReturnValue(['Org A', 'Org B']); + + renderWithContext(); + + expect(fetchChannelRemotes).not.toHaveBeenCalled(); + }); + + test('passes remoteNames from the selector to SharedChannelIndicator', () => { + const {getRemoteNamesForChannel} = require('mattermost-redux/selectors/entities/shared_channels'); + const SharedChannelIndicator = require('components/shared_channel_indicator'); + getRemoteNamesForChannel.mockReturnValue(['Org A', 'Org B']); + + renderWithContext(); + + const props = SharedChannelIndicator.mock.calls[0][0]; + expect(props.remoteNames).toEqual(['Org A', 'Org B']); + expect(props.withTooltip).toBe(true); + }); + + test('forwards the className prop to SharedChannelIndicator', () => { + const SharedChannelIndicator = require('components/shared_channel_indicator'); + + renderWithContext( + , + ); + + const props = SharedChannelIndicator.mock.calls[0][0]; + expect(props.className).toBe('channel-icon'); + }); +}); diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/admin_channel_shared_indicator.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/admin_channel_shared_indicator.tsx new file mode 100644 index 00000000000..e4d4f08cec9 --- /dev/null +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/admin_channel_shared_indicator.tsx @@ -0,0 +1,41 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React, {useEffect} from 'react'; +import {shallowEqual, useDispatch, useSelector} from 'react-redux'; + +import {fetchChannelRemotes} from 'mattermost-redux/actions/shared_channels'; +import {getRemoteNamesForChannel} from 'mattermost-redux/selectors/entities/shared_channels'; + +import SharedChannelIndicator from 'components/shared_channel_indicator'; + +import type {GlobalState} from 'types/store'; + +type Props = { + channelId: string; + className?: string; +}; + +const AdminChannelSharedIndicator: React.FC = ({channelId, className}) => { + const dispatch = useDispatch(); + const remoteNames = useSelector( + (state: GlobalState) => getRemoteNamesForChannel(state, channelId), + shallowEqual, + ); + + useEffect(() => { + if (channelId && remoteNames.length === 0) { + dispatch(fetchChannelRemotes(channelId)); + } + }, [channelId, remoteNames.length, dispatch]); + + return ( + + ); +}; + +export default AdminChannelSharedIndicator; diff --git a/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/channel_list.tsx b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/channel_list.tsx index 75c35004f24..aa8e3b51bff 100644 --- a/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/channel_list.tsx +++ b/webapp/channels/src/components/admin_console/team_channel_settings/channel/list/channel_list.tsx @@ -15,11 +15,12 @@ import type {Row, Column} from 'components/admin_console/data_grid/data_grid'; import type {FilterOptions} from 'components/admin_console/filter/filter'; import TeamFilterDropdown from 'components/admin_console/filter/team_filter_dropdown'; import {PAGE_SIZE} from 'components/admin_console/team_channel_settings/abstract_list'; -import SharedChannelIndicator from 'components/shared_channel_indicator'; import {getHistory} from 'utils/browser_history'; import {getChannelIconComponent} from 'utils/channel_utils'; +import AdminChannelSharedIndicator from './admin_channel_shared_indicator'; + import './channel_list.scss'; export interface ChannelListProps { @@ -195,9 +196,9 @@ export default class ChannelList extends React.PureComponent ) : null;