Refactor outbound delivery state
This commit is contained in:
parent
831ec98418
commit
9c48a95eb5
29 changed files with 3200 additions and 697 deletions
263
ts/test-both/messages/migrateLegacySendAttributes_test.ts
Normal file
263
ts/test-both/messages/migrateLegacySendAttributes_test.ts
Normal file
|
@ -0,0 +1,263 @@
|
|||
// 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 { 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.uuid, 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.uuid,
|
||||
failedConversationByE164.uuid,
|
||||
pendingConversation.uuid,
|
||||
sentConversation.uuid,
|
||||
deliveredConversation.uuid,
|
||||
readConversation.uuid,
|
||||
ignoredUuid(),
|
||||
ourConversation.uuid,
|
||||
],
|
||||
errors: [
|
||||
Object.assign(new Error('looked up by UUID'), {
|
||||
identifier: failedConversationByUuid.uuid,
|
||||
}),
|
||||
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.uuid,
|
||||
ignoredUuid(),
|
||||
ourConversation.uuid,
|
||||
],
|
||||
delivered_to: [
|
||||
deliveredConversation.uuid,
|
||||
ignoredUuid(),
|
||||
ourConversation.uuid,
|
||||
],
|
||||
read_by: [readConversation.uuid, 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.uuid,
|
||||
sent_to: [ourConversation.uuid],
|
||||
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,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue