forked from jsnbuchanan/crowd-funder-for-time-pwa
- Add better error handling and logging for gift recording flow - Add explicit navigation to contacts page before finding gift button - Add info icon click handling when needed - Add more comprehensive button detection with multiple selectors - Add debug logging for page state and navigation - Add screenshot capture on failures - Add retry logic with proper state verification - Fix linter errors in playwright config The changes help diagnose and handle various UI states that can occur during gift recording, making the tests more reliable especially on Linux.
161 lines
6.0 KiB
TypeScript
161 lines
6.0 KiB
TypeScript
import { expect, Page } from '@playwright/test';
|
|
|
|
// Import the seed and switch to the user based on the ID.
|
|
// '01' -> user 111
|
|
// otherwise -> user 000
|
|
// (... which is a weird convention but I haven't taken the time to change it)
|
|
export async function importUser(page: Page, id?: string): Promise<string> {
|
|
let seedPhrase, userName, did;
|
|
|
|
// Set seed phrase and DID based on user ID
|
|
switch(id) {
|
|
case '01':
|
|
seedPhrase = 'island fever beef wine urban aim vacant quit afford total poem flame service calm better adult neither color gaze forum month sister imitate excite';
|
|
userName = 'User One';
|
|
did = 'did:ethr:0x111d15564f824D56C7a07b913aA7aDd03382aA39';
|
|
break;
|
|
default: // to user 00
|
|
seedPhrase = 'rigid shrug mobile smart veteran half all pond toilet brave review universe ship congress found yard skate elite apology jar uniform subway slender luggage';
|
|
userName = 'User Zero';
|
|
did = 'did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F';
|
|
}
|
|
|
|
// Import ID
|
|
await page.goto('./start');
|
|
await page.getByText('You have a seed').click();
|
|
await page.getByPlaceholder('Seed Phrase').fill(seedPhrase);
|
|
await page.getByRole('button', { name: 'Import' }).click();
|
|
|
|
// Check DID
|
|
await expect(page.getByRole('code')).toContainText(did);
|
|
// ... and ensure the app retrieves the registration status
|
|
await expect(page.getByText('Your claims counter resets')).toBeVisible();
|
|
return did;
|
|
}
|
|
|
|
// This is to switch to someone already in the identity table. It doesn't include registration.
|
|
export async function switchToUser(page: Page, did: string): Promise<void> {
|
|
// This is the direct approach but users have to tap on things so we'll do that instead.
|
|
//await page.goto('./identity-switcher');
|
|
|
|
await page.goto('./account');
|
|
await page.getByRole('heading', { name: 'Advanced' }).click();
|
|
await page.getByRole('link', { name: 'Switch Identifier' }).click();
|
|
const didElem = await page.locator(`code:has-text("${did}")`);
|
|
await didElem.isVisible();
|
|
await didElem.click();
|
|
// wait for the switch to happen and the account page to fully load
|
|
await page.getByTestId('didWrapper').locator('code:has-text("did:")');
|
|
}
|
|
|
|
function createContactName(did: string): string {
|
|
return "User " + did.slice(11, 14);
|
|
}
|
|
|
|
export async function deleteContact(page: Page, did: string): Promise<void> {
|
|
await page.goto('./contacts');
|
|
const contactName = createContactName(did);
|
|
// go to the detail page for this contact
|
|
await page.locator(`li[data-testid="contactListItem"] h2:has-text("${contactName}") + span svg.fa-circle-info`).click();
|
|
// delete the contact
|
|
await page.locator('button > svg.fa-trash-can').click();
|
|
await page.locator('div[role="alert"] button:has-text("Yes")').click();
|
|
// for some reason, .isHidden() (without expect) doesn't work
|
|
await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
|
|
}
|
|
|
|
export async function generateNewEthrUser(page: Page): Promise<string> {
|
|
await page.goto('./start');
|
|
await page.getByTestId('newSeed').click();
|
|
await expect(page.locator('span:has-text("Created")')).toBeVisible();
|
|
|
|
await page.goto('./account');
|
|
const didElem = await page.getByTestId('didWrapper').locator('code:has-text("did:")');
|
|
const newDid = await didElem.innerText();
|
|
return newDid;
|
|
}
|
|
|
|
// Generate a new random user and register them.
|
|
// Note that this makes 000 the active user. Use switchToUser to switch to this DID.
|
|
export async function generateAndRegisterEthrUser(page: Page): Promise<string> {
|
|
const newDid = await generateNewEthrUser(page);
|
|
|
|
await importUser(page, '000'); // switch to user 000
|
|
|
|
await page.goto('./contacts');
|
|
const contactName = createContactName(newDid);
|
|
await page.getByPlaceholder('URL or DID, Name, Public Key').fill(`${newDid}, ${contactName}`);
|
|
await page.locator('button > svg.fa-plus').click();
|
|
// register them
|
|
await page.locator('div[role="alert"] button:has-text("Yes")').click();
|
|
// wait for it to disappear because the next steps may depend on alerts being gone
|
|
await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
|
|
await expect(page.locator('li', { hasText: contactName })).toBeVisible();
|
|
|
|
return newDid;
|
|
}
|
|
|
|
// Function to generate a random string of specified length
|
|
export async function generateRandomString(length: number): Promise<string> {
|
|
return Math.random().toString(36).substring(2, 2 + length);
|
|
}
|
|
|
|
// Function to create an array of unique strings
|
|
export async function createUniqueStringsArray(count: number): Promise<string[]> {
|
|
const stringsArray = [];
|
|
const stringLength = 16;
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
let randomString = await generateRandomString(stringLength);
|
|
stringsArray.push(randomString);
|
|
}
|
|
|
|
return stringsArray;
|
|
}
|
|
|
|
// Function to create an array of two-digit non-zero numbers
|
|
export async function createRandomNumbersArray(count: number): Promise<number[]> {
|
|
const numbersArray = [];
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
let randomNumber = Math.floor(Math.random() * 99) + 1;
|
|
numbersArray.push(randomNumber);
|
|
}
|
|
|
|
return numbersArray;
|
|
}
|
|
|
|
export function isLinuxEnvironment() {
|
|
return process.platform === 'linux';
|
|
}
|
|
|
|
export function getOSSpecificTimeout(): number {
|
|
// Increase base timeout for Linux
|
|
const isLinux = process.platform === 'linux';
|
|
return isLinux ? 180000 : 60000; // 3 minutes for Linux, 1 minute for others
|
|
}
|
|
|
|
export function getOSSpecificConfig() {
|
|
if (isLinuxEnvironment()) {
|
|
return {
|
|
retries: 2,
|
|
timeout: 90000, // Increased global timeout
|
|
expect: {
|
|
timeout: 30000 // Increased expect timeout
|
|
},
|
|
// Add video recording for failed tests on Linux
|
|
use: {
|
|
video: 'retain-on-failure',
|
|
trace: 'retain-on-failure'
|
|
}
|
|
};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
// Add helper for test grouping
|
|
export function isResourceIntensiveTest(testPath: string): boolean {
|
|
return testPath.includes('35-record-gift-from-image-share') ||
|
|
testPath.includes('40-add-contact');
|
|
}
|