diff --git a/app/components/post_list/date_header/__snapshots__/date_header.test.js.snap b/app/components/post_list/date_header/__snapshots__/date_header.test.js.snap
new file mode 100644
index 000000000..381ea86a7
--- /dev/null
+++ b/app/components/post_list/date_header/__snapshots__/date_header.test.js.snap
@@ -0,0 +1,641 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DateHeader component should match snapshot with suffix 1`] = `
+ShallowWrapper {
+ "length": 1,
+ Symbol(enzyme.__root__): [Circular],
+ Symbol(enzyme.__unrendered__): ,
+ Symbol(enzyme.__renderer__): Object {
+ "batchedUpdates": [Function],
+ "getNode": [Function],
+ "render": [Function],
+ "simulateEvent": [Function],
+ "unmount": [Function],
+ },
+ Symbol(enzyme.__node__): Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+ ,
+ ,
+ ],
+ "style": Array [
+ Object {
+ "alignItems": "center",
+ "flexDirection": "row",
+ "height": 28,
+ },
+ undefined,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "style": Object {
+ "marginHorizontal": 15,
+ },
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "day": "2-digit",
+ "month": "short",
+ "style": Object {
+ "color": "#aaa",
+ "fontSize": 14,
+ "fontWeight": "600",
+ },
+ "value": 1970-01-18T17:19:12.392Z,
+ "weekday": "short",
+ "year": "numeric",
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ Symbol(enzyme.__nodes__): Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+ ,
+ ,
+ ],
+ "style": Array [
+ Object {
+ "alignItems": "center",
+ "flexDirection": "row",
+ "height": 28,
+ },
+ undefined,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "style": Object {
+ "marginHorizontal": 15,
+ },
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "day": "2-digit",
+ "month": "short",
+ "style": Object {
+ "color": "#aaa",
+ "fontSize": 14,
+ "fontWeight": "600",
+ },
+ "value": 1970-01-18T17:19:12.392Z,
+ "weekday": "short",
+ "year": "numeric",
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ Symbol(enzyme.__options__): Object {
+ "adapter": ReactSixteenAdapter {
+ "options": Object {
+ "enableComponentDidUpdateOnSetState": true,
+ },
+ },
+ "context": Object {
+ "intl": Object {
+ "formatMessage": [MockFunction],
+ },
+ },
+ },
+}
+`;
+
+exports[`DateHeader component should match snapshot without suffix 1`] = `
+ShallowWrapper {
+ "length": 1,
+ Symbol(enzyme.__root__): [Circular],
+ Symbol(enzyme.__unrendered__): ,
+ Symbol(enzyme.__renderer__): Object {
+ "batchedUpdates": [Function],
+ "getNode": [Function],
+ "render": [Function],
+ "simulateEvent": [Function],
+ "unmount": [Function],
+ },
+ Symbol(enzyme.__node__): Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+ ,
+ ,
+ ],
+ "style": Array [
+ Object {
+ "alignItems": "center",
+ "flexDirection": "row",
+ "height": 28,
+ },
+ undefined,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "style": Object {
+ "marginHorizontal": 15,
+ },
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "day": "2-digit",
+ "month": "short",
+ "style": Object {
+ "color": "#aaa",
+ "fontSize": 14,
+ "fontWeight": "600",
+ },
+ "value": 1970-01-18T17:19:12.392Z,
+ "weekday": "short",
+ "year": "numeric",
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ Symbol(enzyme.__nodes__): Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": Array [
+ ,
+
+
+ ,
+ ,
+ ],
+ "style": Array [
+ Object {
+ "alignItems": "center",
+ "flexDirection": "row",
+ "height": 28,
+ },
+ undefined,
+ ],
+ },
+ "ref": null,
+ "rendered": Array [
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "children": ,
+ "style": Object {
+ "marginHorizontal": 15,
+ },
+ },
+ "ref": null,
+ "rendered": Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "day": "2-digit",
+ "month": "short",
+ "style": Object {
+ "color": "#aaa",
+ "fontSize": 14,
+ "fontWeight": "600",
+ },
+ "value": 1970-01-18T17:19:12.392Z,
+ "weekday": "short",
+ "year": "numeric",
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ "type": [Function],
+ },
+ Object {
+ "instance": null,
+ "key": undefined,
+ "nodeType": "class",
+ "props": Object {
+ "style": Object {
+ "backgroundColor": "#aaa",
+ "flex": 1,
+ "height": 1,
+ "opacity": 0.2,
+ },
+ },
+ "ref": null,
+ "rendered": null,
+ "type": [Function],
+ },
+ ],
+ "type": [Function],
+ },
+ ],
+ Symbol(enzyme.__options__): Object {
+ "adapter": ReactSixteenAdapter {
+ "options": Object {
+ "enableComponentDidUpdateOnSetState": true,
+ },
+ },
+ "context": Object {
+ "intl": Object {
+ "formatMessage": [MockFunction],
+ },
+ },
+ },
+}
+`;
diff --git a/app/components/post_list/date_header/date_header.js b/app/components/post_list/date_header/date_header.js
index 9e5d2c47f..1911832b2 100644
--- a/app/components/post_list/date_header/date_header.js
+++ b/app/components/post_list/date_header/date_header.js
@@ -10,17 +10,27 @@ import {
import FormattedDate from 'app/components/formatted_date';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
+import {DATE_LINE, DATE_LINE_SUFFIX} from 'app/selectors/post_list';
+// DateHeader accepts as a timestamp encoded as a string for rendering as part of a post list.
export default class DateHeader extends PureComponent {
static propTypes = {
- date: PropTypes.object.isRequired,
+ dateLineString: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
style: ViewPropTypes.style,
};
render() {
- const {date, theme} = this.props;
+ const {theme, dateLineString} = this.props;
const style = getStyleSheet(theme);
+ const indexSuffix = dateLineString.indexOf(DATE_LINE_SUFFIX);
+
+ let date;
+ if (indexSuffix >= 0) {
+ date = new Date(parseInt(dateLineString.substring(DATE_LINE.length, indexSuffix), 10));
+ } else {
+ date = new Date(parseInt(dateLineString.substring(DATE_LINE.length), 10));
+ }
return (
diff --git a/app/components/post_list/date_header/date_header.test.js b/app/components/post_list/date_header/date_header.test.js
new file mode 100644
index 000000000..e7b9e2898
--- /dev/null
+++ b/app/components/post_list/date_header/date_header.test.js
@@ -0,0 +1,47 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+/* eslint-disable max-nested-callbacks */
+
+import React from 'react';
+import {configure, shallow} from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+configure({adapter: new Adapter()});
+
+import DateHeader from './date_header.js';
+
+describe('DateHeader', () => {
+ const baseProps = {
+ theme: {centerChannelBg: '#aaa', centerChannelColor: '#aaa'},
+ };
+
+ describe('component should match snapshot', () => {
+ it('without suffix', () => {
+ const props = {
+ ...baseProps,
+ dateLineString: 'date-1531152392',
+ index: 0,
+ };
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage: jest.fn()}}},
+ );
+
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it('with suffix', () => {
+ const props = {
+ ...baseProps,
+ dateLineString: 'date-1531152392-index-2',
+ index: 2,
+ };
+ const wrapper = shallow(
+ ,
+ {context: {intl: {formatMessage: jest.fn()}}},
+ );
+
+ expect(wrapper).toMatchSnapshot();
+ });
+ });
+});
diff --git a/app/components/post_list/date_header/utils.js b/app/components/post_list/date_header/utils.js
new file mode 100644
index 000000000..c08f750da
--- /dev/null
+++ b/app/components/post_list/date_header/utils.js
@@ -0,0 +1,6 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {DATE_LINE} from 'app/selectors/post_list';
+
+export const isDateLine = (dateString) => dateString.indexOf(DATE_LINE) === 0;
diff --git a/app/components/post_list/date_header/utils.test.js b/app/components/post_list/date_header/utils.test.js
new file mode 100644
index 000000000..c27de2ee7
--- /dev/null
+++ b/app/components/post_list/date_header/utils.test.js
@@ -0,0 +1,17 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import assert from 'assert';
+
+import {isDateLine} from './utils.js';
+
+describe('DateHeader', () => {
+ it('isDateLine', () => {
+ assert.equal(isDateLine(''), false);
+ assert.equal(isDateLine('date'), false);
+ assert.equal(isDateLine('date-'), true);
+ assert.equal(isDateLine('date-0'), true);
+ assert.equal(isDateLine('date-1531152392'), true);
+ assert.equal(isDateLine('date-1531152392-index'), true);
+ });
+});
diff --git a/app/components/post_list/post_list.js b/app/components/post_list/post_list.js
index ac8be1af8..51b205317 100644
--- a/app/components/post_list/post_list.js
+++ b/app/components/post_list/post_list.js
@@ -13,12 +13,13 @@ import {
import EventEmitter from 'mattermost-redux/utils/event_emitter';
import Post from 'app/components/post';
-import {DATE_LINE, START_OF_NEW_MESSAGES} from 'app/selectors/post_list';
+import {START_OF_NEW_MESSAGES} from 'app/selectors/post_list';
import mattermostManaged from 'app/mattermost_managed';
import {makeExtraData} from 'app/utils/list_view';
import {changeOpacity} from 'app/utils/theme';
import DateHeader from './date_header';
+import {isDateLine} from './date_header/utils';
import NewMessagesDivider from './new_messages_divider';
import withLayout from './with_layout';
@@ -264,9 +265,14 @@ export default class PostList extends PureComponent {
moreMessages={this.moreNewMessages}
/>
);
- } else if (item.indexOf(DATE_LINE) === 0) {
- const date = item.substring(DATE_LINE.length);
- return this.renderDateHeader(new Date(date), index);
+ } else if (isDateLine(item)) {
+ this.itemMeasurements[index] = DATE_HEADER_HEIGHT;
+ return (
+
+ );
}
const postId = item;
@@ -279,16 +285,6 @@ export default class PostList extends PureComponent {
return this.renderPost(postId, previousPostId, nextPostId, index);
};
- renderDateHeader = (date, index) => {
- this.itemMeasurements[index] = DATE_HEADER_HEIGHT;
- return (
-
- );
- };
-
renderPost = (postId, previousPostId, nextPostId, index) => {
const {
highlightPostId,
diff --git a/app/screens/flagged_posts/flagged_posts.js b/app/screens/flagged_posts/flagged_posts.js
index 0b560a3b0..f329083a7 100644
--- a/app/screens/flagged_posts/flagged_posts.js
+++ b/app/screens/flagged_posts/flagged_posts.js
@@ -14,6 +14,7 @@ import {
import ChannelLoader from 'app/components/channel_loader';
import DateHeader from 'app/components/post_list/date_header';
+import {isDateLine} from 'app/components/post_list/date_header/utils';
import FailedNetworkAction from 'app/components/failed_network_action';
import NoResults from 'app/components/no_results';
import PostSeparator from 'app/components/post_separator';
@@ -21,7 +22,6 @@ import StatusBar from 'app/components/status_bar';
import mattermostManaged from 'app/mattermost_managed';
import SearchResultPost from 'app/screens/search/search_result_post';
import ChannelDisplayName from 'app/screens/search/channel_display_name';
-import {DATE_LINE} from 'app/selectors/post_list';
import {changeOpacity} from 'app/utils/theme';
export default class FlaggedPosts extends PureComponent {
@@ -150,13 +150,10 @@ export default class FlaggedPosts extends PureComponent {
renderPost = ({item, index}) => {
const {postIds, theme} = this.props;
const {managedConfig} = this.state;
- if (item.indexOf(DATE_LINE) === 0) {
- const date = new Date(item.substring(DATE_LINE.length));
-
+ if (isDateLine(item)) {
return (
);
@@ -164,7 +161,7 @@ export default class FlaggedPosts extends PureComponent {
let separator;
const nextPost = postIds[index + 1];
- if (nextPost && nextPost.indexOf(DATE_LINE) === -1) {
+ if (nextPost && !isDateLine(nextPost)) {
separator = ;
}
diff --git a/app/screens/recent_mentions/recent_mentions.js b/app/screens/recent_mentions/recent_mentions.js
index 541b9e452..ed6e3b0f7 100644
--- a/app/screens/recent_mentions/recent_mentions.js
+++ b/app/screens/recent_mentions/recent_mentions.js
@@ -14,6 +14,7 @@ import {
import ChannelLoader from 'app/components/channel_loader';
import DateHeader from 'app/components/post_list/date_header';
+import {isDateLine} from 'app/components/post_list/date_header/utils';
import FailedNetworkAction from 'app/components/failed_network_action';
import NoResults from 'app/components/no_results';
import PostSeparator from 'app/components/post_separator';
@@ -21,7 +22,6 @@ import StatusBar from 'app/components/status_bar';
import mattermostManaged from 'app/mattermost_managed';
import SearchResultPost from 'app/screens/search/search_result_post';
import ChannelDisplayName from 'app/screens/search/channel_display_name';
-import {DATE_LINE} from 'app/selectors/post_list';
import {changeOpacity} from 'app/utils/theme';
export default class RecentMentions extends PureComponent {
@@ -150,13 +150,10 @@ export default class RecentMentions extends PureComponent {
renderPost = ({item, index}) => {
const {postIds, theme} = this.props;
const {managedConfig} = this.state;
- if (item.indexOf(DATE_LINE) === 0) {
- const date = new Date(item.substring(DATE_LINE.length));
-
+ if (isDateLine(item)) {
return (
);
@@ -164,7 +161,7 @@ export default class RecentMentions extends PureComponent {
let separator;
const nextPost = postIds[index + 1];
- if (nextPost && nextPost.indexOf(DATE_LINE) === -1) {
+ if (nextPost && !isDateLine(nextPost)) {
separator = ;
}
diff --git a/app/screens/search/search.js b/app/screens/search/search.js
index cd16ad81d..7e17ba525 100644
--- a/app/screens/search/search.js
+++ b/app/screens/search/search.js
@@ -21,6 +21,7 @@ import {RequestStatus} from 'mattermost-redux/constants';
import Autocomplete from 'app/components/autocomplete';
import DateHeader from 'app/components/post_list/date_header';
+import {isDateLine} from 'app/components/post_list/date_header/utils';
import FormattedText from 'app/components/formatted_text';
import Loading from 'app/components/loading';
import PostListRetry from 'app/components/post_list_retry';
@@ -29,7 +30,6 @@ import SafeAreaView from 'app/components/safe_area_view';
import SearchBar from 'app/components/search_bar';
import StatusBar from 'app/components/status_bar';
import mattermostManaged from 'app/mattermost_managed';
-import {DATE_LINE} from 'app/selectors/post_list';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
@@ -260,16 +260,6 @@ export default class Search extends PureComponent {
actions.removeSearchTerms(currentTeamId, item.terms);
});
- renderDateHeader = (date, index) => {
- return (
-
- );
- };
-
renderModifiers = ({item}) => {
const {theme} = this.props;
const style = getStyleFromTheme(theme);
@@ -317,14 +307,18 @@ export default class Search extends PureComponent {
);
}
- if (item.indexOf(DATE_LINE) === 0) {
- const date = item.substring(DATE_LINE.length);
- return this.renderDateHeader(new Date(date), index);
+ if (isDateLine(item)) {
+ return (
+
+ );
}
let separator;
const nextPost = postIds[index + 1];
- if (nextPost && nextPost.indexOf(DATE_LINE) === -1) {
+ if (nextPost && !isDateLine(nextPost)) {
separator = ;
}
diff --git a/app/selectors/post_list.js b/app/selectors/post_list.js
index b138aa6f8..ab738a329 100644
--- a/app/selectors/post_list.js
+++ b/app/selectors/post_list.js
@@ -9,6 +9,7 @@ import {createIdsSelector} from 'mattermost-redux/utils/helpers';
import {shouldFilterJoinLeavePost} from 'mattermost-redux/utils/post_utils';
export const DATE_LINE = 'date-';
+export const DATE_LINE_SUFFIX = '-index-';
export const START_OF_NEW_MESSAGES = 'start-of-new-messages';
function shouldShowJoinLeaveMessages(state) {
@@ -56,7 +57,7 @@ export function makePreparePostIdsForPostList() {
const postDate = new Date(post.create_at);
if (!lastDate || lastDate.toDateString() !== postDate.toDateString()) {
- out.push(DATE_LINE + postDate.toString());
+ out.push(DATE_LINE + post.create_at);
lastDate = postDate;
}
@@ -105,9 +106,14 @@ export function makePreparePostIdsForSearchPosts() {
continue;
}
- const postDate = new Date(post.create_at);
+ // Render a date line for each post, even if displayed on the same date as the
+ // previous post. Since we don't deduplicate here like in other views, we need to
+ // ensure the resulting key is unique, even if the post timestamps (down to the
+ // second) are identical. The screens know to parse out the index before trying
+ // to consume the date value.
+ out.push(DATE_LINE + post.create_at + DATE_LINE_SUFFIX + i);
- out.push(DATE_LINE + postDate.toString(), post.id);
+ out.push(post.id);
}
return out;
diff --git a/app/selectors/post_list.test.js b/app/selectors/post_list.test.js
index d72a1ab52..d69965e00 100644
--- a/app/selectors/post_list.test.js
+++ b/app/selectors/post_list.test.js
@@ -4,15 +4,15 @@
import assert from 'assert';
import {
- DATE_LINE,
makePreparePostIdsForPostList,
+ makePreparePostIdsForSearchPosts,
START_OF_NEW_MESSAGES,
} from 'app/selectors/post_list';
import {Posts, Preferences} from 'mattermost-redux/constants';
import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils';
-/* eslint-disable max-nested-callbacks, no-console */
+/* eslint-disable max-nested-callbacks */
describe('Selectors.PostList', () => {
describe('makePreparePostIdsForPostList', () => {
@@ -44,7 +44,11 @@ describe('Selectors.PostList', () => {
// Defaults to show post
let now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages});
- assert.deepEqual(removeDateLines(now), ['1002', '1001']);
+ assert.deepEqual(now, [
+ '1002',
+ '1001',
+ 'date-0',
+ ]);
// Show join/leave posts
state = {
@@ -66,7 +70,11 @@ describe('Selectors.PostList', () => {
};
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages});
- assert.deepEqual(removeDateLines(now), ['1002', '1001']);
+ assert.deepEqual(now, [
+ '1002',
+ '1001',
+ 'date-0',
+ ]);
// Hide join/leave posts
state = {
@@ -88,7 +96,10 @@ describe('Selectors.PostList', () => {
};
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages});
- assert.deepEqual(removeDateLines(now), ['1001']);
+ assert.deepEqual(now, [
+ '1001',
+ 'date-0',
+ ]);
// always show join/leave posts for the current user
state = {
@@ -107,7 +118,11 @@ describe('Selectors.PostList', () => {
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages});
- assert.deepEqual(removeDateLines(now), ['1002', '1001']);
+ assert.deepEqual(now, [
+ '1002',
+ '1001',
+ 'date-0',
+ ]);
});
it('new messages indicator', () => {
@@ -138,28 +153,66 @@ describe('Selectors.PostList', () => {
// Do not show new messages indicator before all posts
let now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 0, indicateNewMessages: true});
- assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000']);
+ assert.deepEqual(now, [
+ '1010',
+ '1005',
+ '1000',
+ 'date-1000',
+ ]);
now = preparePostIdsForPostList(state, {postIds, indicateNewMessages: true});
- assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000']);
+ assert.deepEqual(now, [
+ '1010',
+ '1005',
+ '1000',
+ 'date-1000',
+ ]);
now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 999, indicateNewMessages: false});
- assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000']);
+ assert.deepEqual(now, [
+ '1010',
+ '1005',
+ '1000',
+ 'date-1000',
+ ]);
// Show new messages indicator before all posts
now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 999, indicateNewMessages: true});
- assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000', START_OF_NEW_MESSAGES]);
+ assert.deepEqual(now, [
+ '1010',
+ '1005',
+ '1000',
+ START_OF_NEW_MESSAGES,
+ 'date-1000',
+ ]);
// Show indicator between posts
now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 1003, indicateNewMessages: true});
- assert.deepEqual(removeDateLines(now), ['1010', '1005', START_OF_NEW_MESSAGES, '1000']);
+ assert.deepEqual(now, [
+ '1010',
+ '1005',
+ START_OF_NEW_MESSAGES,
+ '1000',
+ 'date-1000',
+ ]);
now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 1006, indicateNewMessages: true});
- assert.deepEqual(removeDateLines(now), ['1010', START_OF_NEW_MESSAGES, '1005', '1000']);
+ assert.deepEqual(now, [
+ '1010',
+ START_OF_NEW_MESSAGES,
+ '1005',
+ '1000',
+ 'date-1000',
+ ]);
// Don't show indicator when all posts are read
now = preparePostIdsForPostList(state, {postIds, lastViewedAt: 1020});
- assert.deepEqual(removeDateLines(now), ['1010', '1005', '1000']);
+ assert.deepEqual(now, [
+ '1010',
+ '1005',
+ '1000',
+ 'date-1000',
+ ]);
});
it('memoization', () => {
@@ -197,17 +250,38 @@ describe('Selectors.PostList', () => {
},
};
- let postIds = ['1006', '1004', '1003', '1001'];
+ let postIds = [
+ '1006',
+ '1004',
+ '1003',
+ '1001',
+ ];
let lastViewedAt = initialPosts['1001'].create_at + 1;
let now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
- assert.deepEqual(removeDateLines(now), ['1006', '1004', '1003', START_OF_NEW_MESSAGES, '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ 'date-90000000',
+ '1003',
+ START_OF_NEW_MESSAGES,
+ '1001',
+ 'date-3600000',
+ ]);
// No changes
let prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', '1003', START_OF_NEW_MESSAGES, '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ 'date-90000000',
+ '1003',
+ START_OF_NEW_MESSAGES,
+ '1001',
+ 'date-3600000',
+ ]);
// lastViewedAt changed slightly
lastViewedAt = initialPosts['1001'].create_at + 2;
@@ -215,7 +289,15 @@ describe('Selectors.PostList', () => {
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', '1003', START_OF_NEW_MESSAGES, '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ 'date-90000000',
+ '1003',
+ START_OF_NEW_MESSAGES,
+ '1001',
+ 'date-3600000',
+ ]);
// lastViewedAt changed a lot
lastViewedAt += initialPosts['1003'].create_at + 1;
@@ -223,12 +305,28 @@ describe('Selectors.PostList', () => {
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.notEqual(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
// postIds changed, but still shallowly equal
postIds = [...postIds];
@@ -236,7 +334,15 @@ describe('Selectors.PostList', () => {
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
// Post changed, not in postIds
state = {
@@ -256,7 +362,15 @@ describe('Selectors.PostList', () => {
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
// Post changed, in postIds
state = {
@@ -276,7 +390,15 @@ describe('Selectors.PostList', () => {
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1006', '1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1006',
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
// Filter changed
state = {
@@ -300,17 +422,110 @@ describe('Selectors.PostList', () => {
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.notEqual(now, prev);
- assert.deepEqual(removeDateLines(now), ['1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
prev = now;
now = preparePostIdsForPostList(state, {postIds, lastViewedAt, indicateNewMessages: true});
assert.equal(now, prev);
- assert.deepEqual(removeDateLines(now), ['1004', START_OF_NEW_MESSAGES, '1003', '1001']);
+ assert.deepEqual(now, [
+ '1004',
+ START_OF_NEW_MESSAGES,
+ 'date-90000000',
+ '1003',
+ '1001',
+ 'date-3600000',
+ ]);
+ });
+ });
+
+ describe('makePreparePostIdsForSearchPosts', () => {
+ it('should return an empty array if there are no posts specified', () => {
+ const preparePostIdsForSearchPosts = makePreparePostIdsForSearchPosts();
+
+ const state = {
+ entities: {
+ posts: {
+ posts: {
+ 1001: {id: '1001', create_at: 0, type: ''},
+ 1002: {id: '1002', create_at: 1, type: ''},
+ },
+ },
+ users: {
+ currentUserId: '1234',
+ profiles: {
+ 1234: {id: '1234', username: 'user'},
+ },
+ },
+ },
+ };
+
+ const postIds = [];
+ const actual = preparePostIdsForSearchPosts(state, postIds);
+ assert.deepEqual(actual, []);
+ });
+
+ it('should return an empty array if there are no matching posts', () => {
+ const preparePostIdsForSearchPosts = makePreparePostIdsForSearchPosts();
+
+ const state = {
+ entities: {
+ posts: {
+ posts: {},
+ },
+ users: {
+ currentUserId: '1234',
+ profiles: {
+ 1234: {id: '1234', username: 'user'},
+ },
+ },
+ },
+ };
+
+ const postIds = ['1002', '1001'];
+ const actual = preparePostIdsForSearchPosts(state, postIds);
+ assert.deepEqual(actual, []);
+ });
+
+ it('should return results when there are posts', () => {
+ const preparePostIdsForSearchPosts = makePreparePostIdsForSearchPosts();
+
+ const state = {
+ entities: {
+ posts: {
+ posts: {
+ 1001: {id: '1001', create_at: 0, type: ''},
+ 1002: {id: '1002', create_at: 1000, type: ''},
+
+ // Same timestamp as 1002
+ 1003: {id: '1003', create_at: 1000, type: ''},
+ },
+ },
+ users: {
+ currentUserId: '1234',
+ profiles: {
+ 1234: {id: '1234', username: 'user'},
+ },
+ },
+ },
+ };
+
+ const postIds = ['1003', '1002', '1001'];
+ const actual = preparePostIdsForSearchPosts(state, postIds);
+ assert.deepEqual(actual, [
+ 'date-1000-index-0',
+ '1003',
+ 'date-1000-index-1',
+ '1002',
+ 'date-0-index-2',
+ '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));
-}