signal-desktop/ts/test-both/state/ducks/conversations_test.ts

384 lines
10 KiB
TypeScript

// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import {
actions,
ConversationMessageType,
ConversationsStateType,
ConversationType,
getConversationCallMode,
MessageType,
reducer,
} from '../../../state/ducks/conversations';
import { CallMode } from '../../../types/Calling';
const { repairNewestMessage, repairOldestMessage } = actions;
describe('both/state/ducks/conversations', () => {
describe('helpers', () => {
describe('getConversationCallMode', () => {
const fakeConversation: ConversationType = {
id: 'id1',
e164: '+18005551111',
activeAt: Date.now(),
name: 'No timestamp',
timestamp: 0,
inboxPosition: 0,
phoneNumber: 'notused',
isArchived: false,
markedUnread: false,
type: 'direct',
isMe: false,
lastUpdated: Date.now(),
title: 'No timestamp',
unreadCount: 1,
isSelected: false,
typingContact: {
name: 'Someone There',
color: 'blue',
phoneNumber: '+18005551111',
},
acceptedMessageRequest: true,
};
it("returns CallMode.None if you've left the conversation", () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
left: true,
}),
CallMode.None
);
});
it("returns CallMode.None if you've blocked the other person", () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
isBlocked: true,
}),
CallMode.None
);
});
it("returns CallMode.None if you haven't accepted message requests", () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
acceptedMessageRequest: false,
}),
CallMode.None
);
});
it('returns CallMode.None if the conversation is Note to Self', () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
isMe: true,
}),
CallMode.None
);
});
it('returns CallMode.None for v1 groups', () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
type: 'group',
groupVersion: 1,
}),
CallMode.None
);
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
type: 'group',
}),
CallMode.None
);
});
it('returns CallMode.Direct if the conversation is a normal direct conversation', () => {
assert.strictEqual(
getConversationCallMode(fakeConversation),
CallMode.Direct
);
});
it('returns CallMode.Group if the conversation is a v2 group', () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
type: 'group',
groupVersion: 2,
}),
CallMode.Group
);
});
});
});
describe('reducer', () => {
const time = Date.now();
const conversationId = 'conversation-guid-1';
const messageId = 'message-guid-1';
const messageIdTwo = 'message-guid-2';
const messageIdThree = 'message-guid-3';
function getDefaultState(): ConversationsStateType {
return {
conversationLookup: {},
selectedMessageCounter: 0,
selectedConversationPanelDepth: 0,
showArchived: false,
messagesLookup: {},
messagesByConversation: {},
};
}
function getDefaultMessage(id: string): MessageType {
return {
id,
conversationId: 'conversationId',
source: 'source',
type: 'incoming' as const,
received_at: Date.now(),
attachments: [],
sticker: {},
unread: false,
};
}
function getDefaultConversationMessage(): ConversationMessageType {
return {
heightChangeMessageIds: [],
isLoadingMessages: false,
messageIds: [],
metrics: {
totalUnread: 0,
},
resetCounter: 0,
scrollToMessageCounter: 0,
};
}
describe('REPAIR_NEWEST_MESSAGE', () => {
it('updates newest', () => {
const action = repairNewestMessage(conversationId);
const state: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [messageIdThree, messageIdTwo, messageId],
metrics: {
totalUnread: 0,
},
},
},
};
const expected: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [messageIdThree, messageIdTwo, messageId],
metrics: {
totalUnread: 0,
newest: {
id: messageId,
received_at: time,
},
},
},
},
};
const actual = reducer(state, action);
assert.deepEqual(actual, expected);
});
it('clears newest', () => {
const action = repairNewestMessage(conversationId);
const state: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [],
metrics: {
totalUnread: 0,
newest: {
id: messageId,
received_at: time,
},
},
},
},
};
const expected: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [],
metrics: {
newest: undefined,
totalUnread: 0,
},
},
},
};
const actual = reducer(state, action);
assert.deepEqual(actual, expected);
});
it('returns state if conversation not present', () => {
const action = repairNewestMessage(conversationId);
const state: ConversationsStateType = getDefaultState();
const actual = reducer(state, action);
assert.equal(actual, state);
});
});
describe('REPAIR_OLDEST_MESSAGE', () => {
it('updates oldest', () => {
const action = repairOldestMessage(conversationId);
const state: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [messageId, messageIdTwo, messageIdThree],
metrics: {
totalUnread: 0,
},
},
},
};
const expected: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [messageId, messageIdTwo, messageIdThree],
metrics: {
totalUnread: 0,
oldest: {
id: messageId,
received_at: time,
},
},
},
},
};
const actual = reducer(state, action);
assert.deepEqual(actual, expected);
});
it('clears oldest', () => {
const action = repairOldestMessage(conversationId);
const state: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [],
metrics: {
totalUnread: 0,
oldest: {
id: messageId,
received_at: time,
},
},
},
},
};
const expected: ConversationsStateType = {
...getDefaultState(),
messagesLookup: {
[messageId]: {
...getDefaultMessage(messageId),
received_at: time,
},
},
messagesByConversation: {
[conversationId]: {
...getDefaultConversationMessage(),
messageIds: [],
metrics: {
oldest: undefined,
totalUnread: 0,
},
},
},
};
const actual = reducer(state, action);
assert.deepEqual(actual, expected);
});
it('returns state if conversation not present', () => {
const action = repairOldestMessage(conversationId);
const state: ConversationsStateType = getDefaultState();
const actual = reducer(state, action);
assert.equal(actual, state);
});
});
});
});