diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index b34899a73..b8da9b1a1 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -249,9 +249,9 @@ export function handleSelectChannelByName(channelName, teamName, errorHandler) { if (!myMemberships[channel.id]) { const currentUserId = getCurrentUserId(state); console.log('joining channel', channel?.display_name, channel.id); //eslint-disable-line - const result = await dispatch(joinChannel(currentUserId, teamName, channel.id)); + const result = await dispatch(joinChannel(currentUserId, '', channel.id)); if (result.error || !result.data || !result.data.channel) { - return {error}; + return result; } } } diff --git a/app/actions/views/channel.test.js b/app/actions/views/channel.test.js index 0f013651f..e5b2a6373 100644 --- a/app/actions/views/channel.test.js +++ b/app/actions/views/channel.test.js @@ -11,6 +11,7 @@ import {ViewTypes} from '@constants'; import {ChannelTypes} from '@mm-redux/action_types'; import postReducer from '@mm-redux/reducers/entities/posts'; import initialState from '@store/initial_state'; +import {General} from '@mm-redux/constants'; const { handleSelectChannel, @@ -67,6 +68,10 @@ describe('Actions.Views.Channel', () => { type: MOCK_SELECT_CHANNEL_TYPE, data: 'selected-channel-id', }); + actions.joinChannel = jest.fn((userId, teamId, channelId) => ({ + type: 'MOCK_JOIN_CHANNEL', + data: {channel: {id: channelId}}, + })); const postActions = require('./post'); postActions.getPostsSince = jest.fn(() => { return { @@ -205,6 +210,28 @@ describe('Actions.Views.Channel', () => { expect(receivedChannel).toBe(false); }); + test('handleSelectChannelByName select channel that user is not a member of', async () => { + actions.getChannelByNameAndTeamName = jest.fn(() => { + return { + type: MOCK_RECEIVE_CHANNEL_TYPE, + data: {id: 'channel-id-3', name: 'channel-id-3', display_name: 'Test Channel', type: General.OPEN_CHANNEL}, + }; + }); + + store = mockStore(storeObj); + + await store.dispatch(handleSelectChannelByName('channel-id-3', currentTeamName)); + + const storeActions = store.getActions(); + const receivedChannel = storeActions.some((action) => action.type === MOCK_RECEIVE_CHANNEL_TYPE); + expect(receivedChannel).toBe(true); + + expect(actions.joinChannel).toBeCalled(); + + const joinedChannel = storeActions.some((action) => action.type === 'MOCK_JOIN_CHANNEL' && action.data.channel.id === 'channel-id-3'); + expect(joinedChannel).toBe(true); + }); + test('loadPostsIfNecessaryWithRetry for the first time', async () => { store = mockStore(storeObj); diff --git a/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js b/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js new file mode 100644 index 000000000..cd683e379 --- /dev/null +++ b/detox/e2e/test/messaging/tapping_channel_url_link_joins_channel.e2e.js @@ -0,0 +1,65 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +// ******************************************************************* +// - [#] indicates a test step (e.g. # Go to a screen) +// - [*] indicates an assertion (e.g. * Check the title) +// - Use element testID when selecting an element. Create one if none. +// ******************************************************************* + +import {MainSidebar} from '@support/ui/component'; +import {ChannelScreen} from '@support/ui/screen'; + +import {Setup, Team, User} from '@support/server_api'; +import {serverUrl} from '@support/test_config'; + +describe('Messaging', () => { + let testChannel; + let testTeam; + + beforeAll(async () => { + const {channel, team, user} = await Setup.apiInit(); + testChannel = channel; + testTeam = team; + + await ChannelScreen.open(user); + }); + + it('MM-T3471 Tapping channel URL link joins public channel', async () => { + // # Go to the Town Square channel + const {channelNavBarTitle} = ChannelScreen; + await ChannelScreen.openMainSidebar(); + let channelItem = MainSidebar.getChannelByDisplayName('Town Square'); + await channelItem.tap(); + await expect(channelNavBarTitle).toHaveText('Town Square'); + + // # There's no way to get a channel permalink on mobile so we make one + // manually + const channelPermalink = `${serverUrl}/${testTeam.name}/channels/${testChannel.name}`; + + // # Post the channel permalink to the test channel in Town Square + const {postInput} = ChannelScreen; + await expect(postInput).toBeVisible(); + await postInput.tap(); + await postInput.typeText(channelPermalink); + await ChannelScreen.tapSendButton(); + await expect(element(by.text(channelPermalink))).toBeVisible(); + + // # Create another user in the same team, log in and go to town square + const {user: otherUser} = await User.apiCreateUser({prefix: 'TestUser'}); + await Team.apiAddUserToTeam(otherUser.id, testTeam.id); + await ChannelScreen.logout(); + await ChannelScreen.open(otherUser); + await ChannelScreen.openMainSidebar(); + channelItem = MainSidebar.getChannelByDisplayName('Town Square'); + await channelItem.tap(); + await expect(channelNavBarTitle).toHaveText('Town Square'); + + // # As this new user, tap the channel permalink we posted earlier + const permalinkPost = element(by.text(channelPermalink)); + await permalinkPost.tap({x: 5, y: 10}); + + // * Confirm that we have joined the correct channel from the channel permalink + await expect(channelNavBarTitle).toHaveText(testChannel.display_name); + }); +});