Tracks send state for edited messages

This commit is contained in:
Josh Perez 2023-08-15 19:24:19 -04:00 committed by Jamie Kyle
parent 860bec5534
commit b2319b43d6
8 changed files with 391 additions and 55 deletions

View file

@ -5,12 +5,14 @@ import { Proto } from '@signalapp/mock-server';
import { assert } from 'chai';
import createDebug from 'debug';
import Long from 'long';
import { strictAssert } from '../../util/assert';
import * as durations from '../../util/durations';
import type { App } from '../playwright';
import * as durations from '../../util/durations';
import { Bootstrap } from '../bootstrap';
import { ReceiptType } from '../../types/Receipt';
import { SendStatus } from '../../messages/MessageSendState';
import { sleep } from '../../util/sleep';
import { strictAssert } from '../../util/assert';
export const debug = createDebug('mock:test:edit');
@ -74,7 +76,7 @@ describe('editing', function needsName() {
await bootstrap.teardown();
});
it('handles outgoing edited messages phone to desktop', async () => {
it('handles incoming edited messages phone to desktop', async () => {
const { phone, desktop } = bootstrap;
const window = await app.getWindow();
@ -403,4 +405,257 @@ describe('editing', function needsName() {
const messages = window.locator('.module-message__text');
assert.strictEqual(await messages.count(), 1, 'message count');
});
it('tracks message send state for edits', async () => {
const { contacts, desktop } = bootstrap;
const [friend] = contacts;
const contact = friend.toContact();
const page = await app.getWindow();
debug('message sent friend -> desktop');
await friend.sendText(desktop, 'hello', {
timestamp: bootstrap.getTimestamp(),
});
debug('opening conversation');
const leftPane = page.locator('#LeftPane');
await leftPane
.locator('.module-conversation-list__item--contact-or-conversation')
.first()
.click();
await page.locator('.module-conversation-hero').waitFor();
// Sending the original message
// getting a read receipt
// testing the message's send state
const originalText = 'v1';
debug('finding composition input and clicking it');
{
const input = await app.waitForEnabledComposer();
debug('sending message desktop -> friend');
await input.type(originalText);
await input.press('Enter');
}
debug("waiting for message on friend's device");
const { dataMessage: originalMessage } = await friend.waitForMessage();
assert.strictEqual(
originalMessage.body,
originalText,
'original message is correct'
);
strictAssert(originalMessage.timestamp, 'timestamp missing');
const originalMessageTimestamp = Number(originalMessage.timestamp);
debug('original message', { timestamp: originalMessageTimestamp });
{
const readReceiptTimestamp = bootstrap.getTimestamp();
debug('sending read receipt friend -> desktop', {
target: originalMessageTimestamp,
timestamp: readReceiptTimestamp,
});
const readReceiptSendOptions = {
timestamp: readReceiptTimestamp,
};
await friend.sendRaw(
desktop,
{
receiptMessage: {
type: 1,
timestamp: [originalMessage.timestamp],
},
},
readReceiptSendOptions
);
}
debug("getting friend's conversationId");
const conversationId = await page.evaluate(
serviceId => window.SignalCI?.getConversationId(serviceId),
contact.uuid
);
debug(`got friend's conversationId: ${conversationId}`);
strictAssert(conversationId, 'conversationId exists');
debug("testing message's send state (original)");
{
debug('getting message from app (original)');
const messages = await page.evaluate(
timestamp => window.SignalCI?.getMessagesBySentAt(timestamp),
originalMessageTimestamp
);
strictAssert(messages, 'messages does not exist');
debug('verifying message send state (original)');
const [message] = messages;
strictAssert(
message.sendStateByConversationId,
'sendStateByConversationId'
);
assert.strictEqual(
message.sendStateByConversationId[conversationId].status,
SendStatus.Read,
'send state is read for main message'
);
assert.isUndefined(message.editHistory, 'no edit history, yet');
}
// Sending a v2 edited message targetting the original
// this one goes unread
// but we'll still test the send state
const editMessageV2Text = 'v2';
debug('finding composition input and clicking it v2');
{
const input = await app.waitForEnabledComposer();
debug('sending edit message v2 desktop -> friend');
await sleep(50);
await input.press('ArrowUp');
await input.press('Backspace');
await input.press('Backspace');
await input.type(editMessageV2Text);
await input.press('Enter');
}
debug("waiting for message on friend's device (original)");
const { editMessage: editMessageV2 } = await friend.waitForEditMessage();
assert.strictEqual(editMessageV2.dataMessage?.body, editMessageV2Text);
debug('v2 message', {
timestamp: Number(editMessageV2.dataMessage?.timestamp),
});
// Sending a v3 edited message targetting v2
// v3 will be read after we receive v4
const editMessageV3Text = 'v3';
debug('finding composition input and clicking it v3');
{
const input = await app.waitForEnabledComposer();
debug('sending edit message v3 desktop -> friend');
await sleep(50);
await input.press('ArrowUp');
await input.press('Backspace');
await input.press('Backspace');
await input.type(editMessageV3Text);
await input.press('Enter');
}
debug("waiting for message on friend's device (v3)");
const { editMessage: editMessageV3 } = await friend.waitForEditMessage();
assert.strictEqual(editMessageV3.dataMessage?.body, editMessageV3Text);
strictAssert(editMessageV3.dataMessage?.timestamp, 'timestamp missing');
const editMessageV3Timestamp = Number(editMessageV3.dataMessage.timestamp);
debug('v3 message', { timestamp: editMessageV3Timestamp });
// Sending a v4 edited message targetting v3
// getting a read receipt for v3
// testing send state of the full message
const editMessageV4Text = 'v4';
debug('finding composition input and clicking it v4');
{
const input = await app.waitForEnabledComposer();
debug('sending edit message v4 desktop -> friend');
await sleep(50);
await input.press('ArrowUp');
await input.press('Backspace');
await input.press('Backspace');
await input.type(editMessageV4Text);
await input.press('Enter');
}
debug("waiting for message on friend's device (v4)");
const { editMessage: editMessageV4 } = await friend.waitForEditMessage();
assert.strictEqual(editMessageV4.dataMessage?.body, editMessageV4Text);
strictAssert(editMessageV4.dataMessage?.timestamp, 'timestamp missing');
const editMessageV4Timestamp = Number(editMessageV4.dataMessage.timestamp);
debug('v4 message', { timestamp: editMessageV4Timestamp });
{
const readReceiptTimestamp = bootstrap.getTimestamp();
debug('sending read receipt for edit v3 friend -> desktop', {
target: editMessageV3Timestamp,
timestamp: readReceiptTimestamp,
});
const readReceiptSendOptions = {
timestamp: readReceiptTimestamp,
};
await friend.sendRaw(
desktop,
{
receiptMessage: {
type: 1,
timestamp: [editMessageV3.dataMessage.timestamp],
},
},
readReceiptSendOptions
);
}
debug("testing v4's send state");
{
debug('getting edited message from app (v4)');
const messages = await page.evaluate(
timestamp => window.SignalCI?.getMessagesBySentAt(timestamp),
originalMessageTimestamp
);
strictAssert(messages, 'messages does not exist');
debug('verifying edited message send state (v4)');
const [message] = messages;
strictAssert(
message.sendStateByConversationId,
'sendStateByConversationId'
);
assert.strictEqual(
message.sendStateByConversationId[conversationId].status,
SendStatus.Sent,
'original message send state is sent (v4)'
);
strictAssert(message.editHistory, 'edit history exists');
const [v4, v3, v2, v1] = message.editHistory;
strictAssert(v1.sendStateByConversationId, 'v1 has send state');
assert.strictEqual(
v1.sendStateByConversationId[conversationId].status,
SendStatus.Read,
'send state for first message is read'
);
strictAssert(v2.sendStateByConversationId, 'v2 has send state');
assert.strictEqual(
v2.sendStateByConversationId[conversationId].status,
SendStatus.Pending,
'send state for v2 message is pending'
);
strictAssert(v3.sendStateByConversationId, 'v3 has send state');
assert.strictEqual(
v3.sendStateByConversationId[conversationId].status,
SendStatus.Read,
'send state for v3 message is read'
);
strictAssert(v4.sendStateByConversationId, 'v4 has send state');
assert.strictEqual(
v4.sendStateByConversationId[conversationId].status,
SendStatus.Pending,
'send state for v4 message is pending'
);
assert.strictEqual(
v4.body,
message.body,
'body is same for v4 and main message'
);
}
});
});