From 8e59ea606ecbbd01064921bc1755b032f02cfe94 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Mon, 19 Dec 2016 12:37:54 -0500 Subject: [PATCH] Refactored post store to store posts by their IDs (#142) * Added hook to tests to catch uncaught promise rejections * Refactored post store to store posts by their IDs * Fixed post store when logging out --- service/reducers/entities/posts.js | 269 ++++++++----------- test/mocha.opts | 2 +- test/sanity.test.js | 8 + test/service/actions/posts.test.js | 412 +++++++++++++++++------------ test/service/actions/users.test.js | 3 +- 5 files changed, 377 insertions(+), 317 deletions(-) diff --git a/service/reducers/entities/posts.js b/service/reducers/entities/posts.js index 712f93d8d..f0f565790 100644 --- a/service/reducers/entities/posts.js +++ b/service/reducers/entities/posts.js @@ -2,180 +2,146 @@ // See License.txt for license information. import {Constants, PostsTypes, UsersTypes} from 'service/constants'; -import {combineReducers} from 'redux'; -function isPostListNull(pl) { - if (!pl) { - return true; +function handleReceivedPost(posts = {}, postsByChannel = {}, action) { + const post = action.data; + const channelId = post.channel_id; + + const nextPosts = { + ...posts, + [post.id]: post + }; + + let nextPostsByChannel = postsByChannel; + + // Only change postsByChannel if the order of the posts needs to change + if (!postsByChannel[channelId] || postsByChannel[channelId].indexOf(post.id) === -1) { + // If we don't already have the post, assume it's the most recent one + const postsInChannel = postsByChannel[channelId] || []; + + nextPostsByChannel = {...postsByChannel}; + nextPostsByChannel[channelId] = [ + post.id, + ...postsInChannel + ]; } - if (!pl.posts) { - return true; - } - - return !pl.order; + return {posts: nextPosts, postsByChannel: nextPostsByChannel}; } -function makePostListNonNull(pl) { - let postList = {...pl}; - if (!postList) { - postList = {order: [], posts: {}}; - } - - if (!postList.order) { - postList.order = []; - } - - if (!postList.posts) { - postList.posts = {}; - } - - return postList; -} - -function storePosts(state, action) { - const newPosts = action.data; +function handleReceivedPosts(posts = {}, postsByChannel = {}, action) { + const newPosts = action.data.posts; const channelId = action.channelId; - if (isPostListNull(newPosts)) { - return state; - } + const nextPosts = {...posts}; + const nextPostsByChannel = {...postsByChannel}; + const postsInChannel = postsByChannel[channelId] ? [...postsByChannel[channelId]] : []; - const postList = state[channelId] || {}; - const combinedPosts = makePostListNonNull(postList); + for (const newPost of Object.values(newPosts)) { + nextPosts[newPost.id] = newPost; - for (const pid in newPosts.posts) { - if (newPosts.posts.hasOwnProperty(pid)) { - const np = newPosts.posts[pid]; - if (np.delete_at === 0) { - combinedPosts.posts[pid] = np; - if (combinedPosts.order.indexOf(pid) === -1 && newPosts.order.indexOf(pid) !== -1) { - combinedPosts.order.push(pid); - } - } else if (combinedPosts.posts.hasOwnProperty(pid)) { - combinedPosts.posts[pid] = {...np, state: Constants.POST_DELETED, fileIds: []}; - } + if (postsInChannel.indexOf(newPost.id) === -1) { + // Just add the post id to the end of the order and we'll sort it out later + postsInChannel.push(newPost.id); } } - combinedPosts.order.sort((a, b) => { - if (combinedPosts.posts[a].create_at > combinedPosts.posts[b].create_at) { + // Sort to ensure that the most recent posts are first + postsInChannel.sort((a, b) => { + if (nextPosts[a].create_at > nextPosts[b].create_at) { return -1; - } - if (combinedPosts.posts[a].create_at < combinedPosts.posts[b].create_at) { + } else if (nextPosts[a].create_at < nextPosts[b].create_at) { return 1; } return 0; }); - return { - ...state, - [channelId]: combinedPosts - }; + nextPostsByChannel[channelId] = postsInChannel; + + return {posts: nextPosts, postsByChannel: nextPostsByChannel}; } -function storePost(state, action) { +function handlePostDeleted(posts = {}, postsByChannel = {}, action) { const post = action.data; - const channelId = post.channel_id; - const postList = state[channelId] || {}; - const combinedPosts = makePostListNonNull(postList); + let nextPosts = posts; - combinedPosts.posts[post.id] = post; + // We only need to do something if already have the post + if (posts[post.id]) { + nextPosts = {...posts}; - if (combinedPosts.order.indexOf(post.id) === -1) { - combinedPosts.order.unshift(post.id); - } - - return { - ...state, - [channelId]: combinedPosts - }; -} - -function deletePost(state, action) { - const post = action.data; - const channelId = post.channel_id; - const postInfo = state[channelId]; - - if (!postInfo) { - // the post that has been deleted is in a channel that we haven't seen so just ignore it - return state; - } - - if (isPostListNull(postInfo)) { - return state; - } - - if (postInfo.posts[post.id]) { - const combinedPosts = makePostListNonNull(postInfo); - - combinedPosts.posts = { - ...combinedPosts.posts, - [post.id]: { - ...post, - state: Constants.POST_DELETED, - file_ids: [], - has_reactions: false - } + nextPosts[post.id] = { + ...posts[post.id], + state: Constants.POST_DELETED, + file_ids: [], + has_reactions: false }; - return { - ...state, - [channelId]: combinedPosts - }; + // No changes to the order until the user actually removes the post } - return state; + return {posts: nextPosts, postsByChannel}; } -function removePost(state, action) { +function handleRemovePost(posts = {}, postsByChannel = {}, action) { const post = action.data; const channelId = post.channel_id; - const postInfo = state[channelId]; - if (!postInfo) { - // the post that has been deleted is in a channel that we haven't seen so just ignore it - return state; - } + let nextPosts = posts; + let nextPostsByChannel = postsByChannel; - if (isPostListNull(postInfo)) { - return state; - } + // We only need to do something if already have the post + if (nextPosts[post.id]) { + nextPosts = {...posts}; + nextPostsByChannel = {...postsByChannel}; + const postsInChannel = postsByChannel[channelId] ? [...postsByChannel[channelId]] : []; - if (postInfo.posts[post.id]) { - const combinedPosts = makePostListNonNull(postInfo); + // Remove the post itself + Reflect.deleteProperty(nextPosts, post.id); - combinedPosts.order = combinedPosts.order.slice(0); - combinedPosts.posts = {...combinedPosts.posts}; - - // Remove the post - Reflect.deleteProperty(combinedPosts.posts, post.id); - - const index = combinedPosts.order.indexOf(post.id); + const index = postsInChannel.indexOf(post.id); if (index !== -1) { - combinedPosts.order.splice(index, 1); + postsInChannel.splice(index, 1); } - // Remove any children of the post - for (const pid of Object.keys(combinedPosts.posts)) { - if (combinedPosts.posts[pid].root_id === post.id) { - Reflect.deleteProperty(combinedPosts.posts, pid); - const commentIndex = combinedPosts.order.indexOf(pid); + // Remove any of its comments + for (const id of postsInChannel) { + if (nextPosts[id].root_id === post.id) { + Reflect.deleteProperty(nextPosts, id); + + const commentIndex = postsInChannel.indexOf(id); if (commentIndex !== -1) { - combinedPosts.order.splice(commentIndex, 1); + postsInChannel.splice(commentIndex, 1); } } } - return { - ...state, - [channelId]: combinedPosts - }; + nextPostsByChannel[channelId] = postsInChannel; } - return state; + return {posts: nextPosts, postsByChannel: nextPostsByChannel}; +} + +function handlePosts(state = {}, action) { + switch (action.type) { + case PostsTypes.RECEIVED_POST: + return handleReceivedPost(state.posts, state.postsByChannel, action); + case PostsTypes.RECEIVED_POSTS: + return handleReceivedPosts(state.posts, state.postsByChannel, action); + case PostsTypes.POST_DELETED: + return handlePostDeleted(state.posts, state.postsByChannel, action); + case PostsTypes.REMOVE_POST: + return handleRemovePost(state.posts, state.postsByChannel, action); + + case UsersTypes.LOGOUT_SUCCESS: + return { + posts: {}, + postsByChannel: {} + }; + default: + return state; + } } function selectedPostId(state = '', action) { @@ -196,31 +162,30 @@ function currentFocusedPostId(state = '', action) { } } -function postsInfo(state = {}, action) { - switch (action.type) { - case PostsTypes.RECEIVED_POST: - return storePost(state, action); - case PostsTypes.RECEIVED_POSTS: - return storePosts(state, action); - case PostsTypes.POST_DELETED: - return deletePost(state, action); - case PostsTypes.REMOVE_POST: - return removePost(state, action); - case UsersTypes.LOGOUT_SUCCESS: - return {}; - default: +export default function(state = {}, action) { + const {posts, postsByChannel} = handlePosts(state, action); + + const nextState = { + + // Object mapping post ids to post objects + posts, + + // Object mapping channel ids to an list of posts ids in that channel with the most recent post first + postsByChannel, + + // The current selected post + selectedPostId: selectedPostId(state.selectedPostId, action), + + // The current selected focused post (permalink view) + currentFocusedPostId: currentFocusedPostId(state.currentFocusedPostId, action) + }; + + if (state.posts === nextState.posts && state.postsByChannel === nextState.postsByChannel && + state.selectedPostId === nextState.selectedPostId && + state.currentFocusedPostId === nextState.currentFocusedPostId) { + // None of the children have changed so don't even let the parent object change return state; } + + return nextState; } - -export default combineReducers({ - - // the current selected post - selectedPostId, - - // the current selected focused post (permalink view) - currentFocusedPostId, - - // object where every key is the channel id and has and object with the postList - postsInfo -}); diff --git a/test/mocha.opts b/test/mocha.opts index b79453007..4be08b36b 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,3 +1,3 @@ --require react-native-mock/mock.js --require isomorphic-fetch ---recursive \ No newline at end of file +--recursive diff --git a/test/sanity.test.js b/test/sanity.test.js index ab0858a46..40d1d8c0b 100644 --- a/test/sanity.test.js +++ b/test/sanity.test.js @@ -3,6 +3,14 @@ import 'react-native'; +// Set up a global hooks to make debugging tests less of a pain +before(() => { + process.on('unhandledRejection', (reason) => { + // Rethrow so that tests will actually fail and not just timeout + throw reason; + }); +}); + // Ensure that everything is imported correctly for testing describe('Sanity test', () => { it('Promise', (done) => { diff --git a/test/service/actions/posts.test.js b/test/service/actions/posts.test.js index 6aaed0be9..a345758a2 100644 --- a/test/service/actions/posts.test.js +++ b/test/service/actions/posts.test.js @@ -14,23 +14,43 @@ describe('Actions.Posts', () => { TestHelper.initBasic(Client).then(() => { const store = configureStore(); - store.subscribe(() => { - const createRequest = store.getState().requests.posts.createPost; - const postsInfo = store.getState().entities.posts.postsInfo; + const channelId = TestHelper.basicChannel.id; + const post = TestHelper.fakePost(channelId); - if (createRequest.status === RequestStatus.SUCCESS || createRequest.status === RequestStatus.FAILURE) { - if (createRequest.error) { - done(new Error(JSON.stringify(createRequest.error))); - } else { - assert.ok(postsInfo[TestHelper.basicChannel.id]); - assert.ok(postsInfo[TestHelper.basicChannel.id].order.length); - assert.ok(Object.keys(postsInfo[TestHelper.basicChannel.id].posts).length); - done(); + store.subscribe(() => { + const state = store.getState(); + const createRequest = state.requests.posts.createPost; + const {posts, postsByChannel} = state.entities.posts; + + if (createRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(postsByChannel); + assert.ok(postsByChannel[channelId]); + + let found = false; + for (const storedPost of Object.values(posts)) { + if (storedPost.message === post.message) { + found = true; + break; + } } + assert.ok(found, 'failed to find new post in posts'); + + found = false; + for (const postIdInChannel of postsByChannel[channelId]) { + if (posts[postIdInChannel].message === post.message) { + found = true; + break; + } + } + assert.ok(found, 'failed to find new post in postsByChannel'); + + done(); + } else if (createRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(createRequest.error))); } }); - const post = TestHelper.fakePost(TestHelper.basicChannel.id); Actions.createPost( TestHelper.basicTeam.id, post @@ -41,60 +61,70 @@ describe('Actions.Posts', () => { it('editPost', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const post = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const message = post.message; store.subscribe(() => { - const editRequest = store.getState().requests.posts.editPost; - const postsInfo = store.getState().entities.posts.postsInfo; + const state = store.getState(); + const editRequest = state.requests.posts.editPost; + const posts = state.entities.posts.posts; - if (editRequest.status === RequestStatus.SUCCESS || editRequest.status === RequestStatus.FAILURE) { - if (editRequest.error) { - done(new Error(JSON.stringify(editRequest.error))); - } else { - assert.ok(postsInfo[TestHelper.basicChannel.id]); - assert.ok(postsInfo[TestHelper.basicChannel.id].order.length); - assert.strictEqual( - postsInfo[TestHelper.basicChannel.id].posts[post.id].message, - `${message} (edited)` - ); - done(); - } + if (editRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(posts[post.id]); + + assert.strictEqual( + posts[post.id].message, + `${message} (edited)` + ); + + done(); + } else if (editRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(editRequest.error))); } }); post.message = `${message} (edited)`; Actions.editPost( - TestHelper.basicTeam.id, + teamId, post )(store.dispatch, store.getState); }); }); it('deletePost', (done) => { - TestHelper.initBasic(Client).then(async ({channel}) => { + TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + await Actions.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) )(store.dispatch, store.getState); - const initialPostsInfo = store.getState().entities.posts.postsInfo[channel.id]; - const created = initialPostsInfo.posts[initialPostsInfo.order[0]]; + const initialPosts = store.getState().entities.posts; + const created = initialPosts.posts[initialPosts.postsByChannel[channelId][0]]; store.subscribe(() => { const state = store.getState(); const deleteRequest = state.requests.posts.deletePost; - const postsInfo = state.entities.posts.postsInfo[channel.id]; + const posts = state.entities.posts.posts; if (deleteRequest.status === RequestStatus.SUCCESS) { - assert.ok(postsInfo); + assert.ok(posts); + assert.ok(posts[created.id]); + assert.strictEqual( - postsInfo.posts[created.id].state, + posts[created.id].state, Constants.POST_DELETED ); @@ -104,30 +134,39 @@ describe('Actions.Posts', () => { } }); - Actions.deletePost(TestHelper.basicTeam.id, created)(store.dispatch, store.getState); + Actions.deletePost(teamId, created)(store.dispatch, store.getState); }); }); it('removePost', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const postId = TestHelper.basicPost.id; + const post1a = await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: TestHelper.basicPost.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: postId} ); await Actions.getPosts( - TestHelper.basicTeam.id, - TestHelper.basicChannel.id + teamId, + channelId )(store.dispatch, store.getState); store.subscribe(() => { - const postsInfo = store.getState().entities.posts.postsInfo; - const postList = postsInfo[TestHelper.basicChannel.id]; + const state = store.getState(); + const {posts, postsByChannel} = state.entities.posts; - assert.strictEqual(postList.order.length, 0); - assert.ok(!postList.posts[post1a.id]); - assert.ok(!postList.posts[TestHelper.basicPost.id]); + assert.ok(posts); + assert.ok(postsByChannel); + assert.ok(postsByChannel[channelId]); + + assert.equal(postsByChannel[channelId].length, 0); + assert.ok(!posts[postId]); + assert.ok(!posts[post1a.id]); done(); }); @@ -141,30 +180,45 @@ describe('Actions.Posts', () => { it('getPost', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const post = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); store.subscribe(() => { - const getRequest = store.getState().requests.posts.getPost; - const postsInfo = store.getState().entities.posts.postsInfo; + const state = store.getState(); + const getRequest = state.requests.posts.getPost; + const {posts, postsByChannel} = state.entities.posts; - if (getRequest.status === RequestStatus.SUCCESS || getRequest.status === RequestStatus.FAILURE) { - if (getRequest.error) { - done(new Error(JSON.stringify(getRequest.error))); - } else { - assert.ok(postsInfo[TestHelper.basicChannel.id]); - assert.ok(postsInfo[TestHelper.basicChannel.id].order.length); - assert.ok(postsInfo[TestHelper.basicChannel.id].posts[post.id]); - done(); + if (getRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(postsByChannel); + assert.ok(postsByChannel[channelId]); + + assert.ok(posts[post.id]); + + let found = false; + for (const postIdInChannel of postsByChannel[channelId]) { + if (postIdInChannel === post.id) { + found = true; + break; + } } + assert.ok(found, 'failed to find post in postsByChannel'); + + done(); + } else if (getRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(getRequest.error))); } }); Actions.getPost( - TestHelper.basicTeam.id, - TestHelper.basicChannel.id, + teamId, + channelId, post.id )(store.dispatch, store.getState); }); @@ -173,50 +227,61 @@ describe('Actions.Posts', () => { it('getPosts', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const post1 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post1a = await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post1.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post1.id} ); const post2 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3a = await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post3.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post3.id} ); store.subscribe(() => { - const getRequest = store.getState().requests.posts.getPosts; - const postsInfo = store.getState().entities.posts.postsInfo; + const state = store.getState(); + const getRequest = state.requests.posts.getPosts; + const {posts, postsByChannel} = state.entities.posts; - if (getRequest.status === RequestStatus.SUCCESS || getRequest.status === RequestStatus.FAILURE) { - if (getRequest.error) { - done(new Error(JSON.stringify(getRequest.error))); - } else { - const postsList = postsInfo[TestHelper.basicChannel.id]; - assert.ok(postsList); - assert.equal(postsList.order[0], post3a.id, 'wrong order'); - assert.equal(postsList.order[1], post3.id, 'wrong order'); - assert.equal(postsList.order[3], post1a.id, 'wrong order'); - assert.ok(postsList.posts[post1.id], 'should exists'); - assert.ok(postsList.posts[post2.id], 'should exists'); - done(); - } + if (getRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(postsByChannel); + + const postsInChannel = postsByChannel[channelId]; + assert.ok(postsInChannel); + assert.equal(postsInChannel[0], post3a.id, 'wrong order for post3a'); + assert.equal(postsInChannel[1], post3.id, 'wrong order for post3'); + assert.equal(postsInChannel[3], post1a.id, 'wrong order for post1a'); + + assert.ok(posts[post1.id]); + assert.ok(posts[post1a.id]); + assert.ok(posts[post2.id]); + assert.ok(posts[post3.id]); + assert.ok(posts[post3a.id]); + + done(); + } else if (getRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(getRequest.error))); } }); Actions.getPosts( - TestHelper.basicTeam.id, - TestHelper.basicChannel.id + teamId, + channelId )(store.dispatch, store.getState); }); }).timeout(3000); @@ -224,48 +289,55 @@ describe('Actions.Posts', () => { it('getPostsSince', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const post1 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post1.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post1.id} ); const post2 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3a = await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post3.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post3.id} ); store.subscribe(() => { - const getRequest = store.getState().requests.posts.getPostsSince; - const postsInfo = store.getState().entities.posts.postsInfo; + const state = store.getState(); + const getRequest = state.requests.posts.getPostsSince; + const {posts, postsByChannel} = state.entities.posts; - if (getRequest.status === RequestStatus.SUCCESS || getRequest.status === RequestStatus.FAILURE) { - if (getRequest.error) { - done(new Error(JSON.stringify(getRequest.error))); - } else { - const postsList = postsInfo[TestHelper.basicChannel.id]; - assert.ok(postsList); - assert.equal(postsList.order[0], post3a.id, 'wrong order'); - assert.equal(postsList.order[1], post3.id, 'wrong order'); - assert.equal(Object.keys(postsList.posts).length, 2, 'wrong size'); - done(); - } + if (getRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(postsByChannel); + + const postsInChannel = postsByChannel[channelId]; + assert.ok(postsInChannel); + assert.equal(postsInChannel[0], post3a.id, 'wrong order for post3a'); + assert.equal(postsInChannel[1], post3.id, 'wrong order for post3'); + assert.equal(postsInChannel.length, 2, 'wrong size'); + + done(); + } else if (getRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(getRequest.error))); } }); Actions.getPostsSince( - TestHelper.basicTeam.id, - TestHelper.basicChannel.id, + teamId, + channelId, post2.create_at )(store.dispatch, store.getState); }); @@ -274,48 +346,55 @@ describe('Actions.Posts', () => { it('getPostsBefore', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const post1 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post1a = await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post1.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post1.id} ); const post2 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post3.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post3.id} ); store.subscribe(() => { - const getRequest = store.getState().requests.posts.getPostsBefore; - const postsInfo = store.getState().entities.posts.postsInfo; + const state = store.getState(); + const getRequest = state.requests.posts.getPostsBefore; + const {posts, postsByChannel} = state.entities.posts; - if (getRequest.status === RequestStatus.SUCCESS || getRequest.status === RequestStatus.FAILURE) { - if (getRequest.error) { - done(new Error(JSON.stringify(getRequest.error))); - } else { - const postsList = postsInfo[TestHelper.basicChannel.id]; - assert.ok(postsList); - assert.equal(postsList.order[0], post1a.id, 'wrong order'); - assert.equal(postsList.order[1], post1.id, 'wrong order'); - assert.equal(Object.keys(postsList.posts).length, 3, 'wrong size'); - done(); - } + if (getRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(postsByChannel); + + const postsInChannel = postsByChannel[channelId]; + assert.ok(postsInChannel); + assert.equal(postsInChannel[0], post1a.id, 'wrong order for post1a'); + assert.equal(postsInChannel[1], post1.id, 'wrong order for post1'); + assert.equal(postsInChannel.length, 3, 'wrong size'); + + done(); + } else if (getRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(getRequest.error))); } }); Actions.getPostsBefore( - TestHelper.basicTeam.id, - TestHelper.basicChannel.id, + teamId, + channelId, post2.id, 0, 10 @@ -326,48 +405,55 @@ describe('Actions.Posts', () => { it('getPostsAfter', (done) => { TestHelper.initBasic(Client).then(async () => { const store = configureStore(); + + const teamId = TestHelper.basicTeam.id; + const channelId = TestHelper.basicChannel.id; + const post1 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post1.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post1.id} ); const post2 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3 = await Client.createPost( - TestHelper.basicTeam.id, - TestHelper.fakePost(TestHelper.basicChannel.id) + teamId, + TestHelper.fakePost(channelId) ); const post3a = await Client.createPost( - TestHelper.basicTeam.id, - {...TestHelper.fakePost(TestHelper.basicChannel.id), root_id: post3.id} + teamId, + {...TestHelper.fakePost(channelId), root_id: post3.id} ); store.subscribe(() => { - const getRequest = store.getState().requests.posts.getPostsAfter; - const postsInfo = store.getState().entities.posts.postsInfo; + const state = store.getState(); + const getRequest = state.requests.posts.getPostsAfter; + const {posts, postsByChannel} = state.entities.posts; - if (getRequest.status === RequestStatus.SUCCESS || getRequest.status === RequestStatus.FAILURE) { - if (getRequest.error) { - done(new Error(JSON.stringify(getRequest.error))); - } else { - const postsList = postsInfo[TestHelper.basicChannel.id]; - assert.ok(postsList); - assert.equal(postsList.order[0], post3a.id, 'wrong order'); - assert.equal(postsList.order[1], post3.id, 'wrong order'); - assert.equal(Object.keys(postsList.posts).length, 2, 'wrong size'); - done(); - } + if (getRequest.status === RequestStatus.SUCCESS) { + assert.ok(posts); + assert.ok(postsByChannel); + + const postsInChannel = postsByChannel[channelId]; + assert.ok(postsInChannel); + assert.equal(postsInChannel[0], post3a.id, 'wrong order for post3a'); + assert.equal(postsInChannel[1], post3.id, 'wrong order for post3'); + assert.equal(postsInChannel.length, 2, 'wrong size'); + + done(); + } else if (getRequest.status === RequestStatus.FAILURE) { + done(new Error(JSON.stringify(getRequest.error))); } }); Actions.getPostsAfter( - TestHelper.basicTeam.id, - TestHelper.basicChannel.id, + teamId, + channelId, post2.id, 0, 10 diff --git a/test/service/actions/users.test.js b/test/service/actions/users.test.js index bf8d99aa7..21b2f0bcf 100644 --- a/test/service/actions/users.test.js +++ b/test/service/actions/users.test.js @@ -95,7 +95,8 @@ describe('Actions.Users', () => { assert.deepStrictEqual(channels.stats, {}, 'channel stats is not empty'); assert.strictEqual(posts.selectedPostId, '', 'selected post id is not empty'); assert.strictEqual(posts.currentFocusedPostId, '', 'current focused post id is not empty'); - assert.deepStrictEqual(posts.postsInfo, {}, 'posts info is not empty'); + assert.deepStrictEqual(posts.posts, {}, 'posts is not empty'); + assert.deepStrictEqual(posts.postsByChannel, {}, 'posts by channel is not empty'); assert.deepStrictEqual(preferences.myPreferences, {}, 'user preferences not empty'); assert.strictEqual(navigation.index, 0, 'navigation not reset to first element of stack'); assert.deepStrictEqual(navigation.routes, [Routes.Root], 'navigation not reset to root route');