MM-28338 Fix Combined system messages (#22608)

* Web App -> Monorepo

* Update message data

* update snapshots

* update tests

* update tests, add null filter for userIds.

* Revert "update snapshots"

This reverts commit 4b3f5b192d.

* Remove not related tests

* Update post_list

* Update test (removing usernames for UserIds)

* Update webapp/channels/src/packages/mattermost-redux/src/utils/post_list.ts

better readability.

Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com>

* remove unnecessary tests.

---------

Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Safouen Turki 2023-05-04 16:09:27 +01:00 committed by GitHub
parent 670b0e4c9f
commit fefca512c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 455 additions and 747 deletions

View File

@ -147,10 +147,10 @@ exports[`components/post_view/CombinedSystemMessage should match snapshot, "remo
</Fragment> </Fragment>
`; `;
exports[`components/post_view/CombinedSystemMessage should match snapshot, combining users removed from channel by all actors 1`] = ` exports[`components/post_view/CombinedSystemMessage should render messages in chronological order 1`] = `
<Fragment> <Fragment>
<Connect(Markdown) <Connect(Markdown)
message="@removed_username_1 and @removed_username_2 were **removed from the channel**." message="@removed_username_1 was **removed from the channel**."
options={ options={
Object { Object {
"atMentions": true, "atMentions": true,
@ -159,64 +159,9 @@ exports[`components/post_view/CombinedSystemMessage should match snapshot, combi
Object { Object {
"key": "@removed_username_1", "key": "@removed_username_1",
}, },
Object {
"key": "@removed_username_2",
},
Object {
"key": "you",
},
],
"singleline": true,
}
}
/>
<br />
</Fragment>
`;
exports[`components/post_view/CombinedSystemMessage should match snapshot, when current user is removed from then rejoined the channel 1`] = `
<Fragment>
<Connect(Markdown)
message="You **joined the channel**."
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "You",
},
Object { Object {
"key": undefined, "key": undefined,
}, },
Object {
"key": "",
},
],
"singleline": true,
}
}
/>
<br />
<injectIntl(LastUsers)
actor="you"
expandedLocale={
Object {
"defaultMessage": "{users} and {lastUser} were **removed from the channel**.",
"id": "combined_system_message.removed_from_channel.many_expanded",
}
}
formatOptions={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "You",
},
Object {
"key": "@removed_username_1",
},
Object { Object {
"key": "you", "key": "you",
}, },
@ -224,13 +169,93 @@ exports[`components/post_view/CombinedSystemMessage should match snapshot, when
"singleline": true, "singleline": true,
} }
} }
postType="system_remove_from_channel" />
usernames={ <br />
Array [ <Connect(Markdown)
"You", message="@removed_username_2 **added to the channel** by Someone."
"@removed_username_1", options={
"@removed_username_2", Object {
] "atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "@removed_username_2",
},
Object {
"key": undefined,
},
Object {
"key": "Someone",
},
],
"singleline": true,
}
}
/>
<br />
<Connect(Markdown)
message="@removed_username_2 was **removed from the channel**."
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "@removed_username_2",
},
Object {
"key": undefined,
},
Object {
"key": "Someone",
},
],
"singleline": true,
}
}
/>
<br />
<Connect(Markdown)
message="@User2 **added to the channel** by @User1."
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "@User2",
},
Object {
"key": undefined,
},
Object {
"key": "@User1",
},
],
"singleline": true,
}
}
/>
<br />
<Connect(Markdown)
message="Someone **joined the channel**."
options={
Object {
"atMentions": true,
"mentionHighlight": false,
"mentionKeys": Array [
Object {
"key": "Someone",
},
Object {
"key": undefined,
},
Object {
"key": "Someone",
},
],
"singleline": true,
}
} }
/> />
<br /> <br />

View File

@ -61,25 +61,6 @@ describe('components/post_view/CombinedSystemMessage', () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot, combining users removed from channel by all actors', () => {
const allUserIds = ['current_user_id', 'other_user_id_1', 'removed_user_id_1', 'removed_user_id_2'];
const messageData = [{
actorId: 'current_user_id',
postType: Posts.POST_TYPES.REMOVE_FROM_CHANNEL,
userIds: ['removed_user_id_1'],
}, {
actorId: 'other_user_id_1',
postType: Posts.POST_TYPES.REMOVE_FROM_CHANNEL,
userIds: ['removed_user_id_2'],
}];
const props = {...baseProps, messageData, allUserIds};
const wrapper = shallowWithIntl(
<CombinedSystemMessage {...props}/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot when join leave messages are turned off', () => { test('should match snapshot when join leave messages are turned off', () => {
const wrapper = shallowWithIntl( const wrapper = shallowWithIntl(
<CombinedSystemMessage <CombinedSystemMessage
@ -110,29 +91,6 @@ describe('components/post_view/CombinedSystemMessage', () => {
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot, when current user is removed from then rejoined the channel', () => {
const allUserIds = ['current_user_id', 'other_user_id_1', 'removed_user_id_1', 'removed_user_id_2'];
const messageData = [{
actorId: '',
postType: Posts.POST_TYPES.JOIN_CHANNEL,
userIds: ['current_user_id'],
}, {
actorId: 'current_user_id',
postType: Posts.POST_TYPES.REMOVE_FROM_CHANNEL,
userIds: ['removed_user_id_1', 'removed_user_id_2'],
}, {
actorId: 'other_user_id_1',
postType: Posts.POST_TYPES.REMOVE_FROM_CHANNEL,
userIds: ['removed_user_id_2', 'current_user_id'],
}];
const props = {...baseProps, messageData, allUserIds};
const wrapper = shallowWithIntl(
<CombinedSystemMessage {...props}/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should call getMissingProfilesByIds and/or getMissingProfilesByUsernames on loadUserProfiles', () => { test('should call getMissingProfilesByIds and/or getMissingProfilesByUsernames on loadUserProfiles', () => {
const props = { const props = {
...baseProps, ...baseProps,
@ -164,4 +122,34 @@ describe('components/post_view/CombinedSystemMessage', () => {
expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledTimes(1); expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledTimes(1);
expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledWith(['user1']); expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledWith(['user1']);
}); });
test('should render messages in chronological order', () => {
const allUserIds = ['current_user_id', 'other_user_id_1', 'user_id_1', 'user_id_2', 'join_last'];
const messageData = [{
actorId: 'current_user_id',
postType: Posts.POST_TYPES.REMOVE_FROM_CHANNEL,
userIds: ['removed_user_id_1'],
}, {
actorId: 'other_user_id_1',
postType: Posts.POST_TYPES.ADD_TO_CHANNEL,
userIds: ['removed_user_id_2'],
}, {
actorId: 'other_user_id_1',
postType: Posts.POST_TYPES.REMOVE_FROM_CHANNEL,
userIds: ['removed_user_id_2'],
}, {
actorId: 'user_id_1',
postType: Posts.POST_TYPES.ADD_TO_CHANNEL,
userIds: ['user_id_2'],
}, {
actorId: 'join_last',
postType: Posts.POST_TYPES.JOIN_CHANNEL,
userIds: [''],
}];
const props = {...baseProps, messageData, allUserIds};
const wrapper = shallowWithIntl(
<CombinedSystemMessage {...props}/>,
);
expect(wrapper).toMatchSnapshot();
});
}); });

View File

@ -238,30 +238,32 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {
return usernames; return usernames;
}; };
getUsernamesByIds = (userIds: string[] = []): string[] => { getUsernamesByIds = (userIds: string | string[] = []): string[] => {
const userIdsArray = Array.isArray(userIds) ? userIds : [userIds];
const {currentUserId, currentUsername} = this.props; const {currentUserId, currentUsername} = this.props;
const allUsernames = this.getAllUsernames(); const allUsernames = this.getAllUsernames();
const {formatMessage} = this.props.intl; const {formatMessage} = this.props.intl;
const someone = formatMessage({id: t('channel_loader.someone'), defaultMessage: 'Someone'}); const someone = formatMessage({id: t('channel_loader.someone'), defaultMessage: 'Someone'});
const usernames = userIds. const usernames = userIdsArray.
filter((userId) => { filter((userId) => {
return userId !== currentUserId && userId !== currentUsername; return userId !== currentUserId && userId !== currentUsername;
}). }).
map((userId) => { map((userId) => {
return allUsernames[userId] ? `@${allUsernames[userId]}` : someone; return allUsernames[userId] ? `@${allUsernames[userId]}` : someone;
}).filter((username) => { }).
filter((username) => {
return username && username !== ''; return username && username !== '';
}); });
if (userIds.includes(currentUserId)) { if (userIdsArray.includes(currentUserId)) {
usernames.unshift(allUsernames[currentUserId]); usernames.unshift(allUsernames[currentUserId]);
} else if (userIds.includes(currentUsername)) { } else if (userIdsArray.includes(currentUsername)) {
usernames.unshift(allUsernames[currentUsername]); usernames.unshift(allUsernames[currentUsername]);
} }
return usernames; return Array.from(new Set(usernames));
}; };
renderFormattedMessage(postType: string, userIds: string[], actorId?: string): JSX.Element { renderFormattedMessage(postType: string, userIds: string[], actorId?: string): JSX.Element {
@ -328,7 +330,6 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {
</React.Fragment> </React.Fragment>
); );
} }
render(): JSX.Element { render(): JSX.Element {
const { const {
currentUserId, currentUserId,
@ -336,7 +337,6 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {
} = this.props; } = this.props;
const content = []; const content = [];
const removedUserIds = [];
for (const message of messageData) { for (const message of messageData) {
const { const {
postType, postType,
@ -356,19 +356,9 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {
} }
} }
if (postType === REMOVE_FROM_CHANNEL) {
removedUserIds.push(...userIds);
continue;
}
content.push(this.renderMessage(postType, userIds, actorId)); content.push(this.renderMessage(postType, userIds, actorId));
} }
if (removedUserIds.length > 0) {
const uniqueRemovedUserIds = removedUserIds.filter((id, index, arr) => arr.indexOf(id) === index);
content.push(this.renderMessage(REMOVE_FROM_CHANNEL, uniqueRemovedUserIds, currentUserId));
}
return ( return (
<React.Fragment> <React.Fragment>
{content} {content}

View File

@ -2,7 +2,7 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {GlobalState} from '@mattermost/types/store'; import {GlobalState} from '@mattermost/types/store';
import {Post} from '@mattermost/types/posts'; import {ActivityEntry, Post} from '@mattermost/types/posts';
import deepFreeze from 'mattermost-redux/utils/deep_freeze'; import deepFreeze from 'mattermost-redux/utils/deep_freeze';
import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils'; import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
import {Posts, Preferences} from '../constants'; import {Posts, Preferences} from '../constants';
@ -11,7 +11,6 @@ import TestHelper from '../../test/test_helper';
import { import {
COMBINED_USER_ACTIVITY, COMBINED_USER_ACTIVITY,
combineUserActivitySystemPost, combineUserActivitySystemPost,
comparePostTypes,
DATE_LINE, DATE_LINE,
getDateForDateLine, getDateForDateLine,
getFirstPostId, getFirstPostId,
@ -23,7 +22,7 @@ import {
makeCombineUserActivityPosts, makeCombineUserActivityPosts,
makeFilterPostsAndAddSeparators, makeFilterPostsAndAddSeparators,
makeGenerateCombinedPost, makeGenerateCombinedPost,
postTypePriority, extractUserActivityData,
START_OF_NEW_MESSAGES, START_OF_NEW_MESSAGES,
} from './post_list'; } from './post_list';
@ -1014,8 +1013,11 @@ describe('makeGenerateCombinedPost', () => {
'bill joined the channel.', 'bill joined the channel.',
], ],
user_activity: { user_activity: {
allUserIds: ['user2', 'user3', 'user1'], allUserIds: ['user1', 'user3', 'user2'],
allUsernames: [], allUsernames: [
'alice',
'joe',
],
messageData: [ messageData: [
{ {
postType: Posts.POST_TYPES.JOIN_CHANNEL, postType: Posts.POST_TYPES.JOIN_CHANNEL,
@ -1023,18 +1025,18 @@ describe('makeGenerateCombinedPost', () => {
}, },
{ {
postType: Posts.POST_TYPES.ADD_TO_CHANNEL, postType: Posts.POST_TYPES.ADD_TO_CHANNEL,
userIds: ['user2', 'user3'], userIds: ['user3', 'user2'],
actorId: 'user1', actorId: 'user1',
}, },
], ],
}, },
}, },
system_post_ids: ['post1', 'post2', 'post3'], system_post_ids: ['post3', 'post2', 'post1'],
type: Posts.POST_TYPES.COMBINED_USER_ACTIVITY, type: Posts.POST_TYPES.COMBINED_USER_ACTIVITY,
user_activity_posts: [ user_activity_posts: [
state.entities.posts.posts.post1,
state.entities.posts.posts.post2,
state.entities.posts.posts.post3, state.entities.posts.posts.post3,
state.entities.posts.posts.post2,
state.entities.posts.posts.post1,
], ],
user_id: '', user_id: '',
metadata: {}, metadata: {},
@ -1109,7 +1111,7 @@ describe('makeGenerateCombinedPost', () => {
}; };
generateCombinedPost(state, initialCombinedId); generateCombinedPost(state, initialCombinedId);
expect((generateCombinedPost as any).recomputations()).toBe(1); expect((generateCombinedPost as any).recomputations()).toBe(2);
}); });
test('should recalculate when one of the included posts change', () => { test('should recalculate when one of the included posts change', () => {
@ -1141,574 +1143,332 @@ describe('makeGenerateCombinedPost', () => {
}); });
}); });
}); });
const PostTypes = Posts.POST_TYPES;
describe('extractUserActivityData', () => {
const postAddToChannel: ActivityEntry = {
postType: PostTypes.ADD_TO_CHANNEL,
actorId: ['user_id_1'],
userIds: ['added_user_id_1'],
usernames: ['added_username_1'],
};
const postAddToTeam: ActivityEntry = {
postType: PostTypes.ADD_TO_TEAM,
actorId: ['user_id_1'],
userIds: ['added_user_id_1', 'added_user_id_2'],
usernames: ['added_username_1', 'added_username_2'],
};
const postLeaveChannel: ActivityEntry = {
postType: PostTypes.LEAVE_CHANNEL,
actorId: ['user_id_1'],
userIds: [],
usernames: [],
};
describe('combineUserActivitySystemPost', () => { const postJoinChannel: ActivityEntry = {
const PostTypes = Posts.POST_TYPES; postType: PostTypes.JOIN_CHANNEL,
actorId: ['user_id_1'],
userIds: [],
usernames: [],
};
it('should return null', () => { const postRemoveFromChannel: ActivityEntry = {
expect(Boolean(combineUserActivitySystemPost())).toBe(false); postType: PostTypes.REMOVE_FROM_CHANNEL,
expect(Boolean(combineUserActivitySystemPost([]))).toBe(false); actorId: ['user_id_1'],
userIds: ['removed_user_id_1'],
usernames: ['removed_username_1'],
};
const postLeaveTeam: ActivityEntry = {
postType: PostTypes.LEAVE_TEAM,
actorId: ['user_id_1'],
userIds: [],
usernames: [],
};
const postJoinTeam: ActivityEntry = {
postType: PostTypes.JOIN_TEAM,
actorId: ['user_id_1'],
userIds: [],
usernames: [],
};
const postRemoveFromTeam: ActivityEntry = {
postType: PostTypes.REMOVE_FROM_TEAM,
actorId: ['user_id_1'],
userIds: [],
usernames: [],
};
it('should return empty activity when empty ', () => {
expect(extractUserActivityData([])).toEqual({allUserIds: [], allUsernames: [], messageData: []});
}); });
const postAddToChannel1 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_1', addedUsername: 'added_username_1'}});
const postAddToChannel2 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_2', addedUsername: 'added_username_2'}});
const postAddToChannel3 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_3', addedUsername: 'added_username_3'}});
const postAddToChannel4 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_2', props: {addedUserId: 'added_user_id_4', addedUsername: 'added_username_4'}});
const postAddToChannel5 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_1', props: {addedUsername: 'added_username_1'}});
it('should match return for ADD_TO_CHANNEL', () => {
const out1 = {
allUserIds: ['added_user_id_1', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1']}],
};
expect(combineUserActivitySystemPost([postAddToChannel1])).toEqual(out1);
const out2 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2']}],
};
expect(combineUserActivitySystemPost([postAddToChannel1, postAddToChannel2])).toEqual(out2);
const out3 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']}],
};
expect(combineUserActivitySystemPost([postAddToChannel1, postAddToChannel2, postAddToChannel3])).toEqual(out3);
const out4 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1', 'added_user_id_4', 'user_id_2'],
allUsernames: [],
messageData: [
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_4']},
],
};
expect(combineUserActivitySystemPost([postAddToChannel1, postAddToChannel2, postAddToChannel3, postAddToChannel4])).toEqual(out4);
const out5 = {
allUserIds: ['user_id_1'],
allUsernames: ['added_username_1'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_username_1']}],
};
expect(combineUserActivitySystemPost([postAddToChannel5])).toEqual(out5);
const out6 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1', 'added_user_id_4', 'user_id_2'],
allUsernames: ['added_username_1'],
messageData: [
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_username_1', 'added_user_id_1', 'added_user_id_2', 'added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_4']},
],
};
expect(combineUserActivitySystemPost([postAddToChannel1, postAddToChannel2, postAddToChannel3, postAddToChannel4, postAddToChannel5])).toEqual(out6);
});
it('should match return for ADD_TO_CHANNEL, backward compatibility with addedUsername', () => {
const out1 = {
allUserIds: ['user_id_1'],
allUsernames: ['added_user_name_1'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_name_1']}],
};
expect(combineUserActivitySystemPost([{...postAddToChannel1, props: {addedUsername: 'added_user_name_1'}}])).toEqual(out1);
const out2 = {
allUserIds: ['added_user_id_2', 'user_id_1'],
allUsernames: ['added_user_name_1'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_name_1', 'added_user_id_2']}],
};
expect(combineUserActivitySystemPost([{...postAddToChannel1, props: {addedUsername: 'added_user_name_1'}}, postAddToChannel2])).toEqual(out2);
const out3 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1', 'user_id_2'],
allUsernames: ['added_user_name_4'],
messageData: [
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_name_4']},
],
};
expect(combineUserActivitySystemPost([postAddToChannel1, postAddToChannel2, postAddToChannel3, {...postAddToChannel4, props: {addedUsername: 'added_user_name_4'}}])).toEqual(out3);
});
const postAddToTeam1 = TestHelper.getPostMock({type: PostTypes.ADD_TO_TEAM, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_1'}});
const postAddToTeam2 = TestHelper.getPostMock({type: PostTypes.ADD_TO_TEAM, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_2'}});
const postAddToTeam3 = TestHelper.getPostMock({type: PostTypes.ADD_TO_TEAM, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_3'}});
const postAddToTeam4 = TestHelper.getPostMock({type: PostTypes.ADD_TO_TEAM, user_id: 'user_id_2', props: {addedUserId: 'added_user_id_4'}});
it('should match return for ADD_TO_TEAM', () => {
const out1 = {
allUserIds: ['added_user_id_1', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_1']}],
};
expect(combineUserActivitySystemPost([postAddToTeam1])).toEqual(out1);
const out2 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_1', 'added_user_id_2']}],
};
expect(combineUserActivitySystemPost([postAddToTeam1, postAddToTeam2])).toEqual(out2);
const out3 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']}],
};
expect(combineUserActivitySystemPost([postAddToTeam1, postAddToTeam2, postAddToTeam3])).toEqual(out3);
const out4 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1', 'added_user_id_4', 'user_id_2'],
allUsernames: [],
messageData: [
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_4']},
],
};
expect(combineUserActivitySystemPost([postAddToTeam1, postAddToTeam2, postAddToTeam3, postAddToTeam4])).toEqual(out4);
});
it('should match return for ADD_TO_TEAM, backward compatibility with addedUsername', () => {
const out1 = {
allUserIds: ['user_id_1'],
allUsernames: ['added_user_name_1'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_name_1']}],
};
expect(combineUserActivitySystemPost([{...postAddToTeam1, props: {addedUsername: 'added_user_name_1'}}])).toEqual(out1);
const out2 = {
allUserIds: ['added_user_id_2', 'user_id_1'],
allUsernames: ['added_user_name_1'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_name_1', 'added_user_id_2']}],
};
expect(combineUserActivitySystemPost([{...postAddToTeam1, props: {addedUsername: 'added_user_name_1'}}, postAddToTeam2])).toEqual(out2);
const out3 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3', 'user_id_1', 'user_id_2'],
allUsernames: ['added_user_name_4'],
messageData: [
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_name_4']},
],
};
expect(combineUserActivitySystemPost([postAddToTeam1, postAddToTeam2, postAddToTeam3, {...postAddToTeam4, props: {addedUsername: 'added_user_name_4'}}])).toEqual(out3);
});
const postJoinChannel1 = TestHelper.getPostMock({type: PostTypes.JOIN_CHANNEL, user_id: 'user_id_1'});
const postJoinChannel2 = TestHelper.getPostMock({type: PostTypes.JOIN_CHANNEL, user_id: 'user_id_2'});
const postJoinChannel3 = TestHelper.getPostMock({type: PostTypes.JOIN_CHANNEL, user_id: 'user_id_3'});
const postJoinChannel4 = TestHelper.getPostMock({type: PostTypes.JOIN_CHANNEL, user_id: 'user_id_4'});
it('should match return for JOIN_CHANNEL', () => { it('should match return for JOIN_CHANNEL', () => {
const out1 = { const userActivities = [postJoinChannel];
const expectedOutput = {
allUserIds: ['user_id_1'], allUserIds: ['user_id_1'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1']}], messageData: [{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1']}],
}; };
expect(combineUserActivitySystemPost([postJoinChannel1])).toEqual(out1); expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const postJoinChannel2: ActivityEntry = {
const out2 = { postType: PostTypes.JOIN_CHANNEL,
allUserIds: ['user_id_1', 'user_id_2'], actorId: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUsernames: [], userIds: [],
messageData: [{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1', 'user_id_2']}], usernames: [],
}; };
expect(combineUserActivitySystemPost([postJoinChannel1, postJoinChannel2])).toEqual(out2); const expectedOutput2 = {
allUserIds: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
const out3 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1', 'user_id_2', 'user_id_3']}], messageData: [{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5']}],
}; };
expect(combineUserActivitySystemPost([postJoinChannel1, postJoinChannel2, postJoinChannel3])).toEqual(out3); expect(extractUserActivityData([postJoinChannel2])).toEqual(expectedOutput2);
const out4 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4'],
allUsernames: [],
messageData: [{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']}],
};
expect(combineUserActivitySystemPost([postJoinChannel1, postJoinChannel2, postJoinChannel3, postJoinChannel4])).toEqual(out4);
}); });
const postJoinTeam1 = TestHelper.getPostMock({type: PostTypes.JOIN_TEAM, user_id: 'user_id_1'}); it('should return expected data for ADD_TO_CHANNEL', () => {
const postJoinTeam2 = TestHelper.getPostMock({type: PostTypes.JOIN_TEAM, user_id: 'user_id_2'}); const userActivities = [postAddToChannel];
const postJoinTeam3 = TestHelper.getPostMock({type: PostTypes.JOIN_TEAM, user_id: 'user_id_3'}); const expectedOutput = {
const postJoinTeam4 = TestHelper.getPostMock({type: PostTypes.JOIN_TEAM, user_id: 'user_id_4'}); allUserIds: ['added_user_id_1', 'user_id_1'],
it('should match return for JOIN_TEAM', () => { allUsernames: ['added_username_1'],
const out1 = { messageData: [{postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_1', userIds: ['added_user_id_1']}],
};
expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const postAddToChannel2: ActivityEntry = {
postType: PostTypes.ADD_TO_CHANNEL,
actorId: ['user_id_2'],
userIds: ['added_user_id_2', 'added_user_id_3', 'added_user_id_4'],
usernames: ['added_username_2', 'added_username_3', 'added_username_4'],
};
const userActivities2 = [postAddToChannel, postAddToChannel2];
const expectedOutput2 = {
allUserIds: ['added_user_id_1', 'user_id_1', 'added_user_id_2', 'added_user_id_3', 'added_user_id_4', 'user_id_2'],
allUsernames: ['added_username_1', 'added_username_2', 'added_username_3', 'added_username_4'],
messageData: [
{postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_1', userIds: ['added_user_id_1']},
{postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_2', userIds: ['added_user_id_2', 'added_user_id_3', 'added_user_id_4']},
],
};
expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
});
it('should return expected data for ADD_TO_TEAM', () => {
const userActivities = [postAddToTeam];
const expectedOutput = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'user_id_1'],
allUsernames: ['added_username_1', 'added_username_2'],
messageData: [{postType: PostTypes.ADD_TO_TEAM, actorId: 'user_id_1', userIds: ['added_user_id_1', 'added_user_id_2']}],
};
expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const postAddToTeam2: ActivityEntry = {
postType: PostTypes.ADD_TO_TEAM,
actorId: ['user_id_2'],
userIds: ['added_user_id_3', 'added_user_id_4'],
usernames: ['added_username_3', 'added_username_4'],
};
const userActivities2 = [postAddToTeam, postAddToTeam2];
const expectedOutput2 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'user_id_1', 'added_user_id_3', 'added_user_id_4', 'user_id_2'],
allUsernames: ['added_username_1', 'added_username_2', 'added_username_3', 'added_username_4'],
messageData: [
{postType: PostTypes.ADD_TO_TEAM, actorId: 'user_id_1', userIds: ['added_user_id_1', 'added_user_id_2']},
{postType: PostTypes.ADD_TO_TEAM, actorId: 'user_id_2', userIds: ['added_user_id_3', 'added_user_id_4']},
],
};
expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
});
it('should return expected data for JOIN_TEAM', () => {
const userActivities = [postJoinTeam];
const expectedOutput = {
allUserIds: ['user_id_1'], allUserIds: ['user_id_1'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1']}], messageData: [{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1']}],
}; };
expect(combineUserActivitySystemPost([postJoinTeam1])).toEqual(out1); expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const postJoinTeam2: ActivityEntry = {
const out2 = { postType: PostTypes.JOIN_TEAM,
allUserIds: ['user_id_1', 'user_id_2'], actorId: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUsernames: [], userIds: [],
messageData: [{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1', 'user_id_2']}], usernames: [],
}; };
expect(combineUserActivitySystemPost([postJoinTeam1, postJoinTeam2])).toEqual(out2); const userActivities2 = [postJoinTeam, postJoinTeam2];
const expectedOutput2 = {
const out3 = { allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1', 'user_id_2', 'user_id_3']}], messageData: [
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5']},
],
}; };
expect(combineUserActivitySystemPost([postJoinTeam1, postJoinTeam2, postJoinTeam3])).toEqual(out3); expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
const out4 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4'],
allUsernames: [],
messageData: [{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']}],
};
expect(combineUserActivitySystemPost([postJoinTeam1, postJoinTeam2, postJoinTeam3, postJoinTeam4])).toEqual(out4);
}); });
const postLeaveChannel1 = TestHelper.getPostMock({type: PostTypes.LEAVE_CHANNEL, user_id: 'user_id_1'}); it('should return expected data for LEAVE_CHANNEL', () => {
const postLeaveChannel2 = TestHelper.getPostMock({type: PostTypes.LEAVE_CHANNEL, user_id: 'user_id_2'}); const userActivities = [postLeaveChannel];
const postLeaveChannel3 = TestHelper.getPostMock({type: PostTypes.LEAVE_CHANNEL, user_id: 'user_id_3'}); const expectedOutput = {
const postLeaveChannel4 = TestHelper.getPostMock({type: PostTypes.LEAVE_CHANNEL, user_id: 'user_id_4'});
it('should match return for LEAVE_CHANNEL', () => {
const out1 = {
allUserIds: ['user_id_1'], allUserIds: ['user_id_1'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1']}], messageData: [{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1']}],
}; };
expect(combineUserActivitySystemPost([postLeaveChannel1])).toEqual(out1); expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const out2 = { const postLeaveChannel2: ActivityEntry = {
allUserIds: ['user_id_1', 'user_id_2'], postType: PostTypes.LEAVE_CHANNEL,
allUsernames: [], actorId: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
messageData: [{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1', 'user_id_2']}], userIds: [],
usernames: [],
}; };
expect(combineUserActivitySystemPost([postLeaveChannel1, postLeaveChannel2])).toEqual(out2); const userActivities2 = [postLeaveChannel, postLeaveChannel2];
const expectedOutput2 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUsernames: [],
messageData: [
const out3 = { {postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1']},
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'], {postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5']},
allUsernames: [], ],
messageData: [{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1', 'user_id_2', 'user_id_3']}],
}; };
expect(combineUserActivitySystemPost([postLeaveChannel1, postLeaveChannel2, postLeaveChannel3])).toEqual(out3); expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
const out4 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4'],
allUsernames: [],
messageData: [{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']}],
};
expect(combineUserActivitySystemPost([postLeaveChannel1, postLeaveChannel2, postLeaveChannel3, postLeaveChannel4])).toEqual(out4);
}); });
const postLeaveTeam1 = TestHelper.getPostMock({type: PostTypes.LEAVE_TEAM, user_id: 'user_id_1'}); it('should return expected data for LEAVE_TEAM', () => {
const postLeaveTeam2 = TestHelper.getPostMock({type: PostTypes.LEAVE_TEAM, user_id: 'user_id_2'}); const userActivities = [postLeaveTeam];
const postLeaveTeam3 = TestHelper.getPostMock({type: PostTypes.LEAVE_TEAM, user_id: 'user_id_3'}); const expectedOutput = {
const postLeaveTeam4 = TestHelper.getPostMock({type: PostTypes.LEAVE_TEAM, user_id: 'user_id_4'});
it('should match return for LEAVE_TEAM', () => {
const out1 = {
allUserIds: ['user_id_1'], allUserIds: ['user_id_1'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1']}], messageData: [{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1']}],
}; };
expect(combineUserActivitySystemPost([postLeaveTeam1])).toEqual(out1); expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const postLeaveTeam2: ActivityEntry = {
const out2 = { postType: PostTypes.LEAVE_TEAM,
allUserIds: ['user_id_1', 'user_id_2'], actorId: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUsernames: [], userIds: [],
messageData: [{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1', 'user_id_2']}], usernames: [],
}; };
expect(combineUserActivitySystemPost([postLeaveTeam1, postLeaveTeam2])).toEqual(out2); const userActivities2 = [postLeaveTeam, postLeaveTeam2];
const expectedOutput2 = {
const out3 = { allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1', 'user_id_2', 'user_id_3']}], messageData: [
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5']},
],
}; };
expect(combineUserActivitySystemPost([postLeaveTeam1, postLeaveTeam2, postLeaveTeam3])).toEqual(out3); expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
const out4 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4'],
allUsernames: [],
messageData: [{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']}],
};
expect(combineUserActivitySystemPost([postLeaveTeam1, postLeaveTeam2, postLeaveTeam3, postLeaveTeam4])).toEqual(out4);
}); });
it('should return expected data for REMOVE_FROM_CHANNEL', () => {
const postRemoveFromChannel1 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_CHANNEL, user_id: 'user_id_1', props: {removedUserId: 'removed_user_id_1'}}); const userActivities = [postRemoveFromChannel];
const postRemoveFromChannel2 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_CHANNEL, user_id: 'user_id_1', props: {removedUserId: 'removed_user_id_2'}}); const expectedOutput = {
const postRemoveFromChannel3 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_CHANNEL, user_id: 'user_id_1', props: {removedUserId: 'removed_user_id_3'}});
const postRemoveFromChannel4 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_CHANNEL, user_id: 'user_id_1', props: {removedUserId: 'removed_user_id_4'}});
it('should match return for REMOVE_FROM_CHANNEL', () => {
const out1 = {
allUserIds: ['removed_user_id_1', 'user_id_1'], allUserIds: ['removed_user_id_1', 'user_id_1'],
allUsernames: [], allUsernames: ['removed_username_1'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1']}], messageData: [{postType: PostTypes.REMOVE_FROM_CHANNEL, actorId: 'user_id_1', userIds: ['removed_user_id_1']}],
}; };
expect(combineUserActivitySystemPost([postRemoveFromChannel1])).toEqual(out1); expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const out2 = { const postRemoveFromChannel2: ActivityEntry = {
allUserIds: ['removed_user_id_1', 'removed_user_id_2', 'user_id_1'], postType: PostTypes.REMOVE_FROM_CHANNEL,
allUsernames: [], actorId: ['user_id_2'],
messageData: [{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1', 'removed_user_id_2']}], userIds: ['removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4', 'removed_user_id_5'],
usernames: ['removed_username_2', 'removed_username_3', 'removed_username_4', 'removed_username_5'],
}; };
expect(combineUserActivitySystemPost([postRemoveFromChannel1, postRemoveFromChannel2])).toEqual(out2); const userActivities2 = [postRemoveFromChannel, postRemoveFromChannel2];
const expectedOutput2 = {
const out3 = { allUserIds: ['removed_user_id_1', 'user_id_1', 'removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4', 'removed_user_id_5', 'user_id_2'],
allUserIds: ['removed_user_id_1', 'removed_user_id_2', 'removed_user_id_3', 'user_id_1'], allUsernames: ['removed_username_1', 'removed_username_2', 'removed_username_3', 'removed_username_4', 'removed_username_5'],
allUsernames: [], messageData: [
messageData: [{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1', 'removed_user_id_2', 'removed_user_id_3']}], {postType: PostTypes.REMOVE_FROM_CHANNEL, actorId: 'user_id_1', userIds: ['removed_user_id_1']},
{postType: PostTypes.REMOVE_FROM_CHANNEL, actorId: 'user_id_2', userIds: ['removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4', 'removed_user_id_5']},
],
}; };
expect(combineUserActivitySystemPost([postRemoveFromChannel1, postRemoveFromChannel2, postRemoveFromChannel3])).toEqual(out3); expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
const out4 = {
allUserIds: ['removed_user_id_1', 'removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4', 'user_id_1'],
allUsernames: [],
messageData: [{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1', 'removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4']}],
};
expect(combineUserActivitySystemPost([postRemoveFromChannel1, postRemoveFromChannel2, postRemoveFromChannel3, postRemoveFromChannel4])).toEqual(out4);
}); });
it('should return expected data for REMOVE_FROM_TEAM', () => {
const postRemoveFromTeam1 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_TEAM, user_id: 'user_id_1'}); const userActivities = [postRemoveFromTeam];
const postRemoveFromTeam2 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_TEAM, user_id: 'user_id_2'}); const expectedOutput = {
const postRemoveFromTeam3 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_TEAM, user_id: 'user_id_3'});
const postRemoveFromTeam4 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_TEAM, user_id: 'user_id_4'});
it('should match return for REMOVE_FROM_TEAM', () => {
const out1 = {
allUserIds: ['user_id_1'], allUserIds: ['user_id_1'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1']}], messageData: [{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1']}],
}; };
expect(combineUserActivitySystemPost([postRemoveFromTeam1])).toEqual(out1); expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
const out2 = { const postRemoveFromTeam2: ActivityEntry = {
allUserIds: ['user_id_1', 'user_id_2'], postType: PostTypes.REMOVE_FROM_TEAM,
allUsernames: [], actorId: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
messageData: [{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1', 'user_id_2']}], userIds: [],
usernames: [],
}; };
expect(combineUserActivitySystemPost([postRemoveFromTeam1, postRemoveFromTeam2])).toEqual(out2); const userActivities2 = [postRemoveFromTeam, postRemoveFromTeam2];
const expectedOutput2 = {
const out3 = { allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4', 'user_id_5'],
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'],
allUsernames: [], allUsernames: [],
messageData: [{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1', 'user_id_2', 'user_id_3']}], messageData: [
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_2', 'user_id_3', 'user_id_4', 'user_id_5']},
],
}; };
expect(combineUserActivitySystemPost([postRemoveFromTeam1, postRemoveFromTeam2, postRemoveFromTeam3])).toEqual(out3); expect(extractUserActivityData(userActivities2)).toEqual(expectedOutput2);
const out4 = {
allUserIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4'],
allUsernames: [],
messageData: [{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']}],
};
expect(combineUserActivitySystemPost([postRemoveFromTeam1, postRemoveFromTeam2, postRemoveFromTeam3, postRemoveFromTeam4])).toEqual(out4);
}); });
it('should return expected data for multiple post types', () => {
it('should match return on combination', () => { const userActivities = [postAddToChannel, postAddToTeam, postJoinChannel, postJoinTeam, postLeaveChannel, postLeaveTeam, postRemoveFromChannel, postRemoveFromTeam];
const out1 = { const expectedOutput = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'user_id_1'], allUserIds: ['added_user_id_1', 'user_id_1', 'added_user_id_2', 'removed_user_id_1'],
allUsernames: [], allUsernames: ['added_username_1', 'added_username_2', 'removed_username_1'],
messageData: [ messageData: [
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_1', 'added_user_id_2']}, {postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_1', userIds: ['added_user_id_1']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2']}, {postType: PostTypes.ADD_TO_TEAM, actorId: 'user_id_1', userIds: ['added_user_id_1', 'added_user_id_2']},
],
};
expect(combineUserActivitySystemPost([postAddToChannel1, postAddToChannel2, postAddToTeam1, postAddToTeam2])).toEqual(out1);
const out2 = {
allUserIds: ['user_id_1', 'user_id_2'],
allUsernames: [],
messageData: [
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1', 'user_id_2']},
{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1', 'user_id_2']},
],
};
expect(combineUserActivitySystemPost([postJoinChannel1, postJoinChannel2, postJoinTeam1, postJoinTeam2])).toEqual(out2);
const out3 = {
allUserIds: ['user_id_1', 'user_id_2'],
allUsernames: [],
messageData: [
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1', 'user_id_2']},
{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1', 'user_id_2']},
],
};
expect(combineUserActivitySystemPost([postLeaveChannel1, postLeaveChannel2, postLeaveTeam1, postLeaveTeam2])).toEqual(out3);
const out4 = {
allUserIds: ['removed_user_id_1', 'removed_user_id_2', 'user_id_1', 'user_id_2'],
allUsernames: [],
messageData: [
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1', 'user_id_2']},
{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1', 'removed_user_id_2']},
],
};
expect(combineUserActivitySystemPost([postRemoveFromChannel1, postRemoveFromChannel2, postRemoveFromTeam1, postRemoveFromTeam2])).toEqual(out4);
const out5 = {
allUserIds: ['added_user_id_1', 'added_user_id_2', 'user_id_1', 'user_id_2', 'removed_user_id_1', 'removed_user_id_2'],
allUsernames: [],
messageData: [
{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1', 'user_id_2']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2']},
{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1', 'user_id_2']},
{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1', 'removed_user_id_2']},
],
};
expect(combineUserActivitySystemPost([
postAddToChannel1,
postJoinChannel1,
postLeaveChannel1,
postRemoveFromChannel1,
postAddToChannel2,
postJoinChannel2,
postLeaveChannel2,
postRemoveFromChannel2,
])).toEqual(out5);
const out6 = {
allUserIds: ['added_user_id_3', 'user_id_1', 'added_user_id_4', 'user_id_2', 'user_id_3', 'user_id_4'],
allUsernames: [],
messageData: [
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_3', 'user_id_4']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_4']},
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_3', 'user_id_4']},
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_3', 'user_id_4']},
],
};
expect(combineUserActivitySystemPost([
postAddToTeam3,
postJoinTeam3,
postLeaveTeam3,
postRemoveFromTeam3,
postAddToTeam4,
postJoinTeam4,
postLeaveTeam4,
postRemoveFromTeam4,
])).toEqual(out6);
const out7 = {
allUserIds: ['added_user_id_3', 'added_user_id_1', 'added_user_id_2', 'user_id_1', 'added_user_id_4', 'user_id_2', 'user_id_3', 'user_id_4', 'removed_user_id_1', 'removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4'],
allUsernames: [],
messageData: [
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_3', 'user_id_4', 'user_id_1', 'user_id_2']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_3', 'added_user_id_1', 'added_user_id_2']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_4']},
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_3', 'user_id_4', 'user_id_1', 'user_id_2']},
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_3', 'user_id_4', 'user_id_1', 'user_id_2']},
{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1', 'added_user_id_2', 'added_user_id_3']},
{actorId: 'user_id_2', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_4']},
{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1', 'user_id_2', 'user_id_3', 'user_id_4']},
{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1', 'removed_user_id_2', 'removed_user_id_3', 'removed_user_id_4']},
],
};
expect(combineUserActivitySystemPost([
postAddToTeam3,
postJoinTeam3,
postLeaveTeam3,
postRemoveFromTeam3,
postAddToTeam4,
postJoinTeam4,
postLeaveTeam4,
postRemoveFromTeam4,
postAddToChannel1,
postJoinChannel1,
postLeaveChannel1,
postRemoveFromChannel1,
postAddToChannel2,
postJoinChannel2,
postLeaveChannel2,
postRemoveFromChannel2,
postAddToChannel3,
postJoinChannel3,
postLeaveChannel3,
postRemoveFromChannel3,
postAddToChannel4,
postJoinChannel4,
postLeaveChannel4,
postRemoveFromChannel4,
postAddToTeam1,
postJoinTeam1,
postLeaveTeam1,
postRemoveFromTeam1,
postAddToTeam2,
postJoinTeam2,
postLeaveTeam2,
postRemoveFromTeam2,
])).toEqual(out7);
const out8 = {
allUserIds: ['added_user_id_3', 'user_id_1', 'user_id_3', 'added_user_id_1', 'removed_user_id_1'],
allUsernames: [],
messageData: [
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_3']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_TEAM, userIds: ['added_user_id_3']},
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_3']},
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_3']},
{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1']}, {postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1']},
{actorId: 'user_id_1', postType: PostTypes.ADD_TO_CHANNEL, userIds: ['added_user_id_1']}, {postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1']}, {postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1']},
{actorId: 'user_id_1', postType: PostTypes.REMOVE_FROM_CHANNEL, userIds: ['removed_user_id_1']}, {postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.REMOVE_FROM_CHANNEL, actorId: 'user_id_1', userIds: ['removed_user_id_1']},
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1']},
], ],
}; };
expect(combineUserActivitySystemPost([ expect(extractUserActivityData(userActivities)).toEqual(expectedOutput);
postAddToTeam3,
postAddToTeam3,
postJoinTeam3,
postJoinTeam3,
postLeaveTeam3,
postLeaveTeam3,
postRemoveFromTeam3,
postRemoveFromTeam3,
postAddToChannel1,
postAddToChannel1,
postJoinChannel1,
postJoinChannel1,
postLeaveChannel1,
postLeaveChannel1,
postRemoveFromChannel1,
postRemoveFromChannel1,
])).toEqual(out8);
}); });
}); });
describe('comparePostTypes', () => { describe('combineUserActivityData', () => {
const { it('combineUserActivitySystemPost returns null when systemPosts is an empty array', () => {
JOIN_TEAM, expect(combineUserActivitySystemPost([])).toBeNull();
ADD_TO_TEAM, });
LEAVE_TEAM, it('correctly combine different post types and actorIds by order', () => {
REMOVE_FROM_TEAM, const postAddToChannel1 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_1', addedUsername: 'added_username_1'}});
JOIN_CHANNEL, const postAddToTeam1 = TestHelper.getPostMock({type: PostTypes.ADD_TO_TEAM, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_1'}});
ADD_TO_CHANNEL, const postJoinChannel1 = TestHelper.getPostMock({type: PostTypes.JOIN_CHANNEL, user_id: 'user_id_1'});
LEAVE_CHANNEL, const postJoinTeam1 = TestHelper.getPostMock({type: PostTypes.JOIN_TEAM, user_id: 'user_id_1'});
REMOVE_FROM_CHANNEL, const postLeaveChannel1 = TestHelper.getPostMock({type: PostTypes.LEAVE_CHANNEL, user_id: 'user_id_1'});
} = Posts.POST_TYPES; const postLeaveTeam1 = TestHelper.getPostMock({type: PostTypes.LEAVE_TEAM, user_id: 'user_id_1'});
const postRemoveFromChannel1 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_CHANNEL, user_id: 'user_id_1', props: {removedUserId: 'removed_user_id_1', removedUsername: 'removed_username_1'}});
const postRemoveFromTeam1 = TestHelper.getPostMock({type: PostTypes.REMOVE_FROM_TEAM, user_id: 'user_id_1'});
const posts = [postAddToChannel1, postAddToTeam1, postJoinChannel1, postJoinTeam1, postLeaveChannel1, postLeaveTeam1, postRemoveFromChannel1, postRemoveFromTeam1].reverse();
const expectedOutput = {
allUserIds: ['added_user_id_1', 'user_id_1', 'removed_user_id_1'],
allUsernames: ['added_username_1', 'removed_username_1'],
messageData: [
{postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_1', userIds: ['added_user_id_1']},
{postType: PostTypes.ADD_TO_TEAM, actorId: 'user_id_1', userIds: ['added_user_id_1']},
{postType: PostTypes.JOIN_CHANNEL, userIds: ['user_id_1']},
{postType: PostTypes.JOIN_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.LEAVE_CHANNEL, userIds: ['user_id_1']},
{postType: PostTypes.LEAVE_TEAM, userIds: ['user_id_1']},
{postType: PostTypes.REMOVE_FROM_CHANNEL, actorId: 'user_id_1', userIds: ['removed_user_id_1']},
{postType: PostTypes.REMOVE_FROM_TEAM, userIds: ['user_id_1']},
],
};
expect(combineUserActivitySystemPost(posts)).toEqual(expectedOutput);
});
it('correctly combine same post types', () => {
const postAddToChannel1 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_1', props: {addedUserId: 'added_user_id_1', addedUsername: 'added_username_1'}});
const postAddToChannel2 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_2', props: {addedUserId: 'added_user_id_2', addedUsername: 'added_username_2'}});
const postAddToChannel3 = TestHelper.getPostMock({type: PostTypes.ADD_TO_CHANNEL, user_id: 'user_id_3', props: {addedUserId: 'added_user_id_3', addedUsername: 'added_username_3'}});
const testCases = [ const posts = [postAddToChannel1, postAddToChannel2, postAddToChannel3].reverse();
[], const expectedOutput = {
[{postType: JOIN_TEAM}], allUserIds: ['added_user_id_1', 'user_id_1', 'added_user_id_2', 'user_id_2', 'added_user_id_3', 'user_id_3'],
[{postType: JOIN_TEAM}, {postType: ADD_TO_TEAM}], allUsernames: ['added_username_1', 'added_username_2', 'added_username_3'],
[{postType: ADD_TO_TEAM}, {postType: JOIN_TEAM}], messageData: [
[{postType: ADD_TO_TEAM}, {postType: ADD_TO_TEAM}, {postType: JOIN_TEAM}], {postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_1', userIds: ['added_user_id_1']},
[{postType: JOIN_TEAM}, {postType: ADD_TO_TEAM}, {postType: LEAVE_TEAM}, {postType: REMOVE_FROM_TEAM}], {postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_2', userIds: ['added_user_id_2']},
[{postType: REMOVE_FROM_TEAM}, {postType: LEAVE_TEAM}, {postType: ADD_TO_TEAM}, {postType: JOIN_TEAM}], {postType: PostTypes.ADD_TO_CHANNEL, actorId: 'user_id_3', userIds: ['added_user_id_3']},
[{postType: JOIN_CHANNEL}, {postType: ADD_TO_CHANNEL}, {postType: LEAVE_CHANNEL}, {postType: REMOVE_FROM_CHANNEL}], ],
[{postType: REMOVE_FROM_CHANNEL}, {postType: LEAVE_CHANNEL}, {postType: ADD_TO_CHANNEL}, {postType: JOIN_CHANNEL}], };
[{postType: LEAVE_CHANNEL}, {postType: REMOVE_FROM_CHANNEL}, {postType: LEAVE_TEAM}, {postType: REMOVE_FROM_TEAM}], expect(combineUserActivitySystemPost(posts)).toEqual(expectedOutput);
[{postType: LEAVE_TEAM}, {postType: REMOVE_FROM_TEAM}, {postType: LEAVE_CHANNEL}, {postType: REMOVE_FROM_CHANNEL}], });
[{postType: JOIN_CHANNEL}, {postType: LEAVE_CHANNEL}, {postType: JOIN_CHANNEL}, {postType: REMOVE_FROM_CHANNEL}, {postType: ADD_TO_CHANNEL}],
];
for (const testCase of testCases) {
let previousType = '';
testCase.sort(comparePostTypes as any).forEach((sortedTestCase, index) => {
it(`should sort post type correctly: ${previousType} should come first before ${sortedTestCase.postType}`, () => {
if (index > 0) {
expect(postTypePriority[previousType] <= postTypePriority[sortedTestCase.postType]).toBeTruthy();
}
previousType = sortedTestCase.postType;
});
});
}
}); });

View File

@ -16,7 +16,7 @@ import {createIdsSelector, memoizeResult} from 'mattermost-redux/utils/helpers';
import {isUserActivityPost, shouldFilterJoinLeavePost, isFromWebhook} from 'mattermost-redux/utils/post_utils'; import {isUserActivityPost, shouldFilterJoinLeavePost, isFromWebhook} from 'mattermost-redux/utils/post_utils';
import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils'; import {getUserCurrentTimezone} from 'mattermost-redux/utils/timezone_utils';
import {Post} from '@mattermost/types/posts'; import {ActivityEntry, Post} from '@mattermost/types/posts';
import {GlobalState} from '@mattermost/types/store'; import {GlobalState} from '@mattermost/types/store';
export const COMBINED_USER_ACTIVITY = 'user-activity-'; export const COMBINED_USER_ACTIVITY = 'user-activity-';
@ -285,7 +285,6 @@ export function makeGenerateCombinedPost(): (state: GlobalState, combinedId: str
// Assume that the last post is the oldest one // Assume that the last post is the oldest one
const createAt = posts[posts.length - 1].create_at; const createAt = posts[posts.length - 1].create_at;
const messages = posts.map((post) => post.message); const messages = posts.map((post) => post.message);
return { return {
@ -323,66 +322,30 @@ export function makeGenerateCombinedPost(): (state: GlobalState, combinedId: str
); );
} }
export const postTypePriority = { export function extractUserActivityData(userActivities: ActivityEntry[]) {
[Posts.POST_TYPES.JOIN_TEAM]: 0,
[Posts.POST_TYPES.ADD_TO_TEAM]: 1,
[Posts.POST_TYPES.LEAVE_TEAM]: 2,
[Posts.POST_TYPES.REMOVE_FROM_TEAM]: 3,
[Posts.POST_TYPES.JOIN_CHANNEL]: 4,
[Posts.POST_TYPES.ADD_TO_CHANNEL]: 5,
[Posts.POST_TYPES.LEAVE_CHANNEL]: 6,
[Posts.POST_TYPES.REMOVE_FROM_CHANNEL]: 7,
[Posts.POST_TYPES.PURPOSE_CHANGE]: 8,
[Posts.POST_TYPES.HEADER_CHANGE]: 9,
[Posts.POST_TYPES.JOIN_LEAVE]: 10,
[Posts.POST_TYPES.DISPLAYNAME_CHANGE]: 11,
[Posts.POST_TYPES.CONVERT_CHANNEL]: 12,
[Posts.POST_TYPES.CHANNEL_DELETED]: 13,
[Posts.POST_TYPES.CHANNEL_UNARCHIVED]: 14,
[Posts.POST_TYPES.ADD_REMOVE]: 15,
[Posts.POST_TYPES.EPHEMERAL]: 16,
};
export function comparePostTypes(a: typeof postTypePriority, b: typeof postTypePriority) {
return postTypePriority[a.postType] - postTypePriority[b.postType];
}
function extractUserActivityData(userActivities: any) {
const messageData: any[] = []; const messageData: any[] = [];
const allUserIds: string[] = []; const allUserIds: string[] = [];
const allUsernames: string[] = []; const allUsernames: string[] = [];
Object.entries(userActivities).forEach(([postType, values]: [string, any]) => { userActivities.forEach((activity) => {
if ( if (isUsersRelatedPost(activity.postType)) {
postType === Posts.POST_TYPES.ADD_TO_TEAM || const {postType, actorId, userIds, usernames} = activity;
postType === Posts.POST_TYPES.ADD_TO_CHANNEL || if (usernames && userIds) {
postType === Posts.POST_TYPES.REMOVE_FROM_CHANNEL messageData.push({postType, userIds: [...userIds], actorId: actorId[0]});
) { if (userIds.length > 0) {
Object.keys(values).map((key) => [key, values[key]]).forEach(([actorId, users]) => { allUserIds.push(...userIds.filter((userId) => userId));
if (Array.isArray(users)) {
throw new Error('Invalid Post activity data');
} }
const {ids, usernames} = users;
messageData.push({postType, userIds: [...usernames, ...ids], actorId});
if (ids.length > 0) {
allUserIds.push(...ids);
}
if (usernames.length > 0) { if (usernames.length > 0) {
allUsernames.push(...usernames); allUsernames.push(...usernames.filter((username) => username));
} }
allUserIds.push(actorId); allUserIds.push(actorId[0]);
});
} else {
if (!Array.isArray(values)) {
throw new Error('Invalid Post activity data');
} }
messageData.push({postType, userIds: values}); } else {
allUserIds.push(...values); const {postType, actorId} = activity;
const userIds = actorId;
messageData.push({postType, userIds});
allUserIds.push(...userIds);
} }
}); });
messageData.sort(comparePostTypes);
function reduceUsers(acc: string[], curr: string) { function reduceUsers(acc: string[], curr: string) {
if (!acc.includes(curr)) { if (!acc.includes(curr)) {
acc.push(curr); acc.push(curr);
@ -396,69 +359,45 @@ function extractUserActivityData(userActivities: any) {
messageData, messageData,
}; };
} }
function isUsersRelatedPost(postType: string) {
return (
postType === Posts.POST_TYPES.ADD_TO_TEAM ||
postType === Posts.POST_TYPES.ADD_TO_CHANNEL ||
postType === Posts.POST_TYPES.REMOVE_FROM_CHANNEL
);
}
export function combineUserActivitySystemPost(systemPosts: Post[] = []) { export function combineUserActivitySystemPost(systemPosts: Post[] = []) {
if (systemPosts.length === 0) { if (systemPosts.length === 0) {
return null; return null;
} }
const userActivities: ActivityEntry[] = [];
const userActivities = systemPosts.reduce((acc: any, post: Post) => { systemPosts.reverse().forEach((post: Post) => {
const postType = post.type; const postType = post.type;
let userActivityProps = acc; const actorId = post.user_id;
const combinedPostType = userActivityProps[postType as string];
if ( // When combining removed posts, the actorId does not need to be the same for each post.
postType === Posts.POST_TYPES.ADD_TO_TEAM || // All removed posts will be combined regardless of their respective actorIds.
postType === Posts.POST_TYPES.ADD_TO_CHANNEL || const isRemovedPost = post.type === Posts.POST_TYPES.REMOVE_FROM_CHANNEL;
postType === Posts.POST_TYPES.REMOVE_FROM_CHANNEL const userId = isUsersRelatedPost(postType) ? post.props.addedUserId || post.props.removedUserId : '';
) { const username = isUsersRelatedPost(postType) ? post.props.addedUsername || post.props.removedUsername : '';
const userId = post.props.addedUserId || post.props.removedUserId; const prevPost = userActivities[userActivities.length - 1];
const username = post.props.addedUsername || post.props.removedUsername; const isSamePostType = prevPost && prevPost.postType === post.type;
if (combinedPostType) { const isSameActor = prevPost && prevPost.actorId[0] === post.user_id;
if (Array.isArray(combinedPostType[post.user_id])) {
throw new Error('Invalid Post activity data');
}
const users = combinedPostType[post.user_id] || {ids: [], usernames: []};
if (userId) {
if (!users.ids.includes(userId)) {
users.ids.push(userId);
}
} else if (username && !users.usernames.includes(username)) {
users.usernames.push(username);
}
combinedPostType[post.user_id] = users;
} else {
const users = {
ids: [] as string[],
usernames: [] as string[],
};
if (userId) { if (prevPost && isSamePostType && (isSameActor || isRemovedPost)) {
users.ids.push(userId); prevPost.userIds.push(userId);
} else if (username) { prevPost.usernames.push(username);
users.usernames.push(username); } else if (isSamePostType && !isSameActor && !isUsersRelatedPost(postType)) {
} prevPost.actorId.push(actorId);
userActivityProps[postType] = {
[post.user_id]: users,
};
}
} else { } else {
const propsUserId = post.user_id; userActivities.push({
actorId: [actorId],
if (combinedPostType) { userIds: [userId],
if (!Array.isArray(combinedPostType)) { usernames: [username],
throw new Error('Invalid Post activity data'); postType,
} });
if (!combinedPostType.includes(propsUserId)) {
userActivityProps[postType] = [...combinedPostType, propsUserId];
}
} else {
userActivityProps = {...userActivityProps, [postType]: [propsUserId]};
}
} }
});
return userActivityProps;
}, {});
return extractUserActivityData(userActivities); return extractUserActivityData(userActivities);
} }

View File

@ -204,3 +204,9 @@ export type PostAnalytics = {
requested_ack?: boolean; requested_ack?: boolean;
persistent_notifications?: boolean; persistent_notifications?: boolean;
} }
export type ActivityEntry = {
postType: Post['type'];
actorId: string[];
userIds: string[];
usernames: string[];
}