@ -346,6 +346,35 @@ function generateUniqueTestContacts(): Record<string, TestContact> {
} ;
} ;
}
}
/ * *
* Helper function to safely close alerts that might be blocked by dialogs
*
* This function attempts to close an alert , but handles cases where
* the alert close button might be blocked by modal dialogs .
*
* @param page - Playwright page object
* @param alertSelector - Selector for the alert to close
* /
async function safeCloseAlert ( page : any , alertSelector : string = 'div[role="alert"] button > svg.fa-xmark' ) {
try {
await page . locator ( alertSelector ) . first ( ) . click ( ) ;
} catch ( error ) {
// If click fails due to blocking dialog, try to close the dialog first
try {
const dialog = page . locator ( 'div[role="dialog"]' ) ;
if ( await dialog . isVisible ( { timeout : 1000 } ) ) {
await dialog . locator ( 'button:has-text("No"), button:has-text("Cancel"), button > svg.fa-xmark' ) . first ( ) . click ( ) ;
await dialog . waitFor ( { state : 'hidden' , timeout : 3000 } ) ;
// Now try to close the alert again
await page . locator ( alertSelector ) . first ( ) . click ( ) ;
}
} catch ( dialogError ) {
// If dialog handling fails, just continue without closing the alert
console . log ( 'Alert close failed due to dialog blocking, continuing anyway' ) ;
}
}
}
/ * *
/ * *
* Invalid test data for error scenario testing
* Invalid test data for error scenario testing
*
*
@ -1738,4 +1767,578 @@ test.describe('Contact Import Functionality', () => {
perfMonitor . end ( 'Contact addition with registration - user cancels prompt' ) ;
perfMonitor . end ( 'Contact addition with registration - user cancels prompt' ) ;
} ) ;
} ) ;
/ * *
* Test contact editing functionality - basic information
*
* This test validates the contact editing workflow for basic contact information .
* The test ensures that :
* - Contact edit view loads correctly
* - Name and notes fields can be edited
* - Changes are saved successfully
* - User is redirected to contact detail view
* /
test ( 'Contact editing - basic information' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - basic information' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . alice . did } , ${ testContacts . alice . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Navigate directly to the contact edit page using the contact DID
await perfMonitor . measureAsync ( 'navigate to contact edit page' , ( ) = >
page . goto ( ` ./contact-edit/ ${ encodeURIComponent ( testContacts . alice . did ) } ` )
) ;
// Verify we're on the edit page
await perfMonitor . measureAsync ( 'verify edit page loaded' , ( ) = >
expect ( page . locator ( 'section[id="ContactEdit"]' ) ) . toBeVisible ( )
) ;
// Edit contact name
const newName = ` ${ testContacts . alice . name } (Edited) ` ;
await perfMonitor . measureAsync ( 'edit contact name' , ( ) = >
page . locator ( 'input[data-testId="contactName"]' ) . fill ( newName )
) ;
// Edit contact notes
const newNotes = 'Test notes for contact editing' ;
await perfMonitor . measureAsync ( 'edit contact notes' , ( ) = >
page . locator ( 'textarea[id="contactNotes"]' ) . fill ( newNotes )
) ;
// Save changes
await perfMonitor . measureAsync ( 'save changes' , ( ) = >
page . locator ( 'button:has-text("Save")' ) . click ( )
) ;
// Verify success message
await perfMonitor . measureAsync ( 'verify success message' , ( ) = >
expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( )
) ;
// Verify we're back on the contact detail page
await perfMonitor . measureAsync ( 'verify returned to detail page' , ( ) = >
expect ( page . locator ( ` h2:has-text(" ${ newName } ") ` ) ) . toBeVisible ( )
) ;
perfMonitor . end ( 'Contact editing - basic information' ) ;
} ) ;
/ * *
* Test contact editing - adding contact methods
*
* This test validates the contact methods functionality in the edit view .
* The test ensures that :
* - New contact methods can be added
* - Method types can be selected from dropdown
* - Method labels and values can be edited
* - Changes are saved successfully
* /
test ( 'Contact editing - adding contact methods' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - adding contact methods' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . bob . did } , ${ testContacts . bob . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Navigate directly to the contact edit page
await perfMonitor . measureAsync ( 'navigate to contact edit page' , ( ) = >
page . goto ( ` ./contact-edit/ ${ encodeURIComponent ( testContacts . bob . did ) } ` )
) ;
// Add a new contact method
await perfMonitor . measureAsync ( 'add contact method' , ( ) = >
page . locator ( 'button:has-text("+")' ) . click ( )
) ;
// Fill in the contact method details
await perfMonitor . measureAsync ( 'fill contact method details' , async ( ) = > {
// Fill label
await page . locator ( 'input[placeholder="Label"]' ) . first ( ) . fill ( 'Mobile' ) ;
// Click dropdown and select CELL type
await page . locator ( 'button:has-text("▼")' ) . first ( ) . click ( ) ;
await page . locator ( 'div:has-text("CELL")' ) . click ( ) ;
// Fill value
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . first ( ) . fill ( '+1-555-123-4567' ) ;
} ) ;
// Add another contact method
await perfMonitor . measureAsync ( 'add second contact method' , ( ) = >
page . locator ( 'button:has-text("+")' ) . click ( )
) ;
// Fill in the second contact method
await perfMonitor . measureAsync ( 'fill second contact method' , async ( ) = > {
// Fill label
await page . locator ( 'input[placeholder="Label"]' ) . nth ( 1 ) . fill ( 'Email' ) ;
// Click dropdown and select EMAIL type
await page . locator ( 'button:has-text("▼")' ) . nth ( 1 ) . click ( ) ;
await page . locator ( 'div:has-text("EMAIL")' ) . click ( ) ;
// Fill value
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . nth ( 1 ) . fill ( 'bob@example.com' ) ;
} ) ;
// Save changes
await perfMonitor . measureAsync ( 'save changes' , ( ) = >
page . locator ( 'button:has-text("Save")' ) . click ( )
) ;
// Verify success message
await perfMonitor . measureAsync ( 'verify success message' , ( ) = >
expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( )
) ;
perfMonitor . end ( 'Contact editing - adding contact methods' ) ;
} ) ;
/ * *
* Test contact editing - removing contact methods
*
* This test validates the contact method removal functionality .
* The test ensures that :
* - Contact methods can be removed
* - Removed methods are not saved
* - UI updates correctly after removal
* /
test ( 'Contact editing - removing contact methods' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - removing contact methods' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . charlie . did } , ${ testContacts . charlie . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Navigate directly to the contact edit page
await perfMonitor . measureAsync ( 'navigate to contact edit page' , ( ) = >
page . goto ( ` ./contact-edit/ ${ encodeURIComponent ( testContacts . charlie . did ) } ` )
) ;
// Add a contact method first
await perfMonitor . measureAsync ( 'add contact method' , ( ) = >
page . locator ( 'button:has-text("+")' ) . click ( )
) ;
// Fill in the contact method
await perfMonitor . measureAsync ( 'fill contact method' , async ( ) = > {
await page . locator ( 'input[placeholder="Label"]' ) . first ( ) . fill ( 'Test Method' ) ;
await page . locator ( 'input[placeholder="Type"]' ) . first ( ) . fill ( 'WHATSAPP' ) ;
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . first ( ) . fill ( 'test-value' ) ;
} ) ;
// Remove the contact method
await perfMonitor . measureAsync ( 'remove contact method' , ( ) = >
page . locator ( 'font-awesome[icon="trash-can"]' ) . first ( ) . click ( )
) ;
// Verify the method was removed from UI
await perfMonitor . measureAsync ( 'verify method removed' , ( ) = >
expect ( page . locator ( 'input[placeholder="Label"]' ) ) . toHaveCount ( 0 )
) ;
// Save changes
await perfMonitor . measureAsync ( 'save changes' , ( ) = >
page . locator ( 'button:has-text("Save")' ) . click ( )
) ;
// Verify success message
await perfMonitor . measureAsync ( 'verify success message' , ( ) = >
expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( )
) ;
perfMonitor . end ( 'Contact editing - removing contact methods' ) ;
} ) ;
/ * *
* Test contact editing - canceling changes
*
* This test validates the cancel functionality in the contact edit view .
* The test ensures that :
* - Changes can be canceled
* - User returns to previous view
* - No changes are saved when canceled
* /
test ( 'Contact editing - canceling changes' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - canceling changes' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . david . did } , ${ testContacts . david . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Navigate directly to the contact edit page
await perfMonitor . measureAsync ( 'navigate to contact edit page' , ( ) = >
page . goto ( ` ./contact-edit/ ${ encodeURIComponent ( testContacts . david . did ) } ` )
) ;
// Make some changes
await perfMonitor . measureAsync ( 'make changes' , async ( ) = > {
await page . locator ( 'input[data-testId="contactName"]' ) . fill ( 'This should not be saved' ) ;
await page . locator ( 'textarea[id="contactNotes"]' ) . fill ( 'These notes should not be saved' ) ;
} ) ;
// Cancel changes
await perfMonitor . measureAsync ( 'cancel changes' , ( ) = >
page . locator ( 'button:has-text("Cancel")' ) . click ( )
) ;
// Verify we're back on the contact detail page
await perfMonitor . measureAsync ( 'verify returned to detail page' , ( ) = >
expect ( page . locator ( ` h2:has-text(" ${ testContacts . david . name } ") ` ) ) . toBeVisible ( )
) ;
// Verify the original name is still there (changes weren't saved)
await perfMonitor . measureAsync ( 'verify changes not saved' , ( ) = >
expect ( page . locator ( ` h2:has-text("This should not be saved") ` ) ) . not . toBeVisible ( )
) ;
perfMonitor . end ( 'Contact editing - canceling changes' ) ;
} ) ;
/ * *
* Test contact editing - method type dropdown functionality
*
* This test validates the dropdown functionality for contact method types .
* The test ensures that :
* - Dropdown opens and closes correctly
* - All method types are available ( CELL , EMAIL , WHATSAPP )
* - Type selection works properly
* - Only one dropdown can be open at a time
* /
test ( 'Contact editing - method type dropdown functionality' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - method type dropdown functionality' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . eve . did } , ${ testContacts . eve . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Navigate directly to the contact edit page
await perfMonitor . measureAsync ( 'navigate to contact edit page' , ( ) = >
page . goto ( ` ./contact-edit/ ${ encodeURIComponent ( testContacts . eve . did ) } ` )
) ;
// Add a contact method
await perfMonitor . measureAsync ( 'add contact method' , ( ) = >
page . locator ( 'button:has-text("+")' ) . click ( )
) ;
// Test dropdown functionality
await perfMonitor . measureAsync ( 'test dropdown functionality' , async ( ) = > {
// Click dropdown to open it
await page . locator ( 'button:has-text("▼")' ) . first ( ) . click ( ) ;
// Verify dropdown is open
await expect ( page . locator ( 'div:has-text("CELL")' ) ) . toBeVisible ( ) ;
await expect ( page . locator ( 'div:has-text("EMAIL")' ) ) . toBeVisible ( ) ;
await expect ( page . locator ( 'div:has-text("WHATSAPP")' ) ) . toBeVisible ( ) ;
// Select EMAIL type
await page . locator ( 'div:has-text("EMAIL")' ) . click ( ) ;
// Verify dropdown is closed
await expect ( page . locator ( 'div:has-text("CELL")' ) ) . not . toBeVisible ( ) ;
// Verify the type field shows EMAIL
await expect ( page . locator ( 'input[placeholder="Type"]' ) . first ( ) ) . toHaveValue ( 'EMAIL' ) ;
} ) ;
// Test that only one dropdown can be open at a time
await perfMonitor . measureAsync ( 'test single dropdown open' , async ( ) = > {
// Add another contact method
await page . locator ( 'button:has-text("+")' ) . click ( ) ;
// Open first dropdown
await page . locator ( 'button:has-text("▼")' ) . first ( ) . click ( ) ;
await expect ( page . locator ( 'div:has-text("CELL")' ) ) . toBeVisible ( ) ;
// Open second dropdown (should close first)
await page . locator ( 'button:has-text("▼")' ) . nth ( 1 ) . click ( ) ;
await expect ( page . locator ( 'div:has-text("CELL")' ) ) . not . toBeVisible ( ) ;
} ) ;
perfMonitor . end ( 'Contact editing - method type dropdown functionality' ) ;
} ) ;
/ * *
* Test contact editing - error handling for invalid contact
*
* This test validates error handling when trying to edit a non - existent contact .
* The test ensures that :
* - Appropriate error message is displayed
* - User is redirected to contacts list
* - System remains stable
* /
test ( 'Contact editing - error handling for invalid contact' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - error handling for invalid contact' ) ;
// Try to navigate to edit page for non-existent contact
await perfMonitor . measureAsync ( 'navigate to invalid contact edit' , ( ) = >
page . goto ( './contact-edit/did:ethr:0xInvalidContactDID' )
) ;
// Verify error handling
await perfMonitor . measureAsync ( 'verify error handling' , async ( ) = > {
try {
// Should redirect to contacts page
await expect ( page . locator ( 'h1:has-text("Contacts")' ) ) . toBeVisible ( { timeout : 5000 } ) ;
} catch ( error ) {
// Alternative: check for error message
await expect ( page . locator ( 'div[role="alert"]' ) ) . toBeVisible ( { timeout : 5000 } ) ;
}
} ) ;
perfMonitor . end ( 'Contact editing - error handling for invalid contact' ) ;
} ) ;
/ * *
* Test contact editing - navigation from different entry points
*
* This test validates that contact editing can be accessed from different
* entry points in the application . The test ensures that :
* - Edit button works from contact detail view
* - Back navigation works correctly
* - Edit view loads properly from different contexts
* /
test ( 'Contact editing - navigation from different entry points' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - navigation from different entry points' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . alice . did } , ${ testContacts . alice . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Test navigation from contact detail view
await perfMonitor . measureAsync ( 'navigate from contact detail' , async ( ) = > {
await page . locator ( ` li[data-testid="contactListItem"] h2:has-text(" ${ testContacts . alice . name } ") ` ) . first ( ) . click ( ) ;
// Wait for the contact detail page to load
await expect ( page . locator ( 'h1:has-text("Identifier Details")' ) ) . toBeVisible ( ) ;
await page . locator ( 'router-link font-awesome[icon="pen"]' ) . click ( ) ;
await expect ( page . locator ( 'section[id="ContactEdit"]' ) ) . toBeVisible ( ) ;
} ) ;
// Test back navigation
await perfMonitor . measureAsync ( 'test back navigation' , async ( ) = > {
await page . locator ( 'button:has-text("Back")' ) . click ( ) ;
await expect ( page . locator ( ` h2:has-text(" ${ testContacts . alice . name } ") ` ) ) . toBeVisible ( ) ;
} ) ;
// Test direct URL navigation
await perfMonitor . measureAsync ( 'test direct URL navigation' , async ( ) = > {
const contactDid = encodeURIComponent ( testContacts . alice . did ) ;
await page . goto ( ` ./contact-edit/ ${ contactDid } ` ) ;
await expect ( page . locator ( 'section[id="ContactEdit"]' ) ) . toBeVisible ( ) ;
} ) ;
perfMonitor . end ( 'Contact editing - navigation from different entry points' ) ;
} ) ;
/ * *
* Test contact editing - complex contact methods scenario
*
* This test validates a complex scenario with multiple contact methods
* of different types . The test ensures that :
* - Multiple contact methods can be managed
* - Different types work correctly
* - Complex scenarios are handled properly
* /
test ( 'Contact editing - complex contact methods scenario' , async ( { page , browserName } ) = > {
perfMonitor . start ( 'Contact editing - complex contact methods scenario' ) ;
const testContacts = generateUniqueTestContacts ( ) ;
// First, add a contact to edit
await perfMonitor . measureAsync ( 'navigate to contacts' , ( ) = > page . goto ( './contacts' ) ) ;
await perfMonitor . measureAsync ( 'add test contact' , async ( ) = > {
await page . getByPlaceholder ( 'URL or DID, Name, Public Key' ) . fill ( ` ${ testContacts . bob . did } , ${ testContacts . bob . name } ` ) ;
await page . locator ( 'button > svg.fa-plus' ) . click ( ) ;
// Handle registration prompt if it appears
try {
await expect ( page . locator ( 'div[role="dialog"] h3:has-text("Register")' ) ) . toBeVisible ( { timeout : 3000 } ) ;
// Registration prompt appeared - choose not to register
await page . locator ( 'div[role="dialog"] button:has-text("No")' ) . click ( ) ;
await page . locator ( 'div[role="dialog"]' ) . waitFor ( { state : 'hidden' , timeout : 5000 } ) ;
} catch ( error ) {
// Registration prompt didn't appear - this is expected for unregistered users
perfMonitor . checkpoint ( 'registration prompt did not appear' ) ;
}
await expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( ) ;
await page . locator ( 'div[role="alert"] button > svg.fa-xmark' ) . first ( ) . click ( ) ;
} ) ;
// Navigate directly to the contact edit page
await perfMonitor . measureAsync ( 'navigate to contact edit page' , ( ) = >
page . goto ( ` ./contact-edit/ ${ encodeURIComponent ( testContacts . bob . did ) } ` )
) ;
// Add multiple contact methods of different types
await perfMonitor . measureAsync ( 'add multiple contact methods' , async ( ) = > {
// Add CELL method
await page . locator ( 'button:has-text("+")' ) . click ( ) ;
await page . locator ( 'input[placeholder="Label"]' ) . first ( ) . fill ( 'Mobile' ) ;
await page . locator ( 'button:has-text("▼")' ) . first ( ) . click ( ) ;
await page . locator ( 'div:has-text("CELL")' ) . click ( ) ;
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . first ( ) . fill ( '+1-555-123-4567' ) ;
// Add EMAIL method
await page . locator ( 'button:has-text("+")' ) . click ( ) ;
await page . locator ( 'input[placeholder="Label"]' ) . nth ( 1 ) . fill ( 'Work Email' ) ;
await page . locator ( 'button:has-text("▼")' ) . nth ( 1 ) . click ( ) ;
await page . locator ( 'div:has-text("EMAIL")' ) . click ( ) ;
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . nth ( 1 ) . fill ( 'bob.work@example.com' ) ;
// Add WHATSAPP method
await page . locator ( 'button:has-text("+")' ) . click ( ) ;
await page . locator ( 'input[placeholder="Label"]' ) . nth ( 2 ) . fill ( 'WhatsApp' ) ;
await page . locator ( 'button:has-text("▼")' ) . nth ( 2 ) . click ( ) ;
await page . locator ( 'div:has-text("WHATSAPP")' ) . click ( ) ;
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . nth ( 2 ) . fill ( '+1-555-987-6543' ) ;
} ) ;
// Remove one method
await perfMonitor . measureAsync ( 'remove one method' , ( ) = >
page . locator ( 'font-awesome[icon="trash-can"]' ) . nth ( 1 ) . click ( )
) ;
// Edit remaining methods
await perfMonitor . measureAsync ( 'edit remaining methods' , async ( ) = > {
// Edit the first method
await page . locator ( 'input[placeholder="Label"]' ) . first ( ) . fill ( 'Updated Mobile' ) ;
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . first ( ) . fill ( '+1-555-999-8888' ) ;
// Edit the second method
await page . locator ( 'input[placeholder="Label"]' ) . nth ( 1 ) . fill ( 'Updated WhatsApp' ) ;
await page . locator ( 'input[placeholder="Number, email, etc."]' ) . nth ( 1 ) . fill ( '+1-555-777-6666' ) ;
} ) ;
// Save changes
await perfMonitor . measureAsync ( 'save changes' , ( ) = >
page . locator ( 'button:has-text("Save")' ) . click ( )
) ;
// Verify success message
await perfMonitor . measureAsync ( 'verify success message' , ( ) = >
expect ( page . locator ( 'div[role="alert"] span:has-text("Success")' ) ) . toBeVisible ( )
) ;
perfMonitor . end ( 'Contact editing - complex contact methods scenario' ) ;
} ) ;
} ) ;
} ) ;