@ -60,15 +60,130 @@ function createContactName(did: string): string {
}
export async function deleteContact ( page : Page , did : string ) : Promise < void > {
console . log ( '[DEBUG] deleteContact: Starting deletion for DID:' , did ) ;
await page . goto ( './contacts' ) ;
console . log ( '[DEBUG] deleteContact: Navigated to contacts page' ) ;
// Wait for the page to load completely
await page . waitForLoadState ( 'networkidle' ) ;
console . log ( '[DEBUG] deleteContact: Page load completed' ) ;
// Check if there are any loading indicators or filters active
const loadingIndicator = page . locator ( '[data-testid*="loading"], .loading, .spinner' ) ;
const loadingCount = await loadingIndicator . count ( ) ;
console . log ( '[DEBUG] deleteContact: Loading indicators found:' , loadingCount ) ;
// Check for any filter or state buttons that might be active
const showGiveNumbers = page . locator ( 'button:has-text("Hide Actions")' ) ;
const showGiveNumbersExists = await showGiveNumbers . count ( ) ;
console . log ( '[DEBUG] deleteContact: "Hide Actions" button exists (showing give numbers):' , showGiveNumbersExists > 0 ) ;
if ( showGiveNumbersExists > 0 ) {
console . log ( '[DEBUG] deleteContact: Clicking "Hide Actions" to show normal view' ) ;
await showGiveNumbers . click ( ) ;
await page . waitForTimeout ( 1000 ) ; // Wait for UI to update
}
const contactName = createContactName ( did ) ;
console . log ( '[DEBUG] deleteContact: Looking for contact with name:' , contactName ) ;
// First, let's see what contacts are actually on the page
const contactItems = await page . locator ( 'li[data-testid="contactListItem"]' ) ;
const contactCount = await contactItems . count ( ) ;
console . log ( '[DEBUG] deleteContact: Found contact items on page:' , contactCount ) ;
// Log all contact names visible on the page
for ( let i = 0 ; i < contactCount ; i ++ ) {
const contactItem = contactItems . nth ( i ) ;
const nameElement = contactItem . locator ( 'h2' ) ;
const nameText = await nameElement . textContent ( ) ;
console . log ( '[DEBUG] deleteContact: Contact' , i , ':' , nameText ) ;
}
// If no contacts found, let's take a screenshot to see what's on the page
if ( contactCount === 0 ) {
console . log ( '[DEBUG] deleteContact: No contacts found, taking screenshot' ) ;
await page . screenshot ( { path : 'debug-no-contacts.png' , fullPage : true } ) ;
console . log ( '[DEBUG] deleteContact: Screenshot saved as debug-no-contacts.png' ) ;
}
// Try to find the contact list item with the expected name
const contactListItem = page . locator ( ` li[data-testid="contactListItem"]:has(h2:has-text(" ${ contactName } ")) ` ) ;
const contactExists = await contactListItem . count ( ) ;
console . log ( '[DEBUG] deleteContact: Contact with name exists:' , contactName , contactExists > 0 ) ;
if ( contactExists === 0 ) {
console . error ( '[DEBUG] deleteContact: Contact not found on page:' , contactName ) ;
throw new Error ( ` Contact " ${ contactName } " not found on contacts page ` ) ;
}
// Now click the info icon - fix the selector to match actual DOM structure
// Try different selectors for the info icon
const infoIconSelectors = [
` li[data-testid="contactListItem"]:has(h2:has-text(" ${ contactName } ")) font-awesome[icon="circle-info"] ` ,
` li[data-testid="contactListItem"]:has(h2:has-text(" ${ contactName } ")) .fa-circle-info ` ,
` li[data-testid="contactListItem"]:has(h2:has-text(" ${ contactName } ")) svg.fa-circle-info ` ,
` li[data-testid="contactListItem"]:has(h2:has-text(" ${ contactName } ")) [class*="fa-circle-info"] `
] ;
let infoIcon : import ( '@playwright/test' ) . Locator | null = null ;
let infoIconExists = 0 ;
for ( const selector of infoIconSelectors ) {
console . log ( '[DEBUG] deleteContact: Trying selector:' , selector ) ;
const testIcon = page . locator ( selector ) ;
const testCount = await testIcon . count ( ) ;
console . log ( '[DEBUG] deleteContact: Selector result count:' , testCount ) ;
if ( testCount > 0 ) {
infoIcon = testIcon ;
infoIconExists = testCount ;
console . log ( '[DEBUG] deleteContact: Found working selector:' , selector ) ;
break ;
}
}
console . log ( '[DEBUG] deleteContact: Info icon exists:' , infoIconExists > 0 ) ;
if ( infoIconExists === 0 || ! infoIcon ) {
console . error ( '[DEBUG] deleteContact: Info icon not found for contact:' , contactName ) ;
throw new Error ( ` Info icon not found for contact " ${ contactName } " ` ) ;
}
// 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 ( ) ;
await infoIcon . click ( ) ;
console . log ( '[DEBUG] deleteContact: Clicked info icon, should be on detail page' ) ;
// Verify we're on the detail page
const detailPageHeading = page . locator ( 'h1:has-text("Identifier Details")' ) ;
await detailPageHeading . waitFor ( { timeout : 10000 } ) ;
console . log ( '[DEBUG] deleteContact: Confirmed on detail page' ) ;
// delete the contact
await page . locator ( 'button > svg.fa-trash-can' ) . click ( ) ;
await page . locator ( 'div[role="alert"] button:has-text("Yes")' ) . click ( ) ;
const deleteButton = page . locator ( 'button > svg.fa-trash-can' ) ;
const deleteButtonExists = await deleteButton . count ( ) ;
console . log ( '[DEBUG] deleteContact: Delete button exists:' , deleteButtonExists > 0 ) ;
if ( deleteButtonExists === 0 ) {
console . error ( '[DEBUG] deleteContact: Delete button not found' ) ;
throw new Error ( 'Delete button not found on detail page' ) ;
}
await deleteButton . click ( ) ;
console . log ( '[DEBUG] deleteContact: Clicked delete button' ) ;
// Confirm deletion
const confirmButton = page . locator ( 'div[role="alert"] button:has-text("Yes")' ) ;
await confirmButton . waitFor ( { timeout : 10000 } ) ;
console . log ( '[DEBUG] deleteContact: Confirmation dialog appeared' ) ;
await confirmButton . click ( ) ;
console . log ( '[DEBUG] deleteContact: Clicked confirmation button' ) ;
// for some reason, .isHidden() (without expect) doesn't work
await expect ( page . locator ( 'div[role="alert"] button:has-text("Yes")' ) ) . toBeHidden ( ) ;
console . log ( '[DEBUG] deleteContact: Confirmation dialog dismissed, deletion complete' ) ;
}
export async function generateNewEthrUser ( page : Page ) : Promise < string > {
@ -85,19 +200,36 @@ export async function generateNewEthrUser(page: Page): Promise<string> {
// 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 > {
console . log ( '[DEBUG] generateAndRegisterEthrUser: Starting user generation' ) ;
const newDid = await generateNewEthrUser ( page ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Generated new DID:' , newDid ) ;
await importUser ( page , '000' ) ; // switch to user 000
console . log ( '[DEBUG] generateAndRegisterEthrUser: Switched to user 000' ) ;
await page . goto ( './contacts' ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Navigated to contacts page' ) ;
const contactName = createContactName ( newDid ) ;
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ newDid } , ${ contactName } ` ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Created contact name:' , contactName ) ;
const contactInput = ` ${ newDid } , ${ contactName } ` ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Filling contact input with:' , contactInput ) ;
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( contactInput ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Clicked add contact button' ) ;
// register them
await page . locator ( 'div[role="alert"] button:has-text("Yes")' ) . click ( ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Clicked registration confirmation' ) ;
// 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 ( ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Registration dialog dismissed' ) ;
await expect ( page . locator ( 'li' , { hasText : contactName } ) ) . toBeVisible ( ) ;
console . log ( '[DEBUG] generateAndRegisterEthrUser: Contact is now visible in list:' , contactName ) ;
return newDid ;
}
@ -109,7 +241,7 @@ export async function generateRandomString(length: number): Promise<string> {
// Function to create an array of unique strings
export async function createUniqueStringsArray ( count : number ) : Promise < string [ ] > {
const stringsArray = [ ] ;
const stringsArray : string [ ] = [ ] ;
const stringLength = 16 ;
for ( let i = 0 ; i < count ; i ++ ) {
@ -122,7 +254,7 @@ export async function createUniqueStringsArray(count: number): Promise<string[]>
// Function to create an array of two-digit non-zero numbers
export async function createRandomNumbersArray ( count : number ) : Promise < number [ ] > {
const numbersArray = [ ] ;
const numbersArray : number [ ] = [ ] ;
for ( let i = 0 ; i < count ; i ++ ) {
let randomNumber = Math . floor ( Math . random ( ) * 99 ) + 1 ;