mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-28 04:13:18 +01:00
Timeline: repair oldest/newest metrics if we fetch nothing
This commit is contained in:
384
ts/test-both/state/ducks/conversations_test.ts
Normal file
384
ts/test-both/state/ducks/conversations_test.ts
Normal file
@@ -0,0 +1,384 @@
|
||||
// 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user