diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js
index ee1db2d48..cdf00050c 100644
--- a/app/actions/views/channel.js
+++ b/app/actions/views/channel.js
@@ -198,7 +198,7 @@ export function loadPostsIfNecessaryWithRetry(channelId) {
});
}
} else {
- const {lastConnectAt} = state.websocket;
+ const lastConnectAt = state.websocket?.lastConnectAt || 0;
const lastGetPosts = state.views.channel.lastGetPosts[channelId];
let since;
diff --git a/app/actions/views/channel.test.js b/app/actions/views/channel.test.js
index 2b06a97d4..3775ad84b 100644
--- a/app/actions/views/channel.test.js
+++ b/app/actions/views/channel.test.js
@@ -4,7 +4,15 @@
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
-import {handleSelectChannelByName} from 'app/actions/views/channel';
+import initialState from 'app/initial_state';
+import testHelper from 'test/test_helper';
+
+import {
+ handleSelectChannelByName,
+ loadPostsIfNecessaryWithRetry,
+} from 'app/actions/views/channel';
+
+import postReducer from 'mattermost-redux/reducers/entities/posts';
jest.mock('mattermost-redux/selectors/entities/channels', () => ({
getChannel: () => ({data: 'received-channel-id'}),
@@ -19,6 +27,9 @@ describe('Actions.Views.Channel', () => {
const MOCK_SELECT_CHANNEL_TYPE = 'MOCK_SELECT_CHANNEL_TYPE';
const MOCK_RECEIVE_CHANNEL_TYPE = 'MOCK_RECEIVE_CHANNEL_TYPE';
+ const MOCK_RECEIVED_POSTS = 'RECEIVED_POSTS';
+ const MOCK_RECEIVED_POSTS_IN_CHANNEL = 'RECEIVED_POSTS_IN_CHANNEL';
+ const MOCK_RECEIVED_POSTS_SINCE = 'MOCK_RECEIVED_POSTS_SINCE';
const actions = require('mattermost-redux/actions/channels');
actions.getChannelByNameAndTeamName = jest.fn((teamName) => {
@@ -38,14 +49,51 @@ describe('Actions.Views.Channel', () => {
type: MOCK_SELECT_CHANNEL_TYPE,
data: 'selected-channel-id',
});
+ const postActions = require('mattermost-redux/actions/posts');
+ postActions.getPostsSince = jest.fn(() => {
+ return {
+ type: MOCK_RECEIVED_POSTS_SINCE,
+ data: {
+ order: [],
+ posts: {},
+ },
+ };
+ });
+ postActions.getPosts = jest.fn((channelId) => {
+ const order = [];
+ const posts = {};
+
+ for (let i = 0; i < 60; i++) {
+ const p = testHelper.fakePost(channelId);
+ order.push(p.id);
+ posts[p.id] = p;
+ }
+
+ return {
+ type: MOCK_RECEIVED_POSTS,
+ data: {
+ order,
+ posts,
+ },
+ };
+ });
+
+ const postUtils = require('mattermost-redux/utils/post_utils');
+ postUtils.getLastCreateAt = jest.fn((array) => {
+ return array[0].create_at;
+ });
+
+ let nextPostState = {};
const currentUserId = 'current-user-id';
const currentChannelId = 'channel-id';
const currentChannelName = 'channel-name';
const currentTeamId = 'current-team-id';
const currentTeamName = 'current-team-name';
const storeObj = {
+ ...initialState,
entities: {
+ ...initialState.entities,
users: {
currentUserId,
},
@@ -93,4 +141,84 @@ describe('Actions.Views.Channel', () => {
const storeBatchActions = storeActions.some(({type}) => type === 'BATCHING_REDUCER.BATCH');
expect(storeBatchActions).toBe(false);
});
+
+ test('loadPostsIfNecessaryWithRetry for the first time', async () => {
+ store = mockStore(storeObj);
+
+ await store.dispatch(loadPostsIfNecessaryWithRetry(currentChannelId));
+ expect(postActions.getPosts).toBeCalled();
+
+ const storeActions = store.getActions();
+ const storeBatchActions = storeActions.filter(({type}) => type === 'BATCHING_REDUCER.BATCH');
+ const receivedPosts = storeActions.find(({type}) => type === MOCK_RECEIVED_POSTS);
+ const receivedPostsAtAction = storeBatchActions[0].payload.some((action) => action.type === 'RECEIVED_POSTS_FOR_CHANNEL_AT_TIME');
+
+ nextPostState = postReducer(store.getState().entities.posts, receivedPosts);
+ nextPostState = postReducer(nextPostState, {
+ type: MOCK_RECEIVED_POSTS_IN_CHANNEL,
+ channelId: currentChannelId,
+ data: receivedPosts.data,
+ recent: true,
+ });
+
+ expect(receivedPostsAtAction).toBe(true);
+ });
+
+ test('loadPostsIfNecessaryWithRetry get posts since', async () => {
+ store = mockStore({
+ ...storeObj,
+ entities: {
+ ...storeObj.entities,
+ posts: nextPostState,
+ },
+ views: {
+ ...storeObj.views,
+ channel: {
+ ...storeObj.views.channel,
+ lastGetPosts: {
+ [currentChannelId]: Date.now(),
+ },
+ },
+ },
+ });
+
+ await store.dispatch(loadPostsIfNecessaryWithRetry(currentChannelId));
+ const storeActions = store.getActions();
+ const receivedPostsSince = storeActions.find(({type}) => type === MOCK_RECEIVED_POSTS_SINCE);
+
+ expect(postUtils.getLastCreateAt).toBeCalled();
+ expect(postActions.getPostsSince).toHaveBeenCalledWith(currentChannelId, Object.values(store.getState().entities.posts.posts)[0].create_at);
+ expect(receivedPostsSince).not.toBe(null);
+ });
+
+ test('loadPostsIfNecessaryWithRetry get posts since the websocket reconnected', async () => {
+ const time = Date.now();
+ store = mockStore({
+ ...storeObj,
+ entities: {
+ ...storeObj.entities,
+ posts: nextPostState,
+ },
+ views: {
+ ...storeObj.views,
+ channel: {
+ ...storeObj.views.channel,
+ lastGetPosts: {
+ [currentChannelId]: time,
+ },
+ },
+ },
+ websocket: {
+ lastConnectAt: time + (1 * 60 * 1000),
+ },
+ });
+
+ await store.dispatch(loadPostsIfNecessaryWithRetry(currentChannelId));
+ const storeActions = store.getActions();
+ const receivedPostsSince = storeActions.find(({type}) => type === MOCK_RECEIVED_POSTS_SINCE);
+
+ expect(postUtils.getLastCreateAt).not.toBeCalled();
+ expect(postActions.getPostsSince).toHaveBeenCalledWith(currentChannelId, store.getState().views.channel.lastGetPosts[currentChannelId]);
+ expect(receivedPostsSince).not.toBe(null);
+ });
});
diff --git a/app/screens/channel/channel_nav_bar/__snapshots__/channel_nav_bar.test.js.snap b/app/screens/channel/channel_nav_bar/__snapshots__/channel_nav_bar.test.js.snap
index 65f503959..055cf435a 100644
--- a/app/screens/channel/channel_nav_bar/__snapshots__/channel_nav_bar.test.js.snap
+++ b/app/screens/channel/channel_nav_bar/__snapshots__/channel_nav_bar.test.js.snap
@@ -25,7 +25,6 @@ exports[`ChannelNavBar should match, full snapshot 1`] = `
visible={true}
/>
{
+ const time = Date.now();
+
return {
+ id: this.generateId(),
channel_id: channelId,
+ create_at: time,
+ update_at: time,
message: `Unit Test ${this.generateId()}`,
};
};