* Remove mattermost-redux * Move mm-redux files into app/redux * Add @redux path to tsconfig.json * Fix imports * Install missing dependencies * Fix tsc errors * Fix i18n_utils test * Fix more imports * Remove redux websocket * Fix tests * Rename @redux * Apply changes from mattermost-redux PR 1103 * Remove mattermost-redux mention in template * Add missing imports * Rename app/redux/ to app/mm-redux/ * Remove test file * Fix fetching Sidebar GM profiles Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
1094 lines
No EOL
46 KiB
JavaScript
1094 lines
No EOL
46 KiB
JavaScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import assert from 'assert';
|
|
import nock from 'nock';
|
|
import {Server, WebSocket as MockWebSocket} from 'mock-socket';
|
|
import {batchActions} from 'redux-batched-actions';
|
|
import thunk from 'redux-thunk';
|
|
import configureMockStore from 'redux-mock-store';
|
|
|
|
import {ChannelTypes, GeneralTypes, RoleTypes, TeamTypes, UserTypes} from '@mm-redux/action_types';
|
|
import * as ChannelActions from '@mm-redux/actions/channels';
|
|
import * as PostActions from '@mm-redux/actions/posts';
|
|
import * as PreferenceActions from '@mm-redux/actions/preferences';
|
|
import * as TeamActions from '@mm-redux/actions/teams';
|
|
import * as UserActions from '@mm-redux/actions/users';
|
|
import {Client4} from '@mm-redux/client';
|
|
import {General, Posts, RequestStatus} from '@mm-redux/constants';
|
|
import * as PostSelectors from '@mm-redux/selectors/entities/posts';
|
|
import EventEmitter from '@mm-redux/utils/event_emitter';
|
|
|
|
import * as Actions from '@actions/websocket';
|
|
import {WebsocketEvents} from '@constants';
|
|
|
|
import TestHelper from 'test/test_helper';
|
|
import configureStore from 'test/test_store';
|
|
import initial_state from 'app/initial_state';
|
|
|
|
global.WebSocket = MockWebSocket;
|
|
|
|
const mockConfigRequest = (config = {}) => {
|
|
nock(Client4.getBaseRoute()).
|
|
get('/config/client?format=old').
|
|
reply(200, config);
|
|
};
|
|
|
|
const mockChanelsRequest = (teamId, channels = []) => {
|
|
nock(Client4.getUserRoute('me')).
|
|
get(`/teams/${teamId}/channels?include_deleted=true`).
|
|
reply(200, channels);
|
|
};
|
|
|
|
const mockRolesRequest = (rolesToLoad = []) => {
|
|
nock(Client4.getRolesRoute()).
|
|
post('/names', JSON.stringify(rolesToLoad)).
|
|
reply(200, rolesToLoad);
|
|
};
|
|
|
|
const mockTeamMemberRequest = (tm = []) => {
|
|
nock(Client4.getUserRoute('me')).
|
|
log(console.log).
|
|
get('/teams/members').
|
|
reply(200, tm);
|
|
};
|
|
|
|
describe('Actions.Websocket', () => {
|
|
let store;
|
|
let mockServer;
|
|
beforeAll(async () => {
|
|
store = await configureStore();
|
|
await TestHelper.initBasic(Client4);
|
|
|
|
const connUrl = (Client4.getUrl() + '/api/v4/websocket').replace(/^http:/, 'ws:');
|
|
mockServer = new Server(connUrl);
|
|
return store.dispatch(Actions.init({websocketUrl: Client4.getUrl().replace(/^http:/, 'ws:')}));
|
|
});
|
|
|
|
afterAll(async () => {
|
|
Actions.close()();
|
|
mockServer.stop();
|
|
await TestHelper.tearDown();
|
|
});
|
|
|
|
it('WebSocket Connect', () => {
|
|
const ws = store.getState().requests.general.websocket;
|
|
assert.ok(ws.status === RequestStatus.SUCCESS);
|
|
});
|
|
|
|
it('Websocket Handle New Post if post does not exist', async () => {
|
|
PostSelectors.getPost = jest.fn();
|
|
const channelId = TestHelper.basicChannel.id;
|
|
const message = JSON.stringify({event: WebsocketEvents.POSTED, data: {channel_display_name: TestHelper.basicChannel.display_name, channel_name: TestHelper.basicChannel.name, channel_type: 'O', post: `{"id": "71k8gz5ompbpfkrzaxzodffj8w", "create_at": 1508245311774, "update_at": 1508245311774, "edit_at": 0, "delete_at": 0, "is_pinned": false, "user_id": "${TestHelper.basicUser.id}", "channel_id": "${channelId}", "root_id": "", "parent_id": "", "original_id": "", "message": "Unit Test", "type": "", "props": {}, "hashtags": "", "pending_post_id": "t36kso9nwtdhbm8dbkd6g4eeby: 1508245311749"}`, sender_name: TestHelper.basicUser.username, team_id: TestHelper.basicTeam.id}, broadcast: {omit_users: null, user_id: '', channel_id: channelId, team_id: ''}, seq: 2});
|
|
|
|
nock(Client4.getBaseRoute()).
|
|
post('/users/ids').
|
|
reply(200, [TestHelper.basicUser.id]);
|
|
|
|
nock(Client4.getBaseRoute()).
|
|
post('/users/status/ids').
|
|
reply(200, [{user_id: TestHelper.basicUser.id, status: 'online', manual: false, last_activity_at: 1507662212199}]);
|
|
|
|
// Mock that post already exists and check it is not added
|
|
PostSelectors.getPost.mockReturnValueOnce(true);
|
|
mockServer.emit('message', message);
|
|
let entities = store.getState().entities;
|
|
let posts = entities.posts.posts;
|
|
assert.deepEqual(posts, {});
|
|
|
|
// Mock that post does not exist and check it is added
|
|
PostSelectors.getPost.mockReturnValueOnce(false);
|
|
mockServer.emit('message', message);
|
|
await TestHelper.wait(100);
|
|
entities = store.getState().entities;
|
|
posts = entities.posts.posts;
|
|
const postId = Object.keys(posts)[0];
|
|
assert.ok(posts[postId].message.indexOf('Unit Test') > -1);
|
|
entities = store.getState().entities;
|
|
});
|
|
|
|
it('Websocket Handle New Post emits INCREASE_POST_VISIBILITY_BY_ONE for current channel when post does not exist', async () => {
|
|
PostSelectors.getPost = jest.fn();
|
|
const emit = jest.spyOn(EventEmitter, 'emit');
|
|
const currentChannelId = TestHelper.generateId();
|
|
const otherChannelId = TestHelper.generateId();
|
|
const messageFor = (channelId) => ({event: WebsocketEvents.POSTED, data: {channel_display_name: TestHelper.basicChannel.display_name, channel_name: TestHelper.basicChannel.name, channel_type: 'O', post: `{"id": "71k8gz5ompbpfkrzaxzodffj8w", "create_at": 1508245311774, "update_at": 1508245311774, "edit_at": 0, "delete_at": 0, "is_pinned": false, "user_id": "${TestHelper.basicUser.id}", "channel_id": "${channelId}", "root_id": "", "parent_id": "", "original_id": "", "message": "Unit Test", "type": "", "props": {}, "hashtags": "", "pending_post_id": "t36kso9nwtdhbm8dbkd6g4eeby: 1508245311749"}`, sender_name: TestHelper.basicUser.username, team_id: TestHelper.basicTeam.id}, broadcast: {omit_users: null, user_id: '', channel_id: channelId, team_id: ''}, seq: 2});
|
|
|
|
await store.dispatch(ChannelActions.selectChannel(currentChannelId));
|
|
await TestHelper.wait(100);
|
|
|
|
// Post does not exist and is not for current channel
|
|
PostSelectors.getPost.mockReturnValueOnce(false);
|
|
mockServer.emit('message', JSON.stringify(messageFor(otherChannelId)));
|
|
expect(emit).not.toHaveBeenCalled();
|
|
|
|
// Post exists and is not for current channel
|
|
PostSelectors.getPost.mockReturnValueOnce(true);
|
|
mockServer.emit('message', JSON.stringify(messageFor(otherChannelId)));
|
|
expect(emit).not.toHaveBeenCalled();
|
|
|
|
// Post exists and is for current channel
|
|
PostSelectors.getPost.mockReturnValueOnce(true);
|
|
mockServer.emit('message', JSON.stringify(messageFor(currentChannelId)));
|
|
expect(emit).not.toHaveBeenCalled();
|
|
|
|
// Post does not exist and is for current channel
|
|
PostSelectors.getPost.mockReturnValueOnce(false);
|
|
mockServer.emit('message', JSON.stringify(messageFor(currentChannelId)));
|
|
expect(emit).toHaveBeenCalledWith(WebsocketEvents.INCREASE_POST_VISIBILITY_BY_ONE);
|
|
});
|
|
|
|
it('Websocket Handle New Post if status is manually set do not set to online', async () => {
|
|
const userId = TestHelper.generateId();
|
|
|
|
store = await configureStore({
|
|
entities: {
|
|
users: {
|
|
statuses: {
|
|
[userId]: General.DND,
|
|
},
|
|
isManualStatus: {
|
|
[userId]: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
await store.dispatch(Actions.init({websocketUrl: Client4.getUrl().replace(/^http:/, 'ws:')}));
|
|
|
|
const channelId = TestHelper.basicChannel.id;
|
|
const message = JSON.stringify({
|
|
event: WebsocketEvents.POSTED,
|
|
data: {
|
|
channel_display_name: TestHelper.basicChannel.display_name,
|
|
channel_name: TestHelper.basicChannel.name,
|
|
channel_type: 'O',
|
|
post: `{"id": "71k8gz5ompbpfkrzaxzodffj8w", "create_at": 1508245311774, "update_at": 1508245311774, "edit_at": 0, "delete_at": 0, "is_pinned": false, "user_id": "${userId}", "channel_id": "${channelId}", "root_id": "", "parent_id": "", "original_id": "", "message": "Unit Test", "type": "", "props": {}, "hashtags": "", "pending_post_id": "t36kso9nwtdhbm8dbkd6g4eeby: 1508245311749"}`,
|
|
sender_name: TestHelper.basicUser.username,
|
|
team_id: TestHelper.basicTeam.id,
|
|
},
|
|
broadcast: {
|
|
omit_users: null,
|
|
user_id: userId,
|
|
channel_id: channelId,
|
|
team_id: '',
|
|
},
|
|
seq: 2,
|
|
});
|
|
|
|
mockServer.emit('message', message);
|
|
const entities = store.getState().entities;
|
|
const statuses = entities.users.statuses;
|
|
assert.equal(statuses[userId], General.DND);
|
|
});
|
|
|
|
it('Websocket Handle Post Edited', async () => {
|
|
const post = {id: '71k8gz5ompbpfkrzaxzodffj8w'};
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.POST_EDITED, data: {post: `{"id": "71k8gz5ompbpfkrzaxzodffj8w","create_at": 1508245311774,"update_at": 1585236976007,"edit_at": 1585236976007,"delete_at": 0,"is_pinned": false,"user_id": "${TestHelper.basicUser.id}","channel_id": "${TestHelper.basicChannel.id}","root_id": "","parent_id": "","original_id": "","message": "Unit Test (edited)","type": "","props": {},"hashtags": "","pending_post_id": ""}`}, broadcast: {omit_users: null, user_id: '', channel_id: '18k9ffsuci8xxm7ak68zfdyrce', team_id: ''}, seq: 2}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const {posts} = store.getState().entities.posts;
|
|
assert.ok(posts);
|
|
assert.ok(posts[post.id]);
|
|
assert.ok(posts[post.id].message.indexOf('(edited)') > -1);
|
|
});
|
|
|
|
it('Websocket Handle Post Deleted', async () => {
|
|
const post = TestHelper.fakePost();
|
|
post.channel_id = TestHelper.basicChannel.id;
|
|
|
|
post.id = '71k8gz5ompbpfkrzaxzodffj8w';
|
|
store.dispatch(PostActions.receivedPost(post));
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.POST_DELETED, data: {post: `{"id": "71k8gz5ompbpfkrzaxzodffj8w","create_at": 1508245311774,"update_at": 1508247709215,"edit_at": 1508247709215,"delete_at": 0,"is_pinned": false,"user_id": "${TestHelper.basicUser.id}","channel_id": "${post.channel_id}","root_id": "","parent_id": "","original_id": "","message": "Unit Test","type": "","props": {},"hashtags": "","pending_post_id": ""}`}, broadcast: {omit_users: null, user_id: '', channel_id: '18k9ffsuci8xxm7ak68zfdyrce', team_id: ''}, seq: 7}));
|
|
|
|
const entities = store.getState().entities;
|
|
const {posts} = entities.posts;
|
|
assert.strictEqual(posts[post.id].state, Posts.POST_DELETED);
|
|
});
|
|
|
|
it('Websocket handle Post Unread', async () => {
|
|
const teamId = TestHelper.generateId();
|
|
const channelId = TestHelper.generateId();
|
|
const userId = TestHelper.generateId();
|
|
|
|
store = await configureStore({
|
|
entities: {
|
|
channels: {
|
|
channels: {
|
|
[channelId]: {id: channelId},
|
|
},
|
|
myMembers: {
|
|
[channelId]: {msg_count: 10, mention_count: 0, last_viewed_at: 0},
|
|
},
|
|
},
|
|
teams: {
|
|
myMembers: {
|
|
[teamId]: {msg_count: 10, mention_count: 0},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
await store.dispatch(Actions.init({websocketUrl: Client4.getUrl().replace(/^http:/, 'ws:')}));
|
|
|
|
mockServer.emit('message', JSON.stringify({
|
|
event: WebsocketEvents.POST_UNREAD,
|
|
data: {
|
|
last_viewed_at: 25,
|
|
msg_count: 3,
|
|
mention_count: 2,
|
|
delta_msg: 7,
|
|
},
|
|
broadcast: {omit_users: null, user_id: userId, channel_id: channelId, team_id: teamId},
|
|
seq: 7,
|
|
}));
|
|
|
|
const state = store.getState();
|
|
assert.equal(state.entities.channels.manuallyUnread[channelId], true);
|
|
assert.equal(state.entities.channels.myMembers[channelId].msg_count, 3);
|
|
assert.equal(state.entities.channels.myMembers[channelId].mention_count, 2);
|
|
assert.equal(state.entities.channels.myMembers[channelId].last_viewed_at, 25);
|
|
assert.equal(state.entities.teams.myMembers[teamId].msg_count, 3);
|
|
assert.equal(state.entities.teams.myMembers[teamId].mention_count, 2);
|
|
});
|
|
|
|
it('Websocket handle Post Unread When marked on the same client', async () => {
|
|
const teamId = TestHelper.generateId();
|
|
const channelId = TestHelper.generateId();
|
|
const userId = TestHelper.generateId();
|
|
|
|
store = await configureStore({
|
|
entities: {
|
|
channels: {
|
|
channels: {
|
|
[channelId]: {id: channelId},
|
|
},
|
|
myMembers: {
|
|
[channelId]: {msg_count: 5, mention_count: 4, last_viewed_at: 14},
|
|
},
|
|
manuallyUnread: {
|
|
[channelId]: true,
|
|
},
|
|
},
|
|
teams: {
|
|
myMembers: {
|
|
[teamId]: {msg_count: 5, mention_count: 4},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
await store.dispatch(Actions.init({websocketUrl: Client4.getUrl().replace(/^http:/, 'ws:')}));
|
|
|
|
mockServer.emit('message', JSON.stringify({
|
|
event: WebsocketEvents.POST_UNREAD,
|
|
data: {
|
|
last_viewed_at: 25,
|
|
msg_count: 5,
|
|
mention_count: 4,
|
|
delta_msg: 1,
|
|
},
|
|
broadcast: {omit_users: null, user_id: userId, channel_id: channelId, team_id: teamId},
|
|
seq: 17,
|
|
}));
|
|
|
|
const state = store.getState();
|
|
assert.equal(state.entities.channels.manuallyUnread[channelId], true);
|
|
assert.equal(state.entities.channels.myMembers[channelId].msg_count, 5);
|
|
assert.equal(state.entities.channels.myMembers[channelId].mention_count, 4);
|
|
assert.equal(state.entities.channels.myMembers[channelId].last_viewed_at, 14);
|
|
assert.equal(state.entities.teams.myMembers[teamId].msg_count, 5);
|
|
assert.equal(state.entities.teams.myMembers[teamId].mention_count, 4);
|
|
});
|
|
|
|
it('Websocket Handle Reaction Added to Post', async () => {
|
|
const emoji = '+1';
|
|
const post = {id: 'w7yo9377zbfi9mgiq5gbfpn3ha'};
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.REACTION_ADDED, data: {reaction: `{"user_id":"${TestHelper.basicUser.id}","post_id":"w7yo9377zbfi9mgiq5gbfpn3ha","emoji_name":"${emoji}","create_at":1508249125852}`}, broadcast: {omit_users: null, user_id: '', channel_id: TestHelper.basicChannel.id, team_id: ''}, seq: 12}));
|
|
|
|
await TestHelper.wait(300);
|
|
const nextEntities = store.getState().entities;
|
|
const {reactions} = nextEntities.posts;
|
|
const reactionsForPost = reactions[post.id];
|
|
|
|
assert.ok(reactionsForPost.hasOwnProperty(`${TestHelper.basicUser.id}-${emoji}`));
|
|
});
|
|
|
|
// If we move this test lower it will fail cause of a permissions issue
|
|
it('Websocket handle team updated', async () => {
|
|
const team = {id: '55pfercbm7bsmd11p5cjpgsbwr'};
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.UPDATE_TEAM, data: {team: `{"id":"55pfercbm7bsmd11p5cjpgsbwr","create_at":1495553950859,"update_at":1508250370054,"delete_at":0,"display_name":"${TestHelper.basicTeam.display_name}","name":"${TestHelper.basicTeam.name}","description":"description","email":"","type":"O","company_name":"","allowed_domains":"","invite_id":"m93f54fu5bfntewp8ctwonw19w","allow_open_invite":true}`}, broadcast: {omit_users: null, user_id: '', channel_id: '', team_id: ''}, seq: 26}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const entities = store.getState().entities;
|
|
const {teams} = entities.teams;
|
|
const updated = teams[team.id];
|
|
assert.ok(updated);
|
|
assert.strictEqual(updated.allow_open_invite, true);
|
|
});
|
|
|
|
it('Websocket handle team patched', async () => {
|
|
const team = {id: '55pfercbm7bsmd11p5cjpgsbwr'};
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.UPDATE_TEAM, data: {team: `{"id":"55pfercbm7bsmd11p5cjpgsbwr","create_at":1495553950859,"update_at":1508250370054,"delete_at":0,"display_name":"${TestHelper.basicTeam.display_name}","name":"${TestHelper.basicTeam.name}","description":"description","email":"","type":"O","company_name":"","allowed_domains":"","invite_id":"m93f54fu5bfntewp8ctwonw19w","allow_open_invite":true}`}, broadcast: {omit_users: null, user_id: '', channel_id: '', team_id: ''}, seq: 26}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const entities = store.getState().entities;
|
|
const {teams} = entities.teams;
|
|
const updated = teams[team.id];
|
|
assert.ok(updated);
|
|
assert.strictEqual(updated.allow_open_invite, true);
|
|
});
|
|
|
|
it('WebSocket Leave Team', async () => {
|
|
const team = TestHelper.basicTeam;
|
|
store.dispatch(batchActions([
|
|
{type: UserTypes.RECEIVED_ME, data: TestHelper.basicUser},
|
|
{type: TeamTypes.RECEIVED_TEAM, data: TestHelper.basicTeam},
|
|
{type: TeamTypes.RECEIVED_MY_TEAM_MEMBER, data: TestHelper.basicTeamMember},
|
|
]));
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.LEAVE_TEAM, data: {team_id: team.id, user_id: TestHelper.basicUser.id}, broadcast: {omit_users: null, user_id: '', channel_id: '', team_id: team.id}, seq: 35}));
|
|
|
|
const {myMembers} = store.getState().entities.teams;
|
|
assert.ifError(myMembers[team.id]);
|
|
});
|
|
|
|
it('Websocket Handle User Added', async () => {
|
|
const user = {...TestHelper.fakeUser(), id: TestHelper.generateId()};
|
|
store.dispatch({type: UserTypes.RECEIVED_PROFILE_IN_CHANNEL, data: {id: TestHelper.basicChannel.id, user_id: user.id}});
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.USER_ADDED, data: {team_id: TestHelper.basicTeam.id, user_id: user.id}, broadcast: {omit_users: null, user_id: '', channel_id: TestHelper.basicChannel.id, team_id: ''}, seq: 42}));
|
|
|
|
const entities = store.getState().entities;
|
|
const profilesInChannel = entities.users.profilesInChannel;
|
|
assert.ok(profilesInChannel[TestHelper.basicChannel.id].has(user.id));
|
|
});
|
|
|
|
it('Websocket Handle User Removed', async () => {
|
|
const user = {...TestHelper.fakeUser(), id: TestHelper.generateId()};
|
|
store.dispatch({type: UserTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL, data: {id: TestHelper.basicChannel.id, user_id: user.id}});
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.USER_REMOVED, data: {remover_id: TestHelper.basicUser.id, user_id: user.id}, broadcast: {omit_users: null, user_id: '', channel_id: TestHelper.basicChannel.id, team_id: ''}, seq: 42}));
|
|
|
|
const state = store.getState();
|
|
const entities = state.entities;
|
|
const profilesNotInChannel = entities.users.profilesNotInChannel;
|
|
|
|
assert.ok(profilesNotInChannel[TestHelper.basicChannel.id].has(user.id));
|
|
});
|
|
|
|
it('Websocket Handle User Removed when Current is Guest', async () => {
|
|
const basicGuestUser = TestHelper.fakeUserWithId();
|
|
basicGuestUser.roles = 'system_guest';
|
|
|
|
const user = {...TestHelper.fakeUser(), id: TestHelper.generateId()};
|
|
|
|
// add user first
|
|
store.dispatch({type: UserTypes.RECEIVED_PROFILE_IN_CHANNEL, data: {id: TestHelper.basicChannel.id, user_id: user.id}});
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.USER_ADDED, data: {team_id: TestHelper.basicTeam.id, user_id: user.id}, broadcast: {omit_users: null, user_id: '', channel_id: TestHelper.basicChannel.id, team_id: ''}, seq: 42}));
|
|
|
|
assert.ok(store.getState().entities.users.profilesInChannel[TestHelper.basicChannel.id].has(user.id));
|
|
|
|
// remove user
|
|
store.dispatch({type: UserTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL, data: {id: TestHelper.basicChannel.id, user_id: user.id}});
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.USER_REMOVED, data: {remover_id: basicGuestUser.id, user_id: user.id}, broadcast: {omit_users: null, user_id: '', channel_id: TestHelper.basicChannel.id, team_id: ''}, seq: 42}));
|
|
|
|
assert.ok(!store.getState().entities.users.profilesInChannel[TestHelper.basicChannel.id].has(user.id));
|
|
});
|
|
|
|
it('Websocket Handle User Updated', async () => {
|
|
const user = {...TestHelper.fakeUser(), id: TestHelper.generateId()};
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.USER_UPDATED, data: {user: {id: user.id, create_at: 1495570297229, update_at: 1508253268652, delete_at: 0, username: 'tim', auth_data: '', auth_service: '', email: 'tim@bladekick.com', nickname: '', first_name: 'tester4', last_name: '', position: '', roles: 'system_user', locale: 'en'}}, broadcast: {omit_users: null, user_id: '', channel_id: '', team_id: ''}, seq: 53}));
|
|
|
|
store.subscribe(() => {
|
|
const state = store.getState();
|
|
const entities = state.entities;
|
|
const profiles = entities.users.profiles;
|
|
|
|
assert.strictEqual(profiles[user.id].first_name, 'tester4');
|
|
});
|
|
});
|
|
|
|
it('Websocket Handle Channel Member Updated', async () => {
|
|
const channelMember = TestHelper.basicChannelMember;
|
|
const mockStore = configureMockStore([thunk]);
|
|
const st = mockStore(initial_state);
|
|
await st.dispatch(Actions.init({websocketUrl: Client4.getUrl().replace(/^http:/, 'ws:')}));
|
|
channelMember.roles = 'channel_user channel_admin';
|
|
const rolesToLoad = channelMember.roles.split(' ');
|
|
|
|
nock(Client4.getRolesRoute()).
|
|
post('/names', JSON.stringify(rolesToLoad)).
|
|
reply(200, rolesToLoad);
|
|
|
|
mockServer.emit('message', JSON.stringify({
|
|
event: WebsocketEvents.CHANNEL_MEMBER_UPDATED,
|
|
data: {
|
|
channelMember: JSON.stringify(channelMember),
|
|
},
|
|
}));
|
|
|
|
await TestHelper.wait(300);
|
|
const storeActions = st.getActions();
|
|
const batch = storeActions.find((a) => a.type === 'BATCH_WS_CHANNEL_MEMBER_UPDATE');
|
|
expect(batch).not.toBeNull();
|
|
const memberAction = batch.payload.find((a) => a.type === ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER);
|
|
expect(memberAction).not.toBeNull();
|
|
const rolesActions = batch.payload.find((a) => a.type === RoleTypes.RECEIVED_ROLES);
|
|
expect(rolesActions).not.toBeNull();
|
|
expect(rolesActions.data).toEqual(rolesToLoad);
|
|
});
|
|
|
|
it('Websocket Handle Channel Created', async () => {
|
|
const channelId = TestHelper.basicChannel.id;
|
|
const channel = {id: channelId, display_name: 'test', name: TestHelper.basicChannel.name};
|
|
await store.dispatch(Actions.init({websocketUrl: Client4.getUrl().replace(/^http:/, 'ws:')}));
|
|
store.dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: channel});
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.CHANNEL_CREATED, data: {channel_id: channelId, team_id: TestHelper.basicTeam.id}, broadcast: {omit_users: null, user_id: 't36kso9nwtdhbm8dbkd6g4eeby', channel_id: '', team_id: ''}, seq: 57}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const state = store.getState();
|
|
const entities = state.entities;
|
|
const {channels} = entities.channels;
|
|
|
|
assert.ok(channels[channel.id]);
|
|
});
|
|
|
|
it('Websocket Handle Channel Updated', async () => {
|
|
const channelName = 'Test name';
|
|
const channelId = TestHelper.basicChannel.id;
|
|
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.CHANNEL_UPDATED, data: {channel: `{"id":"${channelId}","create_at":1508253647983,"update_at":1508254198797,"delete_at":0,"team_id":"55pfercbm7bsmd11p5cjpgsbwr","type":"O","display_name":"${channelName}","name":"${TestHelper.basicChannel.name}","header":"header","purpose":"","last_post_at":1508253648004,"total_msg_count":0,"extra_update_at":1508253648001,"creator_id":"${TestHelper.basicUser.id}"}`}, broadcast: {omit_users: null, user_id: '', channel_id: channelId, team_id: ''}, seq: 62}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const state = store.getState();
|
|
const entities = state.entities;
|
|
const {channels} = entities.channels;
|
|
|
|
assert.strictEqual(channels[channelId].display_name, channelName);
|
|
});
|
|
|
|
it('Websocket Handle Channel Deleted', async () => {
|
|
const time = Date.now();
|
|
await store.dispatch(TeamActions.selectTeam(TestHelper.basicTeam));
|
|
await store.dispatch(ChannelActions.selectChannel(TestHelper.basicChannel.id));
|
|
|
|
store.dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: {id: TestHelper.generateId(), name: General.DEFAULT_CHANNEL, team_id: TestHelper.basicTeam.id, display_name: General.DEFAULT_CHANNEL}});
|
|
store.dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: TestHelper.basicChannel});
|
|
|
|
nock(Client4.getUserRoute('me')).
|
|
get(`/teams/${TestHelper.basicTeam.id}/channels/members`).
|
|
reply(201, [{user_id: TestHelper.basicUser.id, channel_id: TestHelper.basicChannel.id}]);
|
|
|
|
mockServer.emit('message', JSON.stringify({
|
|
event: WebsocketEvents.CHANNEL_DELETED,
|
|
data: {
|
|
channel_id: TestHelper.basicChannel.id,
|
|
delete_at: time,
|
|
},
|
|
broadcast: {
|
|
omit_users: null,
|
|
user_id: '',
|
|
channel_id: '',
|
|
team_id: TestHelper.basicTeam.id,
|
|
},
|
|
seq: 68,
|
|
}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const state = store.getState();
|
|
const entities = state.entities;
|
|
const {channels, currentChannelId} = entities.channels;
|
|
|
|
assert.ok(channels[currentChannelId].name === General.DEFAULT_CHANNEL);
|
|
});
|
|
|
|
it('Websocket Handle Channel Unarchive', async () => {
|
|
await store.dispatch(TeamActions.selectTeam(TestHelper.basicTeam));
|
|
await store.dispatch(ChannelActions.selectChannel(TestHelper.basicChannel.id));
|
|
|
|
store.dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: {id: TestHelper.generateId(), name: General.DEFAULT_CHANNEL, team_id: TestHelper.basicTeam.id, display_name: General.DEFAULT_CHANNEL}});
|
|
store.dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: TestHelper.basicChannel});
|
|
|
|
nock(Client4.getUserRoute('me')).
|
|
get(`/teams/${TestHelper.basicTeam.id}/channels/members`).
|
|
reply(201, [{user_id: TestHelper.basicUser.id, channel_id: TestHelper.basicChannel.id}]);
|
|
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.CHANNEL_UNARCHIVE, data: {channel_id: TestHelper.basicChannel.id}, broadcast: {omit_users: null, user_id: '', channel_id: '', team_id: TestHelper.basicTeam.id}, seq: 68}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const state = store.getState();
|
|
const entities = state.entities;
|
|
const {channels, currentChannelId} = entities.channels;
|
|
|
|
assert.ok(channels[currentChannelId].delete_at === 0);
|
|
});
|
|
|
|
it('Websocket Handle Direct Channel', async () => {
|
|
const channel = {id: TestHelper.generateId(), name: TestHelper.basicUser.id + '__' + TestHelper.generateId(), type: 'D'};
|
|
|
|
nock(Client4.getChannelsRoute()).
|
|
get(`/${channel.id}/members/me`).
|
|
reply(201, {user_id: TestHelper.basicUser.id, channel_id: channel.id});
|
|
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.DIRECT_ADDED, data: {teammate_id: 'btaxe5msnpnqurayosn5p8twuw'}, broadcast: {omit_users: null, user_id: '', channel_id: channel.id, team_id: ''}, seq: 2}));
|
|
store.dispatch({type: ChannelTypes.RECEIVED_CHANNEL, data: channel});
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const {channels} = store.getState().entities.channels;
|
|
assert.ok(Object.keys(channels).length);
|
|
});
|
|
|
|
it('Websocket handle user added to team', async () => {
|
|
const team = {id: TestHelper.generateId()};
|
|
|
|
nock(Client4.getBaseRoute()).
|
|
get(`/teams/${team.id}`).
|
|
reply(200, team);
|
|
|
|
nock(Client4.getBaseRoute()).
|
|
get('/users/me/teams/unread').
|
|
reply(200, [{team_id: team.id, msg_count: 0, mention_count: 0}]);
|
|
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.ADDED_TO_TEAM, data: {team_id: team.id, user_id: TestHelper.basicUser.id}, broadcast: {omit_users: null, user_id: TestHelper.basicUser.id, channel_id: '', team_id: ''}, seq: 2}));
|
|
|
|
await TestHelper.wait(300);
|
|
|
|
const {teams, myMembers} = store.getState().entities.teams;
|
|
assert.ok(teams[team.id]);
|
|
assert.ok(myMembers[team.id]);
|
|
|
|
const member = myMembers[team.id];
|
|
assert.ok(member.hasOwnProperty('mention_count'));
|
|
});
|
|
|
|
it('Websocket handle emoji added', async () => {
|
|
const created = {id: '1mmgakhhupfgfm8oug6pooc5no'};
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.EMOJI_ADDED, data: {emoji: `{"id":"1mmgakhhupfgfm8oug6pooc5no","create_at":1508263941321,"update_at":1508263941321,"delete_at":0,"creator_id":"t36kso9nwtdhbm8dbkd6g4eeby","name":"${TestHelper.generateId()}"}`}, broadcast: {omit_users: null, user_id: '', channel_id: '', team_id: ''}, seq: 2}));
|
|
|
|
await TestHelper.wait(200);
|
|
|
|
const state = store.getState();
|
|
|
|
const emojis = state.entities.emojis.customEmoji;
|
|
assert.ok(emojis);
|
|
assert.ok(emojis[created.id]);
|
|
});
|
|
|
|
it('handle license changed', async () => {
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.LICENSE_CHANGED, data: {license: {IsLicensed: 'true'}}}));
|
|
|
|
await TestHelper.wait(200);
|
|
|
|
const state = store.getState();
|
|
|
|
const license = state.entities.general.license;
|
|
assert.ok(license);
|
|
assert.ok(license.IsLicensed);
|
|
});
|
|
|
|
it('handle config changed', async () => {
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.CONFIG_CHANGED, data: {config: {EnableCustomEmoji: 'true', EnableLinkPreviews: 'false'}}}));
|
|
|
|
await TestHelper.wait(200);
|
|
|
|
const state = store.getState();
|
|
|
|
const config = state.entities.general.config;
|
|
assert.ok(config);
|
|
assert.ok(config.EnableCustomEmoji === 'true');
|
|
assert.ok(config.EnableLinkPreviews === 'false');
|
|
});
|
|
|
|
it('handle open dialog', async () => {
|
|
mockServer.emit('message', JSON.stringify({event: WebsocketEvents.OPEN_DIALOG, data: {dialog: JSON.stringify({url: 'someurl', trigger_id: 'sometriggerid', dialog: {}})}}));
|
|
|
|
await TestHelper.wait(200);
|
|
|
|
const state = store.getState();
|
|
|
|
const dialog = state.entities.integrations.dialog;
|
|
assert.ok(dialog);
|
|
assert.ok(dialog.url === 'someurl');
|
|
assert.ok(dialog.trigger_id === 'sometriggerid');
|
|
assert.ok(dialog.dialog);
|
|
});
|
|
});
|
|
|
|
describe('Actions.Websocket doReconnect', () => {
|
|
const mockStore = configureMockStore([thunk]);
|
|
const me = TestHelper.fakeUserWithId();
|
|
const team = TestHelper.fakeTeamWithId();
|
|
const teamMember = TestHelper.fakeTeamMember(me.id, team.id);
|
|
const channel1 = TestHelper.fakeChannelWithId(team.id);
|
|
const channel2 = TestHelper.fakeChannelWithId(team.id);
|
|
const cMember1 = TestHelper.fakeChannelMember(me.id, channel1.id);
|
|
const cMember2 = TestHelper.fakeChannelMember(me.id, channel2.id);
|
|
|
|
const currentTeamId = team.id;
|
|
const currentUserId = me.id;
|
|
const currentChannelId = channel1.id;
|
|
|
|
const initialState = {
|
|
entities: {
|
|
general: {
|
|
config: {},
|
|
},
|
|
teams: {
|
|
currentTeamId,
|
|
myMembers: {
|
|
[currentTeamId]: teamMember,
|
|
},
|
|
teams: {
|
|
[currentTeamId]: team,
|
|
},
|
|
},
|
|
channels: {
|
|
currentChannelId,
|
|
channels: {
|
|
currentChannelId: channel1,
|
|
},
|
|
},
|
|
users: {
|
|
currentUserId,
|
|
profiles: {
|
|
[me.id]: me,
|
|
},
|
|
},
|
|
preferences: {
|
|
myPreferences: {},
|
|
},
|
|
posts: {
|
|
posts: {},
|
|
postsInChannel: {},
|
|
},
|
|
},
|
|
websocket: {
|
|
connected: false,
|
|
lastConnectAt: 0,
|
|
lastDisconnectAt: 0,
|
|
},
|
|
};
|
|
|
|
beforeAll(async () => {
|
|
return TestHelper.initBasic(Client4);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
nock(Client4.getBaseRoute()).
|
|
get('/users/me').
|
|
reply(200, me);
|
|
|
|
nock(Client4.getUserRoute('me')).
|
|
get('/teams').
|
|
reply(200, [team]);
|
|
|
|
nock(Client4.getUserRoute('me')).
|
|
get('/teams/unread').
|
|
reply(200, [{id: team.id, msg_count: 0, mention_count: 0}]);
|
|
|
|
nock(Client4.getBaseRoute()).
|
|
get('/users/me/preferences').
|
|
reply(200, []);
|
|
|
|
nock(Client4.getUserRoute('me')).
|
|
get(`/teams/${team.id}/channels/members`).
|
|
reply(200, [cMember1, cMember2]);
|
|
|
|
nock(Client4.getChannelRoute(channel1.id)).
|
|
get(`/posts?page=0&per_page=${Posts.POST_CHUNK_SIZE}`).
|
|
reply(200, {
|
|
posts: {
|
|
post1: {id: 'post1', create_at: 0, message: 'hey'},
|
|
},
|
|
order: ['post1'],
|
|
});
|
|
});
|
|
|
|
afterAll(async () => {
|
|
Actions.close()();
|
|
await TestHelper.tearDown();
|
|
});
|
|
|
|
it('handle doReconnect', async () => {
|
|
const state = {...initialState};
|
|
const testStore = await mockStore(state);
|
|
const timestamp = 1000;
|
|
const expectedActions = [
|
|
GeneralTypes.WEBSOCKET_SUCCESS,
|
|
'BATCH_WS_RECONNECT',
|
|
'BATCH_GET_POSTS',
|
|
];
|
|
|
|
mockConfigRequest();
|
|
mockTeamMemberRequest([teamMember]);
|
|
mockChanelsRequest(team.id, [channel1, channel2]);
|
|
|
|
let rolesToLoad = Array.from(new Set(me.roles.split(' ').
|
|
concat(teamMember.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
rolesToLoad = Array.from(new Set(cMember1.roles.split(' ').
|
|
concat(cMember2.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
await testStore.dispatch(Actions.doReconnect(timestamp));
|
|
await TestHelper.wait(300);
|
|
const actionTypes = testStore.getActions().map((a) => a.type);
|
|
expect(actionTypes).toEqual(expectedActions);
|
|
});
|
|
|
|
it('handle doReconnect after the current channel was archived or the user left it', async () => {
|
|
const state = {
|
|
...initialState,
|
|
entities: {
|
|
...initialState.entities,
|
|
channels: {
|
|
...initialState.entities.channels,
|
|
currentChannelId: 'channel-3',
|
|
},
|
|
},
|
|
};
|
|
const testStore = await mockStore(state);
|
|
const timestamp = 1000;
|
|
const expectedActions = [
|
|
GeneralTypes.WEBSOCKET_SUCCESS,
|
|
'BATCH_WS_RECONNECT',
|
|
];
|
|
const expectedMissingActions = [
|
|
'BATCH_GET_POSTS',
|
|
];
|
|
|
|
mockConfigRequest();
|
|
mockTeamMemberRequest([teamMember]);
|
|
mockChanelsRequest(team.id, [channel1, channel2]);
|
|
|
|
let rolesToLoad = Array.from(new Set(me.roles.split(' ').
|
|
concat(teamMember.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
rolesToLoad = Array.from(new Set(cMember1.roles.split(' ').
|
|
concat(cMember2.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
await testStore.dispatch(Actions.doReconnect(timestamp));
|
|
await TestHelper.wait(300);
|
|
|
|
const actions = testStore.getActions().map((a) => a.type);
|
|
|
|
expect(actions).toEqual(expect.arrayContaining(expectedActions));
|
|
expect(actions).not.toEqual(expect.arrayContaining(expectedMissingActions));
|
|
});
|
|
|
|
it('handle doReconnect after the current channel was archived and setting is on', async () => {
|
|
const archived = {
|
|
...channel1,
|
|
delete_at: 123,
|
|
};
|
|
const state = {
|
|
...initialState,
|
|
channels: {
|
|
currentChannelId,
|
|
channels: {
|
|
currentChannelId: archived,
|
|
},
|
|
},
|
|
};
|
|
const testStore = await mockStore(state);
|
|
const timestamp = 1000;
|
|
const expectedActions = [
|
|
GeneralTypes.WEBSOCKET_SUCCESS,
|
|
'BATCH_WS_RECONNECT',
|
|
];
|
|
|
|
mockConfigRequest({ExperimentalViewArchivedChannels: 'true'});
|
|
mockTeamMemberRequest([teamMember]);
|
|
mockChanelsRequest(team.id, [archived, channel2]);
|
|
|
|
let rolesToLoad = Array.from(new Set(me.roles.split(' ').
|
|
concat(teamMember.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
rolesToLoad = Array.from(new Set(cMember1.roles.split(' ').
|
|
concat(cMember2.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
await testStore.dispatch(Actions.doReconnect(timestamp));
|
|
await TestHelper.wait(300);
|
|
|
|
const actions = testStore.getActions().map((a) => a.type);
|
|
expect(actions).toEqual(expect.arrayContaining(expectedActions));
|
|
});
|
|
|
|
it('handle doReconnect after the current channel was archived and setting is off', async () => {
|
|
const archived = {
|
|
...channel1,
|
|
delete_at: 123,
|
|
};
|
|
|
|
const state = {
|
|
...initialState,
|
|
channels: {
|
|
currentChannelId,
|
|
channels: {
|
|
currentChannelId: archived,
|
|
},
|
|
},
|
|
};
|
|
const testStore = await mockStore(state);
|
|
const timestamp = 1000;
|
|
const expectedActions = [
|
|
GeneralTypes.WEBSOCKET_SUCCESS,
|
|
'BATCH_WS_RECONNECT',
|
|
];
|
|
const expectedMissingActions = [
|
|
'BATCH_GET_POSTS',
|
|
];
|
|
|
|
mockConfigRequest({ExperimentalViewArchivedChannels: 'false'});
|
|
mockTeamMemberRequest([teamMember]);
|
|
mockChanelsRequest(team.id, [archived, channel2]);
|
|
|
|
let rolesToLoad = Array.from(new Set(me.roles.split(' ').
|
|
concat(teamMember.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
rolesToLoad = Array.from(new Set(cMember1.roles.split(' ').
|
|
concat(cMember2.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
await testStore.dispatch(Actions.doReconnect(timestamp));
|
|
await TestHelper.wait(300);
|
|
|
|
const actions = testStore.getActions().map((a) => a.type);
|
|
expect(actions).toEqual(expectedActions);
|
|
expect(actions).not.toEqual(expect.arrayContaining(expectedMissingActions));
|
|
});
|
|
|
|
it('handle doReconnect after user left current team', async () => {
|
|
const state = {...initialState};
|
|
state.entities.teams.myMembers = {};
|
|
const testStore = await mockStore(state);
|
|
const timestamp = 1000;
|
|
const expectedActions = [
|
|
GeneralTypes.WEBSOCKET_SUCCESS,
|
|
'BATCH_WS_LEAVE_TEAM',
|
|
'BATCH_WS_RECONNECT',
|
|
];
|
|
const expectedMissingActions = [
|
|
'BATCH_GET_POSTS',
|
|
];
|
|
|
|
mockConfigRequest();
|
|
mockTeamMemberRequest([]);
|
|
mockChanelsRequest(team.id, [channel1, channel2]);
|
|
|
|
let rolesToLoad = me.roles.split(' ');
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
rolesToLoad = Array.from(new Set(cMember1.roles.split(' ').
|
|
concat(cMember2.roles.split(' '))));
|
|
mockRolesRequest(rolesToLoad);
|
|
|
|
await testStore.dispatch(Actions.doReconnect(timestamp));
|
|
await TestHelper.wait(300);
|
|
const actions = testStore.getActions().map((a) => a.type);
|
|
expect(actions).toEqual(expectedActions);
|
|
expect(actions).not.toEqual(expect.arrayContaining(expectedMissingActions));
|
|
});
|
|
});
|
|
|
|
describe('Actions.Websocket notVisibleUsersActions', () => {
|
|
const mockStore = configureMockStore([thunk]);
|
|
|
|
const channel1 = TestHelper.fakeChannelWithId('');
|
|
const channel2 = TestHelper.fakeChannelWithId('');
|
|
|
|
const me = TestHelper.fakeUserWithId();
|
|
const user = TestHelper.fakeUserWithId();
|
|
const user2 = TestHelper.fakeUserWithId();
|
|
const user3 = TestHelper.fakeUserWithId();
|
|
const user4 = TestHelper.fakeUserWithId();
|
|
const user5 = TestHelper.fakeUserWithId();
|
|
|
|
it('should do nothing if the known users and the profiles list are the same', () => {
|
|
const membersInChannel = {
|
|
[channel1.id]: {
|
|
[user.id]: {channel_id: channel1.id, user_id: user.id},
|
|
[user2.id]: {channel_id: channel1.id, user_id: user2.id},
|
|
},
|
|
[channel2.id]: {
|
|
[user3.id]: {channel_id: channel2.id, user_id: user3.id},
|
|
},
|
|
};
|
|
|
|
const profiles = {
|
|
[me.id]: me,
|
|
[user.id]: user,
|
|
[user2.id]: user2,
|
|
[user3.id]: user3,
|
|
};
|
|
|
|
const state = {
|
|
entities: {
|
|
channels: {
|
|
membersInChannel,
|
|
},
|
|
users: {
|
|
currentUserId: me.id,
|
|
profiles,
|
|
},
|
|
},
|
|
};
|
|
|
|
const actions = Actions.notVisibleUsersActions(state);
|
|
expect(actions.length).toEqual(0);
|
|
});
|
|
|
|
it('should do nothing if there are known users in my memberships but not in the profiles list', () => {
|
|
const membersInChannel = {
|
|
[channel1.id]: {
|
|
[user.id]: {channel_id: channel1.id, user_id: user.id},
|
|
[user2.id]: {channel_id: channel1.id, user_id: user2.id},
|
|
},
|
|
[channel2.id]: {
|
|
[user3.id]: {channel_id: channel2.id, user_id: user3.id},
|
|
},
|
|
};
|
|
|
|
const profiles = {
|
|
[me.id]: me,
|
|
[user3.id]: user3,
|
|
};
|
|
|
|
const state = {
|
|
entities: {
|
|
channels: {
|
|
membersInChannel,
|
|
},
|
|
users: {
|
|
currentUserId: me.id,
|
|
profiles,
|
|
},
|
|
},
|
|
};
|
|
|
|
const actions = Actions.notVisibleUsersActions(state);
|
|
expect(actions.length).toEqual(0);
|
|
});
|
|
|
|
it('should remove the users if there are unknown users in the profiles list', async () => {
|
|
const membersInChannel = {
|
|
[channel1.id]: {
|
|
[user.id]: {channel_id: channel1.id, user_id: user.id},
|
|
},
|
|
[channel2.id]: {
|
|
[user3.id]: {channel_id: channel2.id, user_id: user3.id},
|
|
},
|
|
};
|
|
|
|
const profiles = {
|
|
[me.id]: me,
|
|
[user.id]: user,
|
|
[user2.id]: user2,
|
|
[user3.id]: user3,
|
|
[user4.id]: user4,
|
|
[user5.id]: user5,
|
|
};
|
|
|
|
const state = {
|
|
entities: {
|
|
channels: {
|
|
membersInChannel,
|
|
},
|
|
users: {
|
|
currentUserId: me.id,
|
|
profiles,
|
|
},
|
|
},
|
|
};
|
|
|
|
const expectedAction = [
|
|
{type: UserTypes.PROFILE_NO_LONGER_VISIBLE, data: {user_id: user2.id}},
|
|
{type: UserTypes.PROFILE_NO_LONGER_VISIBLE, data: {user_id: user4.id}},
|
|
{type: UserTypes.PROFILE_NO_LONGER_VISIBLE, data: {user_id: user5.id}},
|
|
];
|
|
const actions = Actions.notVisibleUsersActions(state);
|
|
expect(actions.length).toEqual(3);
|
|
expect(actions).toEqual(expectedAction);
|
|
});
|
|
});
|
|
|
|
describe('Actions.Websocket handleUserTypingEvent', () => {
|
|
const mockStore = configureMockStore([thunk]);
|
|
|
|
const currentUserId = 'user-id';
|
|
const otherUserId = 'other-user-id';
|
|
const currentChannelId = 'channel-id';
|
|
const otherChannelId = 'other-channel-id';
|
|
|
|
const initialState = {
|
|
entities: {
|
|
general: {
|
|
config: {},
|
|
},
|
|
channels: {
|
|
currentChannelId,
|
|
channels: {
|
|
currentChannelId: {
|
|
id: currentChannelId,
|
|
name: 'channel',
|
|
},
|
|
},
|
|
},
|
|
users: {
|
|
currentUserId,
|
|
profiles: {
|
|
[currentUserId]: {},
|
|
[otherUserId]: {},
|
|
},
|
|
statuses: {
|
|
[currentUserId]: General.ONLINE,
|
|
[otherUserId]: General.OFFLINE,
|
|
},
|
|
},
|
|
preferences: {
|
|
myPreferences: {},
|
|
},
|
|
},
|
|
};
|
|
|
|
it('dispatches actions for current channel if other user is typing', async () => {
|
|
const state = {...initialState};
|
|
const testStore = await mockStore(state);
|
|
const msg = {broadcast: {channel_id: currentChannelId}, data: {parent_id: 'parent-id', user_id: otherUserId}};
|
|
|
|
nock(Client4.getUsersRoute()).
|
|
post('/status/ids', JSON.stringify([otherUserId])).
|
|
reply(200, ['away']);
|
|
|
|
const expectedActionsTypes = [
|
|
WebsocketEvents.TYPING,
|
|
UserTypes.RECEIVED_STATUSES,
|
|
];
|
|
|
|
await testStore.dispatch(Actions.handleUserTypingEvent(msg));
|
|
await TestHelper.wait(300);
|
|
const actionTypes = testStore.getActions().map((action) => action.type);
|
|
expect(actionTypes).toEqual(expectedActionsTypes);
|
|
});
|
|
|
|
it('does not dispatch actions for non current channel', async () => {
|
|
const state = {...initialState};
|
|
const testStore = await mockStore(state);
|
|
const msg = {broadcast: {channel_id: otherChannelId}, data: {parent_id: 'parent-id', user_id: otherUserId}};
|
|
|
|
const expectedActionsTypes = [];
|
|
|
|
await testStore.dispatch(Actions.handleUserTypingEvent(msg));
|
|
const actionTypes = testStore.getActions().map((action) => action.type);
|
|
expect(actionTypes).toEqual(expectedActionsTypes);
|
|
});
|
|
}); |