diff --git a/test-playwright/00-noid-tests.spec.ts b/test-playwright/00-noid-tests.spec.ts index e84949df..d3c848d4 100644 --- a/test-playwright/00-noid-tests.spec.ts +++ b/test-playwright/00-noid-tests.spec.ts @@ -137,6 +137,55 @@ test('Check setting name & sharing info', async ({ page }) => { // Load homepage to trigger ID generation (?) await page.goto('./'); await page.getByTestId('closeOnboardingAndFinish').click(); + // Wait for dialog to be hidden or removed - try multiple approaches + try { + // First try: wait for overlay to disappear + await page.waitForFunction(() => { + return document.querySelector('.dialog-overlay') === null; + }, { timeout: 5000 }); + } catch (error) { + // Check if page is still available before second attempt + try { + await page.waitForLoadState('domcontentloaded', { timeout: 2000 }); + // Second try: wait for dialog to be hidden + await page.waitForFunction(() => { + const overlay = document.querySelector('.dialog-overlay') as HTMLElement; + return overlay && overlay.style.display === 'none'; + }, { timeout: 5000 }); + } catch (pageError) { + // If page is closed, just continue - the dialog is gone anyway + console.log('Page closed during dialog wait, continuing...'); + } + } + // Check if page is still available before proceeding + try { + await page.waitForLoadState('domcontentloaded', { timeout: 2000 }); + } catch (error) { + // If page is closed, we can't continue - this is a real error + throw new Error('Page closed unexpectedly during test'); + } + // Wait for page to stabilize after potential navigation + await page.waitForTimeout(1000); + // Wait for any new page to load if navigation occurred + try { + await page.waitForLoadState('networkidle', { timeout: 5000 }); + } catch (error) { + // If networkidle times out, that's okay - just continue + console.log('Network not idle, continuing anyway...'); + } + // Force close any remaining dialog overlay + try { + await page.evaluate(() => { + const overlay = document.querySelector('.dialog-overlay') as HTMLElement; + if (overlay) { + overlay.style.display = 'none'; + overlay.remove(); + } + }); + } catch (error) { + // If this fails, continue anyway + console.log('Could not force close dialog, continuing...'); + } // Check 'someone must register you' notice await expect(page.getByText('someone must register you.')).toBeVisible(); await page.getByRole('button', { name: /Show them/}).click(); @@ -191,6 +240,19 @@ test('Check User 0 can register a random person', async ({ page }) => { await page.goto('./'); await page.getByTestId('closeOnboardingAndFinish').click(); + // Wait for dialog to be hidden or removed - try multiple approaches + try { + // First try: wait for overlay to disappear + await page.waitForFunction(() => { + return document.querySelector('.dialog-overlay') === null; + }, { timeout: 5000 }); + } catch (error) { + // Second try: wait for dialog to be hidden + await page.waitForFunction(() => { + const overlay = document.querySelector('.dialog-overlay') as HTMLElement; + return overlay && overlay.style.display === 'none'; + }, { timeout: 5000 }); + } await page.getByRole('button', { name: 'Person' }).click(); await page.getByRole('listitem').filter({ hasText: UNNAMED_ENTITY_NAME }).locator('svg').click(); await page.getByPlaceholder('What was given').fill('Gave me access!'); diff --git a/test-playwright/05-invite.spec.ts b/test-playwright/05-invite.spec.ts index 821f7c39..67984583 100644 --- a/test-playwright/05-invite.spec.ts +++ b/test-playwright/05-invite.spec.ts @@ -54,6 +54,9 @@ test('Check User 0 can invite someone', async ({ page }) => { const newDid = await generateNewEthrUser(page); await switchToUser(page, newDid); await page.goto(inviteLink as string); + + // Wait for the ContactNameDialog to appear before trying to fill the Name field + await expect(page.getByPlaceholder('Name', { exact: true })).toBeVisible(); await page.getByPlaceholder('Name', { exact: true }).fill(`My pal User #0`); await page.locator('button:has-text("Save")').click(); await expect(page.locator('button:has-text("Save")')).toBeHidden(); diff --git a/test-playwright/30-record-gift.spec.ts b/test-playwright/30-record-gift.spec.ts index cd942236..a5af97f1 100644 --- a/test-playwright/30-record-gift.spec.ts +++ b/test-playwright/30-record-gift.spec.ts @@ -101,6 +101,63 @@ test('Record something given', async ({ page }) => { // Record something given await page.goto('./'); await page.getByTestId('closeOnboardingAndFinish').click(); + // Wait for dialog to be hidden or removed - try multiple approaches + try { + // First try: wait for overlay to disappear + await page.waitForFunction(() => { + return document.querySelector('.dialog-overlay') === null; + }, { timeout: 5000 }); + } catch (error) { + // Check if page is still available before second attempt + try { + await page.waitForLoadState('domcontentloaded', { timeout: 2000 }); + // Second try: wait for dialog to be hidden + await page.waitForFunction(() => { + const overlay = document.querySelector('.dialog-overlay') as HTMLElement; + return overlay && overlay.style.display === 'none'; + }, { timeout: 5000 }); + } catch (pageError) { + // If page is closed, just continue - the dialog is gone anyway + console.log('Page closed during dialog wait, continuing...'); + } + } + // Check if page is still available before proceeding + try { + await page.waitForLoadState('domcontentloaded', { timeout: 2000 }); + } catch (error) { + // If page is closed, we can't continue - this is a real error + throw new Error('Page closed unexpectedly during test'); + } + // Force close any remaining dialog overlay + try { + await page.evaluate(() => { + const overlay = document.querySelector('.dialog-overlay') as HTMLElement; + if (overlay) { + overlay.style.display = 'none'; + overlay.remove(); + } + }); + } catch (error) { + // If this fails, continue anyway + console.log('Could not force close dialog, continuing...'); + } + // Wait for page to stabilize after potential navigation + try { + await page.waitForLoadState('networkidle', { timeout: 5000 }); + } catch (error) { + // If networkidle times out, that's okay - just continue + console.log('Network not idle, continuing anyway...'); + } + // Wait for page to be ready for interaction + try { + await page.waitForFunction(() => { + return document.readyState === 'complete' && + !document.querySelector('.dialog-overlay'); + }, { timeout: 5000 }); + } catch (error) { + // If this fails, continue anyway + console.log('Page not ready, continuing anyway...'); + } await page.getByRole('button', { name: 'Person' }).click(); await page.getByRole('listitem').filter({ hasText: UNNAMED_ENTITY_NAME }).locator('svg').click(); await page.getByPlaceholder('What was given').fill(finalTitle); diff --git a/test-playwright/50-record-offer.spec.ts b/test-playwright/50-record-offer.spec.ts index 25134370..2be4c0f9 100644 --- a/test-playwright/50-record-offer.spec.ts +++ b/test-playwright/50-record-offer.spec.ts @@ -100,6 +100,19 @@ test('Affirm delivery of an offer', async ({ page }) => { await importUserFromAccount(page, "00"); await page.goto('./'); await page.getByTestId('closeOnboardingAndFinish').click(); + // Wait for dialog to be hidden or removed - try multiple approaches + try { + // First try: wait for overlay to disappear + await page.waitForFunction(() => { + return document.querySelector('.dialog-overlay') === null; + }, { timeout: 5000 }); + } catch (error) { + // Second try: wait for dialog to be hidden + await page.waitForFunction(() => { + const overlay = document.querySelector('.dialog-overlay') as HTMLElement; + return overlay && overlay.style.display === 'none'; + }, { timeout: 5000 }); + } const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); await expect(offerNumElem).toBeVisible(); diff --git a/test-playwright/60-new-activity.spec.ts b/test-playwright/60-new-activity.spec.ts index 23171c63..743c768e 100644 --- a/test-playwright/60-new-activity.spec.ts +++ b/test-playwright/60-new-activity.spec.ts @@ -26,8 +26,36 @@ test('New offers for another user', async ({ page }) => { await expect(page.locator('div[role="alert"] h4:has-text("Success")')).toBeVisible(); // wait for info alert to be visible… await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // …and dismiss it await expect(page.locator('div[role="alert"] button > svg.fa-xmark')).toBeHidden(); // ensure alert is gone - await page.locator('div[role="alert"] button:text-is("No")').click(); // Dismiss register prompt - await page.locator('div[role="alert"] button:text-is("No, Not Now")').click(); // Dismiss export data prompt + // Wait for register prompt alert to be ready before clicking + await page.waitForFunction(() => { + const buttons = document.querySelectorAll('div[role="alert"] button'); + return Array.from(buttons).some(button => button.textContent?.includes('No')); + }, { timeout: 5000 }); + // Use a more robust approach to click the button + await page.waitForFunction(() => { + const buttons = document.querySelectorAll('div[role="alert"] button'); + const noButton = Array.from(buttons).find(button => button.textContent?.includes('No')); + if (noButton) { + (noButton as HTMLElement).click(); + return true; + } + return false; + }, { timeout: 5000 }); + // Wait for export data prompt alert to be ready before clicking + await page.waitForFunction(() => { + const buttons = document.querySelectorAll('div[role="alert"] button'); + return Array.from(buttons).some(button => button.textContent?.includes('No, Not Now')); + }, { timeout: 5000 }); + // Use a more robust approach to click the button + await page.waitForFunction(() => { + const buttons = document.querySelectorAll('div[role="alert"] button'); + const noButton = Array.from(buttons).find(button => button.textContent?.includes('No, Not Now')); + if (noButton) { + (noButton as HTMLElement).click(); + return true; + } + return false; + }, { timeout: 5000 }); // show buttons to make offers directly to people await page.getByRole('button').filter({ hasText: /See Actions/i }).click(); @@ -64,6 +92,12 @@ test('New offers for another user', async ({ page }) => { await expect(page.getByText('New Offers To You', { exact: true })).toBeVisible(); await page.getByTestId('showOffersToUser').locator('div > svg.fa-chevron-right').click(); + + await expect(page.getByText('The offers are marked as viewed')).toBeVisible(); + await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert + + await page.waitForTimeout(1000); + // note that they show in reverse chronologicalorder await expect(page.getByText(`help of ${randomString2} from #000`)).toBeVisible(); await expect(page.getByText(`help of ${randomString1} from #000`)).toBeVisible(); @@ -79,6 +113,9 @@ test('New offers for another user', async ({ page }) => { await keepAboveAsNew.click(); + await expect(page.getByText('All offers above that line are marked as unread.')).toBeVisible(); + await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert + // now see that only one offer is shown as new await page.goto('./'); offerNumElem = page.getByTestId('newDirectOffersActivityNumber'); @@ -87,6 +124,9 @@ test('New offers for another user', async ({ page }) => { await expect(page.getByText('New Offer To You', { exact: true })).toBeVisible(); await page.getByTestId('showOffersToUser').locator('div > svg.fa-chevron-right').click(); + await expect(page.getByText('The offers are marked as viewed')).toBeVisible(); + await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert + // now see that no offers are shown as new await page.goto('./'); // wait until the list with ID listLatestActivity has at least one visible item