You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							241 lines
						
					
					
						
							7.6 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							241 lines
						
					
					
						
							7.6 KiB
						
					
					
				| import { expect, Page } from "@playwright/test"; | |
| 
 | |
| // Get test user data 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 function getTestUserData(id?: string): { | |
|   seedPhrase: string; | |
|   userName: string; | |
|   did: string; | |
| } { | |
|   switch (id) { | |
|     case "01": | |
|       return { | |
|         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", | |
|       }; | |
|     default: // to user 00 | |
|       return { | |
|         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", | |
|       }; | |
|   } | |
| } | |
| 
 | |
| export async function importUserFromAccount(page: Page, id?: string): Promise<string> { | |
|   // Navigate to AccountViewView to use the Identity Switcher | |
|   await page.goto("./account"); | |
| 
 | |
|   // Click "Show Advanced Settings" to reveal the identity switcher | |
|   await page.getByTestId("advancedSettings").click(); | |
| 
 | |
|   // Use the identity switcher to add User Zero | |
|   await page.locator("#switch-identity-link").click(); | |
|   await page.locator("#start-link").click(); | |
| 
 | |
|   // Select "You have a seed" option | |
|   await page.getByText("You have a seed").click(); | |
| 
 | |
|   // Get User Zero's seed phrase using the new method | |
|   const userZeroData = getTestUserData(id); | |
| 
 | |
|   // Enter User Zero's seed phrase | |
|   await page.getByPlaceholder("Seed Phrase").fill(userZeroData.seedPhrase); | |
| 
 | |
|   await page.getByRole("button", { name: "Import" }).click(); | |
| 
 | |
|   return userZeroData.did; | |
| } | |
| 
 | |
| // Import the seed and switch to the user based on the ID. | |
| export async function importUser(page: Page, id?: string): Promise<string> { | |
|   const userData = getTestUserData(id); | |
|   const { seedPhrase, userName, did } = userData; | |
| 
 | |
|   // 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.locator("#sectionUsageLimits").getByText("Checking") | |
|   ).toBeHidden(); | |
|   return did; | |
| } | |
| 
 | |
| export async function importUserAndCloseOnboarding( | |
|   page: Page, | |
|   id?: string | |
| ): Promise<string> { | |
|   const did = await importUser(page, id); | |
|   await page.goto("./"); | |
|   await page.getByTestId("closeOnboardingAndFinish").click(); | |
|   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("./account"); | |
|    | |
|   // Wait for the page to load and the advanced settings element to be visible | |
|   await page.waitForLoadState('networkidle'); | |
|   await page.getByTestId("advancedSettings").waitFor({ state: 'visible' }); | |
| 
 | |
|   const switchIdentityLink = page.locator("#switch-identity-link"); | |
| 
 | |
|   if (await switchIdentityLink.isHidden()) { | |
|     await page.getByTestId("advancedSettings").click(); | |
|     await switchIdentityLink.click(); | |
|   } else { | |
|     await switchIdentityLink.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}") + div 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: string[] = []; | |
|   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: number[] = []; | |
| 
 | |
|   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") | |
|   ); | |
| }
 | |
| 
 |