signal-desktop/ts/test-both/messages/migrateLegacySendAttributes_test.ts
2023-08-21 09:30:33 -07:00

263 lines
7.6 KiB
TypeScript

// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { v4 as uuid } from 'uuid';
import { getDefaultConversation } from '../helpers/getDefaultConversation';
import type { ConversationType } from '../../state/ducks/conversations';
import { SendStatus } from '../../messages/MessageSendState';
import { migrateLegacySendAttributes } from '../../messages/migrateLegacySendAttributes';
describe('migrateLegacySendAttributes', () => {
const defaultMessage = {
type: 'outgoing' as const,
sent_at: 123,
sent: true,
};
const createGetConversation = (
...conversations: ReadonlyArray<ConversationType>
) => {
const lookup = new Map<string, ConversationType>();
conversations.forEach(conversation => {
[conversation.id, conversation.serviceId, conversation.e164].forEach(
property => {
if (property) {
lookup.set(property, conversation);
}
}
);
});
return (id?: string | null) => (id ? lookup.get(id) : undefined);
};
it("doesn't migrate messages that already have the modern send state", () => {
const ourConversationId = uuid();
const message = {
...defaultMessage,
sendStateByConversationId: {
[ourConversationId]: {
status: SendStatus.Sent,
updatedAt: 123,
},
},
};
const getConversation = () => undefined;
assert.isUndefined(
migrateLegacySendAttributes(message, getConversation, ourConversationId)
);
});
it("doesn't migrate messages that aren't outgoing", () => {
const ourConversationId = uuid();
const message = {
...defaultMessage,
type: 'incoming' as const,
};
const getConversation = () => undefined;
assert.isUndefined(
migrateLegacySendAttributes(message, getConversation, ourConversationId)
);
});
it('advances the send state machine, starting from "pending", for different state types', () => {
let e164Counter = 0;
const getTestConversation = () => {
const last4Digits = e164Counter.toString().padStart(4);
assert.strictEqual(
last4Digits.length,
4,
'Test setup failure: E164 is too long'
);
e164Counter += 1;
return getDefaultConversation({ e164: `+1999555${last4Digits}` });
};
// This is aliased for clarity.
const ignoredUuid = uuid;
const failedConversationByUuid = getTestConversation();
const failedConversationByE164 = getTestConversation();
const pendingConversation = getTestConversation();
const sentConversation = getTestConversation();
const deliveredConversation = getTestConversation();
const readConversation = getTestConversation();
const conversationNotInRecipientsList = getTestConversation();
const ourConversation = getTestConversation();
const message = {
...defaultMessage,
recipients: [
failedConversationByUuid.serviceId,
failedConversationByE164.serviceId,
pendingConversation.serviceId,
sentConversation.serviceId,
deliveredConversation.serviceId,
readConversation.serviceId,
ignoredUuid(),
ourConversation.serviceId,
],
errors: [
Object.assign(new Error('looked up by UUID'), {
identifier: failedConversationByUuid.serviceId,
}),
Object.assign(new Error('looked up by E164'), {
number: failedConversationByE164.e164,
}),
Object.assign(new Error('ignored error'), {
identifier: ignoredUuid(),
}),
new Error('a different error'),
],
sent_to: [
sentConversation.e164,
conversationNotInRecipientsList.serviceId,
ignoredUuid(),
ourConversation.serviceId,
],
delivered_to: [
deliveredConversation.serviceId,
ignoredUuid(),
ourConversation.serviceId,
],
read_by: [readConversation.serviceId, ignoredUuid()],
};
const getConversation = createGetConversation(
failedConversationByUuid,
failedConversationByE164,
pendingConversation,
sentConversation,
deliveredConversation,
readConversation,
conversationNotInRecipientsList,
ourConversation
);
assert.deepEqual(
migrateLegacySendAttributes(message, getConversation, ourConversation.id),
{
[ourConversation.id]: {
status: SendStatus.Delivered,
updatedAt: undefined,
},
[failedConversationByUuid.id]: {
status: SendStatus.Failed,
updatedAt: undefined,
},
[failedConversationByE164.id]: {
status: SendStatus.Failed,
updatedAt: undefined,
},
[pendingConversation.id]: {
status: SendStatus.Pending,
updatedAt: message.sent_at,
},
[sentConversation.id]: {
status: SendStatus.Sent,
updatedAt: undefined,
},
[conversationNotInRecipientsList.id]: {
status: SendStatus.Sent,
updatedAt: undefined,
},
[deliveredConversation.id]: {
status: SendStatus.Delivered,
updatedAt: undefined,
},
[readConversation.id]: {
status: SendStatus.Read,
updatedAt: undefined,
},
}
);
});
it('considers our own conversation sent if the "sent" attribute is set', () => {
const ourConversation = getDefaultConversation();
const conversation1 = getDefaultConversation();
const conversation2 = getDefaultConversation();
const message = {
...defaultMessage,
recipients: [conversation1.id, conversation2.id],
sent: true,
};
const getConversation = createGetConversation(
ourConversation,
conversation1,
conversation2
);
assert.deepEqual(
migrateLegacySendAttributes(
message,
getConversation,
ourConversation.id
)?.[ourConversation.id],
{
status: SendStatus.Sent,
updatedAt: undefined,
}
);
});
it("considers our own conversation failed if the message isn't marked sent and we aren't elsewhere in the recipients list", () => {
const ourConversation = getDefaultConversation();
const conversation1 = getDefaultConversation();
const conversation2 = getDefaultConversation();
const message = {
...defaultMessage,
recipients: [conversation1.id, conversation2.id],
sent: false,
};
const getConversation = createGetConversation(
ourConversation,
conversation1,
conversation2
);
assert.deepEqual(
migrateLegacySendAttributes(
message,
getConversation,
ourConversation.id
)?.[ourConversation.id],
{
status: SendStatus.Failed,
updatedAt: undefined,
}
);
});
it('migrates a typical legacy note to self message', () => {
const ourConversation = getDefaultConversation();
const message = {
...defaultMessage,
conversationId: ourConversation.id,
recipients: [],
destination: ourConversation.serviceId,
sent_to: [ourConversation.serviceId],
sent: true,
synced: true,
unidentifiedDeliveries: [],
delivered_to: [ourConversation.id],
read_by: [ourConversation.id],
};
const getConversation = createGetConversation(ourConversation);
assert.deepEqual(
migrateLegacySendAttributes(message, getConversation, ourConversation.id),
{
[ourConversation.id]: {
status: SendStatus.Read,
updatedAt: undefined,
},
}
);
});
});