[MM-53556] Fix crash when you are added to a group that's not in state (#24196)

* fix webapp crashing when you get added to a group
Этот коммит содержится в:
Ben Cooke
2023-08-15 11:03:44 -04:00
коммит произвёл GitHub
родитель faea229921
Коммит f64e6174e2
2 изменённых файлов: 82 добавлений и 11 удалений

Просмотреть файл

@@ -35,6 +35,7 @@ import {loadRolesIfNeeded} from 'mattermost-redux/actions/roles';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getNewestThreadInTeam, getThread, getThreads} from 'mattermost-redux/selectors/entities/threads'; import {getNewestThreadInTeam, getThread, getThreads} from 'mattermost-redux/selectors/entities/threads';
import {getGroup} from 'mattermost-redux/selectors/entities/groups';
import { import {
getThread as fetchThread, getThread as fetchThread,
getCountsAndThreadsSince, getCountsAndThreadsSince,
@@ -65,6 +66,7 @@ import {
checkForModifiedUsers, checkForModifiedUsers,
getUser as loadUser, getUser as loadUser,
} from 'mattermost-redux/actions/users'; } from 'mattermost-redux/actions/users';
import {getGroup as fetchGroup} from 'mattermost-redux/actions/groups';
import {removeNotVisibleUsers} from 'mattermost-redux/actions/websocket'; import {removeNotVisibleUsers} from 'mattermost-redux/actions/websocket';
import {setGlobalItem} from 'actions/storage'; import {setGlobalItem} from 'actions/storage';
import {setGlobalDraft, transformServerDraft} from 'actions/views/drafts'; import {setGlobalDraft, transformServerDraft} from 'actions/views/drafts';
@@ -1355,20 +1357,32 @@ function handleGroupUpdatedEvent(msg) {
); );
} }
function handleGroupAddedMemberEvent(msg) { export function handleGroupAddedMemberEvent(msg) {
return (doDispatch, doGetState) => { return async (doDispatch, doGetState) => {
const state = doGetState(); const state = doGetState();
const currentUserId = getCurrentUserId(state); const currentUserId = getCurrentUserId(state);
const data = JSON.parse(msg.data.group_member); const groupInfo = JSON.parse(msg.data.group_member);
if (currentUserId === data.user_id) { if (currentUserId === groupInfo.user_id) {
dispatch( const group = getGroup(state, groupInfo.group_id);
{ if (group) {
type: GroupTypes.ADD_MY_GROUP, dispatch(
data, {
id: data.group_id, type: GroupTypes.ADD_MY_GROUP,
}, id: groupInfo.group_id,
); },
);
} else {
const {error} = await doDispatch(fetchGroup(groupInfo.group_id, true));
if (!error) {
dispatch(
{
type: GroupTypes.ADD_MY_GROUP,
id: groupInfo.group_id,
},
);
}
}
} }
}; };
} }

Просмотреть файл

@@ -6,6 +6,7 @@ import {
getThreadsForPosts, getThreadsForPosts,
receivedNewPost, receivedNewPost,
} from 'mattermost-redux/actions/posts'; } from 'mattermost-redux/actions/posts';
import {getGroup} from 'mattermost-redux/actions/groups';
import {ChannelTypes, UserTypes, CloudTypes} from 'mattermost-redux/action_types'; import {ChannelTypes, UserTypes, CloudTypes} from 'mattermost-redux/action_types';
import {getUser} from 'mattermost-redux/actions/users'; import {getUser} from 'mattermost-redux/actions/users';
@@ -37,6 +38,7 @@ import {
handleAppsPluginEnabled, handleAppsPluginEnabled,
handleAppsPluginDisabled, handleAppsPluginDisabled,
handleCloudSubscriptionChanged, handleCloudSubscriptionChanged,
handleGroupAddedMemberEvent,
} from './websocket_actions'; } from './websocket_actions';
jest.mock('mattermost-redux/actions/posts', () => ({ jest.mock('mattermost-redux/actions/posts', () => ({
@@ -45,6 +47,11 @@ jest.mock('mattermost-redux/actions/posts', () => ({
getProfilesAndStatusesForPosts: jest.fn(), getProfilesAndStatusesForPosts: jest.fn(),
})); }));
jest.mock('mattermost-redux/actions/groups', () => ({
...jest.requireActual('mattermost-redux/actions/groups'),
getGroup: jest.fn(() => ({type: 'RECEIVED_GROUP'})),
}));
jest.mock('mattermost-redux/actions/users', () => ({ jest.mock('mattermost-redux/actions/users', () => ({
getMissingProfilesByIds: jest.fn(() => ({type: 'GET_MISSING_PROFILES_BY_IDS'})), getMissingProfilesByIds: jest.fn(() => ({type: 'GET_MISSING_PROFILES_BY_IDS'})),
getStatusesByIds: jest.fn(() => ({type: 'GET_STATUSES_BY_IDS'})), getStatusesByIds: jest.fn(() => ({type: 'GET_STATUSES_BY_IDS'})),
@@ -105,6 +112,20 @@ let mockState = {
PluginsEnabled: 'true', PluginsEnabled: 'true',
}, },
}, },
groups: {
syncables: {},
groups: {
'group-1': {
id: 'group-1',
name: 'group1',
display_name: 'Group 1',
member_count: 1,
allow_reference: true,
},
},
stats: {},
myGroups: {},
},
channels: { channels: {
currentChannelId: 'otherChannel', currentChannelId: 'otherChannel',
channels: { channels: {
@@ -202,6 +223,42 @@ describe('handlePostEditEvent', () => {
}); });
}); });
describe('handleGroupAddedMemberEvent', () => {
test('add to group in state', async () => {
const testStore = configureStore(mockState);
const msg = {
data: {
group_member: '{"group_id":"group-1","user_id":"currentUserId","create_at":1691178673417,"delete_at":0}',
},
broadcast: {
user_id: 'currentUserId',
},
};
testStore.dispatch(handleGroupAddedMemberEvent(msg));
expect(store.dispatch).toHaveBeenCalledWith({
type: 'ADD_MY_GROUP',
id: 'group-1',
});
});
test('add to group not in state', async () => {
const testStore = configureStore(mockState);
const msg = {
data: {
group_member: '{"group_id":"group-2","user_id":"currentUserId","create_at":1691178673417,"delete_at":0}',
},
broadcast: {
user_id: 'currentUserId',
},
};
testStore.dispatch(handleGroupAddedMemberEvent(msg));
expect(getGroup).toHaveBeenCalled();
expect(testStore.getActions()).toEqual([{type: 'RECEIVED_GROUP'}]);
});
});
describe('handlePostUnreadEvent', () => { describe('handlePostUnreadEvent', () => {
test('post marked as unred', async () => { test('post marked as unred', async () => {
const msgData = {last_viewed_at: 123, msg_count: 40, mention_count: 1}; const msgData = {last_viewed_at: 123, msg_count: 40, mention_count: 1};