From c3bf2a4e965ef58986c4073b04df8f997a151aeb Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 6 Jul 2021 17:16:05 +1000 Subject: [PATCH] fixes and tests --- ts/components/ConversationListItem.tsx | 2 +- .../session/LeftPaneMessageSection.tsx | 7 +- ts/components/session/menu/Menu.tsx | 2 +- ts/models/conversation.ts | 8 +- ts/state/ducks/conversations.ts | 2 +- ts/state/selectors/conversations.ts | 8 + .../unit/selectors/conversations_test.ts | 206 ++++++++++++++++++ ts/test/state/selectors/conversations_test.ts | 103 --------- ts/test/test-utils/utils/message.ts | 1 + 9 files changed, 223 insertions(+), 116 deletions(-) create mode 100644 ts/test/session/unit/selectors/conversations_test.ts delete mode 100644 ts/test/state/selectors/conversations_test.ts diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index 3a56e5997..545385274 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -155,7 +155,7 @@ export interface ConversationListItemHeaderProps { unreadCount: number; mentionedUs: boolean; activeAt?: number; - isPinned?: boolean; + isPinned: boolean; name?: string; phoneNumber: string; diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index d0603d6d8..665293eb3 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -77,17 +77,12 @@ export class LeftPaneMessageSection extends React.Component { } public renderRow = ({ index, key, style }: RowRendererParamsType): JSX.Element => { - const { openConversationExternal } = this.props; - let { conversations } = this.props; + const { conversations, openConversationExternal } = this.props; if (!conversations) { throw new Error('renderRow: Tried to render without conversations'); } - conversations = _.sortBy([...conversations], convo => { - return convo.isPinned ? -1 : 1; - }); - const conversation = conversations[index]; return ( diff --git a/ts/components/session/menu/Menu.tsx b/ts/components/session/menu/Menu.tsx index 2216d478e..ff03f5c89 100644 --- a/ts/components/session/menu/Menu.tsx +++ b/ts/components/session/menu/Menu.tsx @@ -135,7 +135,7 @@ export const MenuItemPinConversation = ( ): JSX.Element | null => { const { conversationId } = props; const conversation = getConversationController().get(conversationId); - const isPinned = conversation.getIsPinned(); + const isPinned = conversation.isPinned(); const nbOfAlreadyPinnedConvos = useSelector(getNumberOfPinnedConversations); const togglePinConversation = async () => { diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 848cfbc3a..5dae6d3c5 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -91,7 +91,7 @@ export interface ConversationAttributes { accessKey?: any; triggerNotificationsFor: ConversationNotificationSettingType; isTrustedForAttachmentDownload: boolean; - isPinned?: boolean; + isPinned: boolean; } export interface ConversationAttributesOptionals { @@ -129,7 +129,7 @@ export interface ConversationAttributesOptionals { accessKey?: any; triggerNotificationsFor?: ConversationNotificationSettingType; isTrustedForAttachmentDownload?: boolean; - isPinned?: boolean; + isPinned: boolean; } /** @@ -407,7 +407,7 @@ export class ConversationModel extends Backbone.Model { left: !!this.get('left'), groupAdmins, members, - isPinned: this.getIsPinned(), + isPinned: this.isPinned(), }; } @@ -1234,7 +1234,7 @@ export class ConversationModel extends Backbone.Model { return this.get('name') || window.i18n('unknown'); } - public getIsPinned() { + public isPinned() { return this.get('isPinned'); } diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index a5ecb17bb..eb20669f9 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -82,7 +82,7 @@ export interface ConversationType { avatarPath?: string; // absolute filepath to the avatar groupAdmins?: Array; // admins for closed groups and moderators for open groups members?: Array; // members for closed groups only - isPinned?: boolean; + isPinned: boolean; } export type ConversationLookupType = { diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 5ebea6395..f580406f3 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -64,6 +64,14 @@ const collator = new Intl.Collator(); export const _getConversationComparator = (testingi18n?: LocalizerType) => { return (left: ConversationType, right: ConversationType): number => { + // Pin is the first criteria to check + if (left.isPinned && !right.isPinned) { + return -1; + } + if (!left.isPinned && right.isPinned) { + return 1; + } + // Then if none is pinned, check other criteria const leftActiveAt = left.activeAt; const rightActiveAt = right.activeAt; if (leftActiveAt && !rightActiveAt) { diff --git a/ts/test/session/unit/selectors/conversations_test.ts b/ts/test/session/unit/selectors/conversations_test.ts new file mode 100644 index 000000000..06b494aa5 --- /dev/null +++ b/ts/test/session/unit/selectors/conversations_test.ts @@ -0,0 +1,206 @@ +import { assert } from 'chai'; +import { ConversationTypeEnum } from '../../../../models/conversation'; + +import { ConversationLookupType } from '../../../../state/ducks/conversations'; +import { + _getConversationComparator, + _getLeftPaneLists, +} from '../../../../state/selectors/conversations'; + +describe('state/selectors/conversations', () => { + describe('#getLeftPaneList', () => { + it('sorts conversations based on timestamp then by intl-friendly title', () => { + const i18n = (key: string) => key; + const data: ConversationLookupType = { + id1: { + id: 'id1', + activeAt: 0, + name: 'No timestamp', + phoneNumber: 'notused', + + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + id2: { + id: 'id2', + activeAt: 20, + name: 'B', + phoneNumber: 'notused', + + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + id3: { + id: 'id3', + activeAt: 20, + name: 'C', + phoneNumber: 'notused', + + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + id4: { + id: 'id4', + activeAt: 20, + name: 'Á', + phoneNumber: 'notused', + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + id5: { + id: 'id5', + activeAt: 30, + name: 'First!', + phoneNumber: 'notused', + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + }; + const comparator = _getConversationComparator(i18n); + const { conversations } = _getLeftPaneLists(data, comparator); + + assert.strictEqual(conversations[0].name, 'First!'); + assert.strictEqual(conversations[1].name, 'Á'); + assert.strictEqual(conversations[2].name, 'B'); + assert.strictEqual(conversations[3].name, 'C'); + }); + }); + + describe('#getLeftPaneListWithPinned', () => { + it('sorts conversations based on pin, timestamp then by intl-friendly title', () => { + const i18n = (key: string) => key; + const data: ConversationLookupType = { + id1: { + id: 'id1', + activeAt: 0, + name: 'No timestamp', + phoneNumber: 'notused', + + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + id2: { + id: 'id2', + activeAt: 20, + name: 'B', + phoneNumber: 'notused', + + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + id3: { + id: 'id3', + activeAt: 20, + name: 'C', + phoneNumber: 'notused', + + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: true, + }, + id4: { + id: 'id4', + activeAt: 20, + name: 'Á', + phoneNumber: 'notused', + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: true, + }, + id5: { + id: 'id5', + activeAt: 30, + name: 'First!', + phoneNumber: 'notused', + type: ConversationTypeEnum.PRIVATE, + isMe: false, + unreadCount: 1, + mentionedUs: false, + isSelected: false, + isTyping: false, + isBlocked: false, + isKickedFromGroup: false, + left: false, + isPinned: false, + }, + }; + const comparator = _getConversationComparator(i18n); + const { conversations } = _getLeftPaneLists(data, comparator); + + assert.strictEqual(conversations[0].name, 'Á'); + assert.strictEqual(conversations[1].name, 'C'); + assert.strictEqual(conversations[2].name, 'First!'); + assert.strictEqual(conversations[3].name, 'B'); + }); + }); +}); diff --git a/ts/test/state/selectors/conversations_test.ts b/ts/test/state/selectors/conversations_test.ts deleted file mode 100644 index 99810915e..000000000 --- a/ts/test/state/selectors/conversations_test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { assert } from 'chai'; -import { ConversationTypeEnum } from '../../../models/conversation'; - -import { ConversationLookupType } from '../../../state/ducks/conversations'; -import { - _getConversationComparator, - _getLeftPaneLists, -} from '../../../state/selectors/conversations'; - -describe('state/selectors/conversations', () => { - describe('#getLeftPaneList', () => { - it('sorts conversations based on timestamp then by intl-friendly title', () => { - const i18n = (key: string) => key; - const data: ConversationLookupType = { - id1: { - id: 'id1', - activeAt: 0, - name: 'No timestamp', - phoneNumber: 'notused', - - type: ConversationTypeEnum.PRIVATE, - isMe: false, - unreadCount: 1, - mentionedUs: false, - isSelected: false, - isTyping: false, - isBlocked: false, - isKickedFromGroup: false, - left: false, - }, - id2: { - id: 'id2', - activeAt: 20, - name: 'B', - phoneNumber: 'notused', - - type: ConversationTypeEnum.PRIVATE, - isMe: false, - unreadCount: 1, - mentionedUs: false, - isSelected: false, - isTyping: false, - isBlocked: false, - isKickedFromGroup: false, - left: false, - }, - id3: { - id: 'id3', - activeAt: 20, - name: 'C', - phoneNumber: 'notused', - - type: ConversationTypeEnum.PRIVATE, - isMe: false, - unreadCount: 1, - mentionedUs: false, - isSelected: false, - isTyping: false, - isBlocked: false, - isKickedFromGroup: false, - left: false, - }, - id4: { - id: 'id4', - activeAt: 20, - name: 'Á', - phoneNumber: 'notused', - type: ConversationTypeEnum.PRIVATE, - isMe: false, - unreadCount: 1, - mentionedUs: false, - isSelected: false, - isTyping: false, - isBlocked: false, - isKickedFromGroup: false, - left: false, - }, - id5: { - id: 'id5', - activeAt: 30, - name: 'First!', - phoneNumber: 'notused', - type: ConversationTypeEnum.PRIVATE, - isMe: false, - unreadCount: 1, - mentionedUs: false, - isSelected: false, - isTyping: false, - isBlocked: false, - isKickedFromGroup: false, - left: false, - }, - }; - const comparator = _getConversationComparator(i18n); - const { conversations } = _getLeftPaneLists(data, comparator); - - assert.strictEqual(conversations[0].name, 'First!'); - assert.strictEqual(conversations[1].name, 'Á'); - assert.strictEqual(conversations[2].name, 'B'); - assert.strictEqual(conversations[3].name, 'C'); - }); - }); -}); diff --git a/ts/test/test-utils/utils/message.ts b/ts/test/test-utils/utils/message.ts index bb658a5d9..4d0cdf6f2 100644 --- a/ts/test/test-utils/utils/message.ts +++ b/ts/test/test-utils/utils/message.ts @@ -88,6 +88,7 @@ export class MockConversation { zombies: [], triggerNotificationsFor: 'all', isTrustedForAttachmentDownload: false, + isPinned: false, }; }