// Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { assert } from 'chai'; import type { Locator, Page } from 'playwright'; export function bufferToUuid(buffer: Buffer): string { const hex = buffer.toString('hex'); return [ hex.substring(0, 8), hex.substring(8, 12), hex.substring(12, 16), hex.substring(16, 20), hex.substring(20), ].join('-'); } export async function type(input: Locator, text: string): Promise { let currentValue = ''; try { currentValue = await input.inputValue(); } catch (e) { // 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 }); // 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(); } export async function expectItemsWithText( items: Locator, expected: ReadonlyArray ): Promise { // Wait for each message to appear in case they're not all there yet for (const [index, message] of expected.entries()) { const nth = items.nth(index); // eslint-disable-next-line no-await-in-loop await nth.waitFor(); // eslint-disable-next-line no-await-in-loop const text = await nth.innerText(); const log = `Expect item at index ${index} to match`; if (typeof message === 'string') { assert.strictEqual(text, message, log); } else { assert.match(text, message, log); } } const innerTexts = await items.allInnerTexts(); assert.deepEqual( innerTexts.length, expected.length, `Expect correct number of items\nActual:\n${innerTexts .map(text => ` - "${text}"\n`) .join('')}\nExpected:\n${expected .map(text => ` - ${text.toString()}\n`) .join('')}` ); } export async function expectSystemMessages( context: Page | Locator, expected: ReadonlyArray ): Promise { await expectItemsWithText( context.locator('.SystemMessage__contents'), expected ); }