2023-03-27 23:48:57 +00:00
|
|
|
// Copyright 2023 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2023-03-29 21:58:16 +00:00
|
|
|
import { Proto } from '@signalapp/mock-server';
|
2023-03-27 23:48:57 +00:00
|
|
|
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 { Bootstrap } from '../bootstrap';
|
2023-03-29 21:58:16 +00:00
|
|
|
import { ReceiptType } from '../../types/Receipt';
|
2023-03-27 23:48:57 +00:00
|
|
|
|
|
|
|
export const debug = createDebug('mock:test:edit');
|
|
|
|
|
|
|
|
function wrap({
|
|
|
|
dataMessage,
|
|
|
|
editMessage,
|
|
|
|
}: {
|
|
|
|
dataMessage?: Proto.IDataMessage;
|
|
|
|
editMessage?: Proto.IEditMessage;
|
|
|
|
}): Proto.IContent {
|
|
|
|
return {
|
|
|
|
dataMessage,
|
|
|
|
editMessage,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function createMessage(): Proto.IDataMessage {
|
|
|
|
return {
|
|
|
|
body: 'hey yhere',
|
|
|
|
groupV2: undefined,
|
|
|
|
timestamp: Long.fromNumber(Date.now()),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function createEditedMessage(
|
|
|
|
targetMessage: Proto.IDataMessage
|
|
|
|
): Proto.IEditMessage {
|
|
|
|
strictAssert(targetMessage.timestamp, 'timestamp missing');
|
|
|
|
|
|
|
|
return {
|
|
|
|
targetSentTimestamp: targetMessage.timestamp,
|
|
|
|
dataMessage: {
|
|
|
|
body: 'hey there',
|
|
|
|
groupV2: undefined,
|
|
|
|
timestamp: Long.fromNumber(Date.now()),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('editing', function needsName() {
|
|
|
|
this.timeout(durations.MINUTE);
|
|
|
|
|
|
|
|
let bootstrap: Bootstrap;
|
|
|
|
let app: App;
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
|
|
bootstrap = new Bootstrap();
|
|
|
|
await bootstrap.init();
|
|
|
|
app = await bootstrap.link();
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(async function after() {
|
|
|
|
if (!bootstrap) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.currentTest?.state !== 'passed') {
|
|
|
|
await bootstrap.saveLogs(app);
|
|
|
|
}
|
|
|
|
|
|
|
|
await app.close();
|
|
|
|
await bootstrap.teardown();
|
|
|
|
});
|
|
|
|
|
2023-03-29 21:58:16 +00:00
|
|
|
it('handles outgoing edited messages phone -> desktop', async () => {
|
2023-03-27 23:48:57 +00:00
|
|
|
const { phone, desktop } = bootstrap;
|
|
|
|
|
|
|
|
const window = await app.getWindow();
|
|
|
|
|
|
|
|
const originalMessage = createMessage();
|
2023-03-29 21:58:16 +00:00
|
|
|
const originalMessageTimestamp = Number(originalMessage.timestamp);
|
2023-03-27 23:48:57 +00:00
|
|
|
|
|
|
|
debug('sending message');
|
|
|
|
{
|
|
|
|
const sendOptions = {
|
2023-03-29 21:58:16 +00:00
|
|
|
timestamp: originalMessageTimestamp,
|
2023-03-27 23:48:57 +00:00
|
|
|
};
|
|
|
|
await phone.sendRaw(
|
|
|
|
desktop,
|
|
|
|
wrap({ dataMessage: originalMessage }),
|
|
|
|
sendOptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug('opening conversation');
|
|
|
|
const leftPane = window.locator('.left-pane-wrapper');
|
|
|
|
await leftPane
|
|
|
|
.locator('.module-conversation-list__item--contact-or-conversation')
|
|
|
|
.first()
|
|
|
|
.click();
|
|
|
|
await window.locator('.module-conversation-hero').waitFor();
|
|
|
|
|
|
|
|
debug('checking for message');
|
|
|
|
await window.locator('.module-message__text >> "hey yhere"').waitFor();
|
|
|
|
|
2023-03-29 21:58:16 +00:00
|
|
|
debug('waiting for receipts for original message');
|
|
|
|
const receipts = await app.waitForReceipts();
|
|
|
|
assert.strictEqual(receipts.type, ReceiptType.Read);
|
|
|
|
assert.strictEqual(receipts.timestamps.length, 1);
|
|
|
|
assert.strictEqual(receipts.timestamps[0], originalMessageTimestamp);
|
|
|
|
|
2023-03-27 23:48:57 +00:00
|
|
|
debug('sending edited message');
|
2023-03-29 21:58:16 +00:00
|
|
|
const editedMessage = createEditedMessage(originalMessage);
|
|
|
|
const editedMessageTimestamp = Number(editedMessage.dataMessage?.timestamp);
|
2023-03-27 23:48:57 +00:00
|
|
|
{
|
|
|
|
const sendOptions = {
|
2023-03-29 21:58:16 +00:00
|
|
|
timestamp: editedMessageTimestamp,
|
2023-03-27 23:48:57 +00:00
|
|
|
};
|
|
|
|
await phone.sendRaw(
|
|
|
|
desktop,
|
|
|
|
wrap({ editMessage: editedMessage }),
|
|
|
|
sendOptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug('checking for edited message');
|
|
|
|
await window.locator('.module-message__text >> "hey there"').waitFor();
|
|
|
|
|
|
|
|
const messages = window.locator('.module-message__text');
|
|
|
|
assert.strictEqual(await messages.count(), 1, 'message count');
|
|
|
|
});
|
2023-03-29 21:58:16 +00:00
|
|
|
|
|
|
|
it('handles incoming edited messages contact -> desktop', async () => {
|
|
|
|
const { contacts, desktop } = bootstrap;
|
|
|
|
|
|
|
|
const window = await app.getWindow();
|
|
|
|
|
|
|
|
const [friend] = contacts;
|
|
|
|
|
|
|
|
const originalMessage = createMessage();
|
|
|
|
const originalMessageTimestamp = Number(originalMessage.timestamp);
|
|
|
|
|
|
|
|
debug('incoming message');
|
|
|
|
{
|
|
|
|
const sendOptions = {
|
|
|
|
timestamp: originalMessageTimestamp,
|
|
|
|
};
|
|
|
|
await friend.sendRaw(
|
|
|
|
desktop,
|
|
|
|
wrap({ dataMessage: originalMessage }),
|
|
|
|
sendOptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug('opening conversation');
|
|
|
|
const leftPane = window.locator('.left-pane-wrapper');
|
|
|
|
await leftPane
|
|
|
|
.locator('.module-conversation-list__item--contact-or-conversation')
|
|
|
|
.first()
|
|
|
|
.click();
|
|
|
|
await window.locator('.module-conversation-hero').waitFor();
|
|
|
|
|
|
|
|
debug('checking for message');
|
|
|
|
await window.locator('.module-message__text >> "hey yhere"').waitFor();
|
|
|
|
|
|
|
|
debug('waiting for original receipt');
|
|
|
|
const originalReceipt = await friend.waitForReceipt();
|
|
|
|
{
|
|
|
|
const { receiptMessage } = originalReceipt;
|
|
|
|
strictAssert(receiptMessage.timestamp, 'receipt has a timestamp');
|
|
|
|
assert.strictEqual(receiptMessage.type, Proto.ReceiptMessage.Type.READ);
|
|
|
|
assert.strictEqual(receiptMessage.timestamp.length, 1);
|
|
|
|
assert.strictEqual(
|
|
|
|
Number(receiptMessage.timestamp[0]),
|
|
|
|
originalMessageTimestamp
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug('sending edited message');
|
|
|
|
const editedMessage = createEditedMessage(originalMessage);
|
|
|
|
const editedMessageTimestamp = Number(editedMessage.dataMessage?.timestamp);
|
|
|
|
{
|
|
|
|
const sendOptions = {
|
|
|
|
timestamp: editedMessageTimestamp,
|
|
|
|
};
|
|
|
|
await friend.sendRaw(
|
|
|
|
desktop,
|
|
|
|
wrap({ editMessage: editedMessage }),
|
|
|
|
sendOptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug('checking for edited message');
|
|
|
|
await window.locator('.module-message__text >> "hey there"').waitFor();
|
|
|
|
|
|
|
|
const messages = window.locator('.module-message__text');
|
|
|
|
assert.strictEqual(await messages.count(), 1, 'message count');
|
|
|
|
|
|
|
|
debug('waiting for receipt for edited message');
|
|
|
|
const editedReceipt = await friend.waitForReceipt();
|
|
|
|
{
|
|
|
|
const { receiptMessage } = editedReceipt;
|
|
|
|
strictAssert(receiptMessage.timestamp, 'receipt has a timestamp');
|
|
|
|
assert.strictEqual(receiptMessage.type, Proto.ReceiptMessage.Type.READ);
|
|
|
|
assert.strictEqual(receiptMessage.timestamp.length, 1);
|
|
|
|
assert.strictEqual(
|
|
|
|
Number(receiptMessage.timestamp[0]),
|
|
|
|
editedMessageTimestamp
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
2023-03-27 23:48:57 +00:00
|
|
|
});
|