Use typing helper in mock-tests

This commit is contained in:
trevor-signal 2024-04-03 13:17:39 -04:00 committed by GitHub
parent 257813265c
commit e96a1e4bc3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 83 additions and 89 deletions

View file

@ -22,6 +22,7 @@ import {
import { stats } from '../../util/benchmark/stats';
import { sleep } from '../../util/sleep';
import { MINUTE } from '../../util/durations';
import { typeIntoInput } from '../helpers';
const LAST_MESSAGE = 'start sending messages now';
@ -171,7 +172,7 @@ Bootstrap.benchmark(async (bootstrap: Bootstrap): Promise<void> => {
});
debug('entering message text');
await input.type(`my message ${runId}`);
await typeIntoInput(input, `my message ${runId}`);
await input.press('Enter');
debug('waiting for message on server side');

View file

@ -8,6 +8,7 @@ import { ReceiptType } from '@signalapp/mock-server';
import { Bootstrap, debug, RUN_COUNT, DISCARD_COUNT } from './fixtures';
import { stats } from '../../util/benchmark/stats';
import { typeIntoInput } from '../helpers';
const CONVERSATION_SIZE = 500; // messages
@ -88,7 +89,7 @@ Bootstrap.benchmark(async (bootstrap: Bootstrap): Promise<void> => {
const input = await app.waitForEnabledComposer();
debug('entering message text');
await input.type(`my message ${runId}`);
await typeIntoInput(input, `my message ${runId}`);
await input.press('Enter');
debug('waiting for message on server side');

View file

@ -3,6 +3,7 @@
import { assert } from 'chai';
import type { Locator, Page } from 'playwright';
import { expect } from 'playwright/test';
export function bufferToUuid(buffer: Buffer): string {
const hex = buffer.toString('hex');
@ -16,22 +17,30 @@ export function bufferToUuid(buffer: Buffer): string {
].join('-');
}
export async function type(input: Locator, text: string): Promise<void> {
export async function typeIntoInput(
input: Locator,
text: string
): Promise<void> {
let currentValue = '';
let isInputElement = true;
try {
currentValue = await input.inputValue();
} catch (e) {
isInputElement = false;
// if input is actually not an input (e.g. contenteditable)
currentValue = (await input.textContent()) ?? '';
}
// Type with a reasonably human delay
await input.type(text, { delay: 100 });
await input.type(text, { delay: 30 });
// Wait to ensure that the input (and react state controlling it) has actually
// updated with the right value
await input.locator(`:text("${currentValue}${text}")`).waitFor();
if (isInputElement) {
await expect(input).toHaveValue(`${currentValue}${text}`);
} else {
await input.locator(`:text("${currentValue}${text}")`).waitFor();
}
}
export async function expectItemsWithText(

View file

@ -16,7 +16,7 @@ import { drop } from '../../util/drop';
import { strictAssert } from '../../util/assert';
import { generateAci } from '../../types/ServiceId';
import { IMAGE_GIF } from '../../types/MIME';
import { type } from '../helpers';
import { typeIntoInput } from '../helpers';
import type { MessageAttributesType } from '../../model-types';
import { sleep } from '../../util/sleep';
@ -95,6 +95,21 @@ describe('editing', function (this: Mocha.Suite) {
let bootstrap: Bootstrap;
let app: App;
async function sendEditedMessage(
page: Page,
timestamp: number,
additionalText: string
) {
await page
.getByTestId(`${timestamp}`)
.locator('.module-message__buttons__menu')
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
const input = await app.waitForEnabledComposer();
await typeIntoInput(input, additionalText);
await input.press('Enter');
}
beforeEach(async () => {
bootstrap = new Bootstrap();
await bootstrap.init();
@ -309,7 +324,7 @@ describe('editing', function (this: Mocha.Suite) {
const input = await app.waitForEnabledComposer();
debug('entering original message text');
await input.type('edit message 1');
await typeIntoInput(input, 'edit message 1');
await input.press('Enter');
}
@ -317,23 +332,11 @@ describe('editing', function (this: Mocha.Suite) {
const { dataMessage: originalMessage } = await friend.waitForMessage();
assert.strictEqual(originalMessage.body, 'edit message 1');
const message = window.locator(
`.module-message[data-testid="${originalMessage.timestamp}"]`
await sendEditedMessage(
window,
originalMessage.timestamp?.toNumber() ?? 0,
'.2'
);
await message.waitFor();
debug('opening context menu');
await message.locator('[aria-label="More actions"]').click();
debug('starting message edit');
await window.locator('.module-message__context__edit-message').click();
{
const input = await app.waitForEnabledComposer();
await input.press('Backspace');
await input.type('2');
await input.press('Enter');
}
debug("waiting for friend's edit message");
const { editMessage: firstEdit } = await friend.waitForEditMessage();
@ -341,30 +344,20 @@ describe('editing', function (this: Mocha.Suite) {
firstEdit.targetSentTimestamp?.toNumber(),
originalMessage.timestamp?.toNumber()
);
assert.strictEqual(firstEdit.dataMessage?.body, 'edit message 2');
assert.strictEqual(firstEdit.dataMessage?.body, 'edit message 1.2');
debug('opening context menu again');
const firstEditMessage = window.locator(
`.module-message[data-testid="${firstEdit.dataMessage?.timestamp?.toNumber()}"]`
await sendEditedMessage(
window,
firstEdit.dataMessage?.timestamp?.toNumber() ?? 0,
'.3'
);
await firstEditMessage.locator('[aria-label="More actions"]').click();
debug('starting second message edit');
await window.locator('.module-message__context__edit-message').click();
{
const input = await app.waitForEnabledComposer();
await input.press('Backspace');
await input.type('3');
await input.press('Enter');
}
const { editMessage: secondEdit } = await friend.waitForEditMessage();
assert.strictEqual(
secondEdit.targetSentTimestamp?.toNumber(),
firstEdit.dataMessage?.timestamp?.toNumber()
);
assert.strictEqual(secondEdit.dataMessage?.body, 'edit message 3');
assert.strictEqual(secondEdit.dataMessage?.body, 'edit message 1.2.3');
debug('opening edit history');
const secondEditMessage = window.locator(
@ -380,8 +373,8 @@ describe('editing', function (this: Mocha.Suite) {
assert.strictEqual(await history.count(), 3);
assert.isTrue(await history.locator('"edit message 1"').isVisible());
assert.isTrue(await history.locator('"edit message 2"').isVisible());
assert.isTrue(await history.locator('"edit message 3"').isVisible());
assert.isTrue(await history.locator('"edit message 1.2"').isVisible());
assert.isTrue(await history.locator('"edit message 1.2.3"').isVisible());
});
it('is fine with out of order edit processing', async () => {
@ -517,20 +510,6 @@ describe('editing', function (this: Mocha.Suite) {
return messages[0];
}
async function editMessage(
page: Page,
timestamp: number,
additionalText: string
) {
await page
.getByTestId(`${timestamp}`)
.locator('.module-message__buttons__menu')
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
const input = await app.waitForEnabledComposer();
await type(input, additionalText);
await input.press('Enter');
}
const { contacts, desktop } = bootstrap;
const [friend] = contacts;
@ -566,7 +545,7 @@ describe('editing', function (this: Mocha.Suite) {
const input = await app.waitForEnabledComposer();
debug('sending message desktop -> friend');
await input.type(originalText);
await typeIntoInput(input, originalText);
await input.press('Enter');
}
@ -636,7 +615,7 @@ describe('editing', function (this: Mocha.Suite) {
debug('finding composition input and clicking it v2');
debug('sending edit message v2 desktop -> friend');
await editMessage(page, originalMessageTimestamp, '2');
await sendEditedMessage(page, originalMessageTimestamp, '2');
{
const readReceiptTimestamp = bootstrap.getTimestamp();
@ -688,7 +667,7 @@ describe('editing', function (this: Mocha.Suite) {
// v3 will be read after we receive v4
const editMessageV3Text = '123';
debug('sending edit message v3 desktop -> friend');
await editMessage(
await sendEditedMessage(
page,
editMessageV2.dataMessage?.timestamp?.toNumber() ?? 0,
'3'
@ -709,7 +688,7 @@ describe('editing', function (this: Mocha.Suite) {
// testing send state of the full message
const editMessageV4Text = '1234';
debug('sending edit message v4 desktop -> friend');
await editMessage(
await sendEditedMessage(
page,
editMessageV3.dataMessage?.timestamp?.toNumber() ?? 0,
'4'

View file

@ -14,7 +14,7 @@ import { toUntaggedPni } from '../../types/ServiceId';
import { MY_STORY_ID } from '../../types/Stories';
import { Bootstrap } from '../bootstrap';
import type { App } from '../bootstrap';
import { expectSystemMessages } from '../helpers';
import { expectSystemMessages, typeIntoInput } from '../helpers';
export const debug = createDebug('mock:test:merge');
@ -130,7 +130,7 @@ describe('pnp/merge', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello ACI');
await typeIntoInput(compositionInput, 'Hello ACI');
await compositionInput.press('Enter');
}
@ -157,7 +157,7 @@ describe('pnp/merge', function (this: Mocha.Suite) {
debug('Send message to PNI');
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello PNI');
await typeIntoInput(compositionInput, 'Hello PNI');
await compositionInput.press('Enter');
}
@ -270,7 +270,7 @@ describe('pnp/merge', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello merged');
await typeIntoInput(compositionInput, 'Hello merged');
await compositionInput.press('Enter');
}
@ -380,7 +380,7 @@ describe('pnp/merge', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello merged');
await typeIntoInput(compositionInput, 'Hello merged');
await compositionInput.press('Enter');
}

View file

@ -12,7 +12,7 @@ import { MY_STORY_ID } from '../../types/Stories';
import { toUntaggedPni } from '../../types/ServiceId';
import { Bootstrap } from '../bootstrap';
import type { App } from '../bootstrap';
import { expectSystemMessages } from '../helpers';
import { expectSystemMessages, typeIntoInput } from '../helpers';
export const debug = createDebug('mock:test:merge');
@ -99,7 +99,7 @@ describe('pnp/phone discovery', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello PNI');
await typeIntoInput(compositionInput, 'Hello PNI');
await compositionInput.press('Enter');
}

View file

@ -10,7 +10,7 @@ import * as durations from '../../util/durations';
import { generatePni, toUntaggedPni } from '../../types/ServiceId';
import { Bootstrap } from '../bootstrap';
import type { App } from '../bootstrap';
import { expectSystemMessages } from '../helpers';
import { expectSystemMessages, typeIntoInput } from '../helpers';
export const debug = createDebug('mock:test:pni-change');
@ -105,7 +105,7 @@ describe('pnp/PNI Change', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('message to contactA');
await typeIntoInput(compositionInput, 'message to contactA');
await compositionInput.press('Enter');
}
@ -204,7 +204,7 @@ describe('pnp/PNI Change', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('message to contactA');
await typeIntoInput(compositionInput, 'message to contactA');
await compositionInput.press('Enter');
}
@ -306,7 +306,7 @@ describe('pnp/PNI Change', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('message to contactA');
await typeIntoInput(compositionInput, 'message to contactA');
await compositionInput.press('Enter');
}
@ -362,7 +362,7 @@ describe('pnp/PNI Change', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('message to contactB');
await typeIntoInput(compositionInput, 'message to contactB');
await compositionInput.press('Enter');
// We get a safety number change warning, because we get a different identity key!
@ -437,7 +437,7 @@ describe('pnp/PNI Change', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('message to contactA');
await typeIntoInput(compositionInput, 'message to contactA');
await compositionInput.press('Enter');
}
@ -523,7 +523,7 @@ describe('pnp/PNI Change', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('second message to contactA');
await typeIntoInput(compositionInput, 'second message to contactA');
await compositionInput.press('Enter');
}

View file

@ -23,7 +23,7 @@ import {
RECEIPT_BATCHER_WAIT_MS,
} from '../../types/Receipt';
import { sleep } from '../../util/sleep';
import { expectSystemMessages } from '../helpers';
import { expectSystemMessages, typeIntoInput } from '../helpers';
export const debug = createDebug('mock:test:pni-signature');
@ -149,7 +149,7 @@ describe('pnp/PNI Signature', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('first');
await typeIntoInput(compositionInput, 'first');
await compositionInput.press('Enter');
}
debug('Wait for the first message with pni signature');
@ -177,7 +177,7 @@ describe('pnp/PNI Signature', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('second');
await typeIntoInput(compositionInput, 'second');
await compositionInput.press('Enter');
}
debug('Wait for the second message with pni signature');
@ -211,7 +211,7 @@ describe('pnp/PNI Signature', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('third');
await typeIntoInput(compositionInput, 'third');
await compositionInput.press('Enter');
}
debug('Wait for the third message without pni signature');
@ -376,7 +376,7 @@ describe('pnp/PNI Signature', function (this: Mocha.Suite) {
const compositionInput = await app.waitForEnabledComposer();
debug('Enter an ACI message text');
await compositionInput.type('Hello ACI');
await typeIntoInput(compositionInput, 'Hello ACI');
await compositionInput.press('Enter');
}

View file

@ -12,7 +12,7 @@ import { uuidToBytes } from '../../util/uuidToBytes';
import { MY_STORY_ID } from '../../types/Stories';
import { Bootstrap } from '../bootstrap';
import type { App } from '../bootstrap';
import { bufferToUuid } from '../helpers';
import { bufferToUuid, typeIntoInput } from '../helpers';
import { contactByEncryptedUsernameRoute } from '../../util/signalRoutes';
export const debug = createDebug('mock:test:username');
@ -99,7 +99,7 @@ describe('pnp/username', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello username');
await typeIntoInput(compositionInput, 'Hello username');
await compositionInput.press('Enter');
}
@ -191,7 +191,7 @@ describe('pnp/username', function (this: Mocha.Suite) {
debug('entering new username');
const usernameField = profileEditor.locator('.Input__input');
await usernameField.type(NICKNAME);
await typeIntoInput(usernameField, NICKNAME);
debug('waiting for generated discriminator');
const discriminator = profileEditor.locator(
@ -308,16 +308,18 @@ describe('pnp/username', function (this: Mocha.Suite) {
await window.getByRole('button', { name: 'New chat' }).click();
const searchInput = window.locator('.module-SearchInput__container input');
await searchInput.type(CARL_USERNAME);
await typeIntoInput(searchInput, CARL_USERNAME);
debug('starting lookup');
await window.locator(`div.ListTile >> "${CARL_USERNAME}"`).click();
await window
.locator(`div.ListTile >> "${CARL_USERNAME}"`)
.click({ timeout: 2000 });
debug('sending a message');
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello Carl');
await typeIntoInput(compositionInput, 'Hello Carl');
await compositionInput.press('Enter');
const { body, source } = await carl.waitForMessage();
@ -374,7 +376,7 @@ describe('pnp/username', function (this: Mocha.Suite) {
{
const compositionInput = await app.waitForEnabledComposer();
await compositionInput.type('Hello Carl');
await typeIntoInput(compositionInput, 'Hello Carl');
await compositionInput.press('Enter');
const { body, source } = await carl.waitForMessage();

View file

@ -10,6 +10,7 @@ import { Bootstrap } from '../bootstrap';
import type { App } from '../bootstrap';
import { ReceiptType } from '../../types/Receipt';
import { toUntaggedPni } from '../../types/ServiceId';
import { typeIntoInput } from '../helpers';
export const debug = createDebug('mock:test:challenge:receipts');
@ -121,7 +122,7 @@ describe('challenge/receipts', function (this: Mocha.Suite) {
debug('Sending a message back to user - will trigger captcha!');
{
const input = await app.waitForEnabledComposer();
await input.type('Hi, good to hear from you!');
await typeIntoInput(input, 'Hi, good to hear from you!');
await input.press('Enter');
}
@ -201,7 +202,7 @@ describe('challenge/receipts', function (this: Mocha.Suite) {
debug('Sending a message back to ContactB - will trigger captcha!');
{
const input = await app.waitForEnabledComposer();
await input.type('Hi, good to hear from you!');
await typeIntoInput(input, 'Hi, good to hear from you!');
await input.press('Enter');
}

View file

@ -6,6 +6,7 @@ import { assert } from 'chai';
import * as durations from '../../util/durations';
import type { App, Bootstrap } from './fixtures';
import { initStorage, debug } from './fixtures';
import { typeIntoInput } from '../helpers';
describe('storage service', function (this: Mocha.Suite) {
this.timeout(durations.MINUTE);
@ -121,7 +122,7 @@ describe('storage service', function (this: Mocha.Suite) {
);
const input = composeArea.locator('[data-testid=CompositionInput]');
await input.type('hello stranger!');
await typeIntoInput(input, 'hello stranger!');
await input.press('Enter');
{