// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import assert from 'assert'; import { DATE_LINE, makePreparePostIdsForPostList, START_OF_NEW_MESSAGES } from 'app/selectors/post_list'; import {Posts, Preferences} from 'mattermost-redux/constants'; import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils'; describe('Selectors.PostList', () => { describe('makePreparePostIdsForPostList', () => { it('filter join/leave posts', () => { const preparePostIdsForPostList = makePreparePostIdsForPostList(); let state = { entities: { posts: { posts: { 1001: {id: '1001', create_at: 0}, 1002: {id: '1002', create_at: 1, type: Posts.POST_TYPES.JOIN_CHANNEL} } }, preferences: { myPreferences: {} }, users: { currentUserId: '1234' } } }; const lastViewedAt = Number.POSITIVE_INFINITY; const postIds = ['1002', '1001']; // Defaults to show post let now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.deepEqual(removeDateLines(now), ['1002', '1001']); // Show join/leave posts state = { ...state, entities: { ...state.entities, preferences: { ...state.entities.preferences, myPreferences: { ...state.entities.preferences.myPreferences, [getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: { category: Preferences.CATEGORY_ADVANCED_SETTINGS, name: Preferences.ADVANCED_FILTER_JOIN_LEAVE, value: 'true' } } } } }; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.deepEqual(removeDateLines(now), ['1002', '1001']); // Hide join/leave posts state = { ...state, entities: { ...state.entities, preferences: { ...state.entities.preferences, myPreferences: { ...state.entities.preferences.myPreferences, [getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: { category: Preferences.CATEGORY_ADVANCED_SETTINGS, name: Preferences.ADVANCED_FILTER_JOIN_LEAVE, value: 'false' } } } } }; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.deepEqual(removeDateLines(now), ['1001']); }); it('new messages indicator', () => { const preparePostIdsForPostList = makePreparePostIdsForPostList(); const state = { entities: { posts: { posts: { 1000: {id: '1000', create_at: 1000}, 1005: {id: '1005', create_at: 1005}, 1010: {id: '1010', create_at: 1010} } }, preferences: { myPreferences: {} }, users: { currentUserId: '1234' } } }; const postIds = ['1010', '1005', '1000']; // Remember that we list the posts backwards // Show new messages indicator before all posts let now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 0}); assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000', START_OF_NEW_MESSAGES]); // Show indicator between posts now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 1003}); assert.deepEqual(removeDateLines(now), ['1010', '1005', START_OF_NEW_MESSAGES, '1000']); // Don't show indicator when all posts are read now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 1020}); assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000']); }); it('memoization', () => { const preparePostIdsForPostList = makePreparePostIdsForPostList(); // Posts 7 hours apart so they should appear on multiple days const initialPosts = { 1001: {id: '1001', create_at: 1 * 60 * 60 * 1000}, 1002: {id: '1002', create_at: (1 * 60 * 60 * 1000) + 5}, 1003: {id: '1003', create_at: (1 * 60 * 60 * 1000) + 10}, 1004: {id: '1004', create_at: 25 * 60 * 60 * 1000}, 1005: {id: '1005', create_at: (25 * 60 * 60 * 1000) + 5}, 1006: {id: '1006', create_at: (25 * 60 * 60 * 1000) + 10, type: Posts.POST_TYPES.JOIN_CHANNEL} }; let state = { entities: { posts: { posts: initialPosts }, preferences: { myPreferences: { [getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: { category: Preferences.CATEGORY_ADVANCED_SETTINGS, name: Preferences.ADVANCED_FILTER_JOIN_LEAVE, value: 'true' } } }, users: { currentUserId: '1234' } } }; let postIds = ['1006', '1004', '1003', '1001']; let lastViewedAt = initialPosts['1001'].create_at + 1; let now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.deepEqual(removeDateLines(now), ['1006', '1004', '1003', START_OF_NEW_MESSAGES, '1001']); // No changes let prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', '1003', START_OF_NEW_MESSAGES, '1001']); // lastViewedAt changed slightly lastViewedAt = initialPosts['1001'].create_at + 2; prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', '1003', START_OF_NEW_MESSAGES, '1001']); // lastViewedAt changed a lot lastViewedAt += initialPosts['1003'].create_at + 1; prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.notEqual(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']); prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']); // postIds changed, but still shallowly equal postIds = [...postIds]; prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']); // Post changed, not in postIds state = { ...state, entities: { ...state.entities, posts: { ...state.entities.posts, posts: { ...state.entities.posts.posts, 1007: {id: '1007', create_at: 7 * 60 * 60 * 7 * 1000} } } } }; prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']); // Post changed, in postIds state = { ...state, entities: { ...state.entities, posts: { ...state.entities.posts, posts: { ...state.entities.posts.posts, 1006: {...state.entities.posts.posts['1006'], message: 'abcd'} } } } }; prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']); // Filter changed state = { ...state, entities: { ...state.entities, preferences: { ...state.entities.preferences, myPreferences: { ...state.entities.preferences.myPreferences, [getPreferenceKey(Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE)]: { category: Preferences.CATEGORY_ADVANCED_SETTINGS, name: Preferences.ADVANCED_FILTER_JOIN_LEAVE, value: 'false' } } } } }; prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.notEqual(now, prev); assert.deepEqual(removeDateLines(now), ['1004', START_OF_NEW_MESSAGES, '1003', '1001']); prev = now; now = preparePostIdsForPostList(state, {postIds, lastViewedAt}); assert.equal(now, prev); assert.deepEqual(removeDateLines(now), ['1004', START_OF_NEW_MESSAGES, '1003', '1001']); }); }); }); // Remove date lines when checking equality since those depend on time-zone of the computer running the tests function removeDateLines(list) { return list.filter((item) => !item.startsWith(DATE_LINE)); }