Browse Source
Enhance test files with comprehensive performance tracking: - Add performance collector integration to usage limits, project gifts, and offer recording tests - Implement detailed user action timing with measureUserAction wrapper - Add navigation metrics collection and validation - Include performance data attachments to test reports - Add dialog overlay handling for improved test reliability Files modified: - test-playwright/10-check-usage-limits.spec.ts - test-playwright/37-record-gift-on-project.spec.ts - test-playwright/50-record-offer.spec.tspull/159/head
3 changed files with 409 additions and 164 deletions
@ -1,50 +1,101 @@ |
|||||
import { test, expect, Page } from '@playwright/test'; |
import { test, expect, Page } from '@playwright/test'; |
||||
import { importUser } from './testUtils'; |
import { importUser } from './testUtils'; |
||||
|
import { createPerformanceCollector, attachPerformanceData, assertPerformanceMetrics } from './performanceUtils'; |
||||
|
|
||||
async function testProjectGive(page: Page, selector: string) { |
async function testProjectGive(page: Page, selector: string, testInfo: any) { |
||||
|
// STEP 1: Initialize the performance collector
|
||||
|
const perfCollector = await createPerformanceCollector(page); |
||||
|
|
||||
// Generate a random string of a few characters
|
// STEP 2: Generate unique test data
|
||||
const randomString = Math.random().toString(36).substring(2, 6); |
const randomString = Math.random().toString(36).substring(2, 6); |
||||
|
|
||||
// Generate a random non-zero single-digit number
|
|
||||
const randomNonZeroNumber = Math.floor(Math.random() * 99) + 1; |
const randomNonZeroNumber = Math.floor(Math.random() * 99) + 1; |
||||
|
|
||||
// Standard title prefix
|
|
||||
const standardTitle = 'Gift '; |
const standardTitle = 'Gift '; |
||||
|
|
||||
// Combine title prefix with the random string
|
|
||||
const finalTitle = standardTitle + randomString; |
const finalTitle = standardTitle + randomString; |
||||
|
|
||||
// find a project and enter a give to it and see that it shows
|
// STEP 3: Import user and navigate to discover
|
||||
await importUser(page, '00'); |
await perfCollector.measureUserAction('import-user-account', async () => { |
||||
await page.goto('./discover'); |
await importUser(page, '00'); |
||||
await page.getByTestId('closeOnboardingAndFinish').click(); |
}); |
||||
|
|
||||
await page.locator('ul#listDiscoverResults li:first-child a').click() |
await perfCollector.measureUserAction('navigate-to-discover', async () => { |
||||
// wait for the project page to load
|
await page.goto('./discover'); |
||||
await page.waitForLoadState('networkidle'); |
}); |
||||
// click the give button, inside the first div
|
const initialMetrics = await perfCollector.collectNavigationMetrics('discover-page-load'); |
||||
await page.getByTestId(selector).locator('div:first-child div button').click(); |
await testInfo.attach('initial-page-load-metrics', { |
||||
await page.getByPlaceholder('What was given').fill(finalTitle); |
contentType: 'application/json', |
||||
await page.getByRole('spinbutton').fill(randomNonZeroNumber.toString()); |
body: JSON.stringify(initialMetrics, null, 2) |
||||
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
}); |
||||
await expect(page.getByText('That gift was recorded.')).toBeVisible(); |
|
||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
await perfCollector.measureUserAction('close-onboarding', async () => { |
||||
|
await page.getByTestId('closeOnboardingAndFinish').click(); |
||||
// refresh the page
|
}); |
||||
await page.reload(); |
|
||||
// check that the give is in the list
|
await perfCollector.measureUserAction('select-first-project', async () => { |
||||
await page |
await page.locator('ul#listDiscoverResults li:first-child a').click(); |
||||
.getByTestId(selector) |
}); |
||||
.locator('div ul li:first-child') |
|
||||
.filter({ hasText: finalTitle }) |
// STEP 4: Wait for project page to load
|
||||
.isVisible(); |
await perfCollector.measureUserAction('wait-for-project-load', async () => { |
||||
|
await page.waitForLoadState('networkidle'); |
||||
|
}); |
||||
|
|
||||
|
// STEP 5: Handle dialog overlays
|
||||
|
await perfCollector.measureUserAction('close-dialog-overlays', async () => { |
||||
|
await page.waitForTimeout(1000); |
||||
|
const closeButtons = page.locator('button[aria-label*="close"], button[aria-label*="Close"], .dialog-overlay button, [role="dialog"] button'); |
||||
|
const count = await closeButtons.count(); |
||||
|
|
||||
|
for (let i = 0; i < count; i++) { |
||||
|
try { |
||||
|
await closeButtons.nth(i).click({ timeout: 2000 }); |
||||
|
} catch (e) { |
||||
|
// Ignore errors if button is not clickable
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await page.waitForTimeout(500); |
||||
|
}); |
||||
|
|
||||
|
// STEP 6: Record gift
|
||||
|
await perfCollector.measureUserAction('click-give-button', async () => { |
||||
|
await page.getByTestId(selector).locator('div:first-child div button').click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('fill-gift-details', async () => { |
||||
|
await page.getByPlaceholder('What was given').fill(finalTitle); |
||||
|
await page.getByRole('spinbutton').fill(randomNonZeroNumber.toString()); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('submit-gift', async () => { |
||||
|
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
||||
|
await expect(page.getByText('That gift was recorded.')).toBeVisible(); |
||||
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 7: Verify gift appears in list
|
||||
|
await perfCollector.measureUserAction('refresh-page', async () => { |
||||
|
await page.reload(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-gift-in-list', async () => { |
||||
|
await page |
||||
|
.getByTestId(selector) |
||||
|
.locator('div ul li:first-child') |
||||
|
.filter({ hasText: finalTitle }) |
||||
|
.isVisible(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 8: Attach and validate performance data
|
||||
|
const { webVitals, performanceReport, summary } = await attachPerformanceData(testInfo, perfCollector); |
||||
|
const avgNavigationTime = perfCollector.navigationMetrics.reduce((sum, nav) => |
||||
|
sum + nav.metrics.loadComplete, 0) / perfCollector.navigationMetrics.length; |
||||
|
assertPerformanceMetrics(webVitals, initialMetrics, avgNavigationTime); |
||||
} |
} |
||||
|
|
||||
test('Record a give to a project', async ({ page }) => { |
test('Record a give to a project', async ({ page }, testInfo) => { |
||||
await testProjectGive(page, 'gives-to'); |
await testProjectGive(page, 'gives-to', testInfo); |
||||
}); |
}); |
||||
|
|
||||
test('Record a give from a project', async ({ page }) => { |
test('Record a give from a project', async ({ page }, testInfo) => { |
||||
await testProjectGive(page, 'gives-from'); |
await testProjectGive(page, 'gives-from', testInfo); |
||||
}); |
}); |
||||
|
@ -1,127 +1,291 @@ |
|||||
import { test, expect, Page } from '@playwright/test'; |
import { test, expect, Page } from '@playwright/test'; |
||||
import { importUser, importUserFromAccount } from './testUtils'; |
import { importUser, importUserFromAccount } from './testUtils'; |
||||
|
import { createPerformanceCollector, attachPerformanceData, assertPerformanceMetrics } from './performanceUtils'; |
||||
|
|
||||
test('Record an offer', async ({ page }) => { |
test('Record an offer', async ({ page }, testInfo) => { |
||||
test.setTimeout(60000); |
test.setTimeout(60000); |
||||
|
|
||||
// Generate a random string of 3 characters, skipping the "0." at the beginning
|
// STEP 1: Initialize the performance collector
|
||||
|
const perfCollector = await createPerformanceCollector(page); |
||||
|
|
||||
|
// STEP 2: Generate unique test data
|
||||
const randomString = Math.random().toString(36).substring(2, 5); |
const randomString = Math.random().toString(36).substring(2, 5); |
||||
// Standard title prefix
|
|
||||
const description = `Offering of ${randomString}`; |
const description = `Offering of ${randomString}`; |
||||
const updatedDescription = `Updated ${description}`; |
const updatedDescription = `Updated ${description}`; |
||||
const randomNonZeroNumber = Math.floor(Math.random() * 998) + 1; |
const randomNonZeroNumber = Math.floor(Math.random() * 998) + 1; |
||||
|
|
||||
// Switch to user 0
|
// STEP 3: Import user and navigate to discover page
|
||||
// await importUser(page);
|
await perfCollector.measureUserAction('import-user-account', async () => { |
||||
// Become User Zero
|
await importUserFromAccount(page, "00"); |
||||
await importUserFromAccount(page, "00"); |
}); |
||||
// Select a project
|
|
||||
await page.goto('./discover'); |
await perfCollector.measureUserAction('navigate-to-discover', async () => { |
||||
await page.getByTestId('closeOnboardingAndFinish').click(); |
await page.goto('./discover'); |
||||
await page.locator('ul#listDiscoverResults li:nth-child(1)').click(); |
}); |
||||
// Record an offer
|
const initialMetrics = await perfCollector.collectNavigationMetrics('discover-page-load'); |
||||
await page.locator('button', { hasText: 'Edit' }).isVisible(); // since the 'edit' takes longer to show, wait for that (lest the click miss)
|
await testInfo.attach('initial-page-load-metrics', { |
||||
await page.getByTestId('offerButton').click(); |
contentType: 'application/json', |
||||
await page.getByTestId('inputDescription').fill(description); |
body: JSON.stringify(initialMetrics, null, 2) |
||||
await page.getByTestId('inputOfferAmount').fill(randomNonZeroNumber.toString()); |
}); |
||||
expect(page.getByRole('button', { name: 'Sign & Send' })); |
|
||||
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
// STEP 4: Close onboarding and select project
|
||||
await expect(page.getByText('That offer was recorded.')).toBeVisible(); |
await perfCollector.measureUserAction('close-onboarding', async () => { |
||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
await page.getByTestId('closeOnboardingAndFinish').click(); |
||||
// go to the offer and check the values
|
}); |
||||
await page.goto('./projects'); |
|
||||
await page.getByRole('link', { name: 'Offers', exact: true }).click(); |
await perfCollector.measureUserAction('select-project', async () => { |
||||
await page.locator('li').filter({ hasText: description }).locator('a').first().click(); |
await page.locator('ul#listDiscoverResults li:nth-child(1)').click(); |
||||
await expect(page.getByRole('heading', { name: 'Verifiable Claim Details' })).toBeVisible(); |
}); |
||||
await expect(page.getByText(description, { exact: true })).toBeVisible(); |
|
||||
await expect(page.getByText('Offered to a bigger plan')).toBeVisible(); |
// STEP 5: Record an offer
|
||||
|
await perfCollector.measureUserAction('wait-for-edit-button', async () => { |
||||
|
await page.locator('button', { hasText: 'Edit' }).isVisible(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-offer-button', async () => { |
||||
|
await page.getByTestId('offerButton').click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('fill-offer-details', async () => { |
||||
|
await page.getByTestId('inputDescription').fill(description); |
||||
|
await page.getByTestId('inputOfferAmount').fill(randomNonZeroNumber.toString()); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('submit-offer', async () => { |
||||
|
expect(page.getByRole('button', { name: 'Sign & Send' })); |
||||
|
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
||||
|
await expect(page.getByText('That offer was recorded.')).toBeVisible(); |
||||
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 6: Navigate to projects and check offer
|
||||
|
await perfCollector.measureUserAction('navigate-to-projects', async () => { |
||||
|
await page.goto('./projects'); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-offers-tab', async () => { |
||||
|
await page.getByRole('link', { name: 'Offers', exact: true }).click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-offer-details', async () => { |
||||
|
await page.locator('li').filter({ hasText: description }).locator('a').first().click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-offer-details', async () => { |
||||
|
await expect(page.getByRole('heading', { name: 'Verifiable Claim Details' })).toBeVisible(); |
||||
|
await expect(page.getByText(description, { exact: true })).toBeVisible(); |
||||
|
await expect(page.getByText('Offered to a bigger plan')).toBeVisible(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 7: Expand details and check public server
|
||||
const serverPagePromise = page.waitForEvent('popup'); |
const serverPagePromise = page.waitForEvent('popup'); |
||||
// expand the Details section to see the extended details
|
|
||||
await page.getByRole('heading', { name: 'Details', exact: true }).click(); |
await perfCollector.measureUserAction('expand-details', async () => { |
||||
await page.getByRole('link', { name: 'View on the Public Server' }).click(); |
await page.getByRole('heading', { name: 'Details', exact: true }).click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('open-public-server', async () => { |
||||
|
await page.getByRole('link', { name: 'View on the Public Server' }).click(); |
||||
|
}); |
||||
|
|
||||
const serverPage = await serverPagePromise; |
const serverPage = await serverPagePromise; |
||||
await expect(serverPage.getByText(description)).toBeVisible(); |
await perfCollector.measureUserAction('verify-public-server', async () => { |
||||
await expect(serverPage.getByText('did:none:HIDDEN')).toBeVisible(); |
await expect(serverPage.getByText(description)).toBeVisible(); |
||||
// Now update that offer
|
await expect(serverPage.getByText('did:none:HIDDEN')).toBeVisible(); |
||||
|
}); |
||||
// find the edit page and check the old values again
|
|
||||
await page.goto('./projects'); |
// STEP 8: Update the offer
|
||||
await page.getByRole('link', { name: 'Offers', exact: true }).click(); |
await perfCollector.measureUserAction('navigate-back-to-projects', async () => { |
||||
await page.locator('li').filter({ hasText: description }).locator('a').first().click(); |
await page.goto('./projects'); |
||||
await page.getByTestId('editClaimButton').click(); |
}); |
||||
await page.locator('heading', { hasText: 'What is offered' }).isVisible(); |
|
||||
const itemDesc = await page.getByTestId('itemDescription'); |
await perfCollector.measureUserAction('click-offers-tab-again', async () => { |
||||
await expect(itemDesc).toHaveValue(description); |
await page.getByRole('link', { name: 'Offers', exact: true }).click(); |
||||
const amount = await page.getByTestId('inputOfferAmount'); |
}); |
||||
await expect(amount).toHaveValue(randomNonZeroNumber.toString()); |
|
||||
// update the values
|
await perfCollector.measureUserAction('click-offer-to-edit', async () => { |
||||
await itemDesc.fill(updatedDescription); |
await page.locator('li').filter({ hasText: description }).locator('a').first().click(); |
||||
await amount.fill(String(randomNonZeroNumber + 1)); |
}); |
||||
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
|
||||
await expect(page.getByText('That offer was recorded.')).toBeVisible(); |
await perfCollector.measureUserAction('click-edit-button', async () => { |
||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
await page.getByTestId('editClaimButton').click(); |
||||
// go to the offer claim again and check the updated values
|
}); |
||||
await page.goto('./projects'); |
|
||||
await page.getByRole('link', { name: 'Offers', exact: true }).click(); |
await perfCollector.measureUserAction('verify-edit-form', async () => { |
||||
await page.locator('li').filter({ hasText: description }).locator('a').first().click(); |
await page.locator('heading', { hasText: 'What is offered' }).isVisible(); |
||||
const newItemDesc = page.getByTestId('description'); |
const itemDesc = await page.getByTestId('itemDescription'); |
||||
await expect(newItemDesc).toHaveText(updatedDescription); |
await expect(itemDesc).toHaveValue(description); |
||||
// go to edit page
|
const amount = await page.getByTestId('inputOfferAmount'); |
||||
await page.getByTestId('editClaimButton').click(); |
await expect(amount).toHaveValue(randomNonZeroNumber.toString()); |
||||
const newAmount = page.getByTestId('inputOfferAmount'); |
}); |
||||
await expect(newAmount).toHaveValue((randomNonZeroNumber + 1).toString()); |
|
||||
// go to the home page and check that the offer is shown as new
|
await perfCollector.measureUserAction('update-offer-values', async () => { |
||||
await page.goto('./'); |
const itemDesc = await page.getByTestId('itemDescription'); |
||||
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); |
await itemDesc.fill(updatedDescription); |
||||
// extract the number and check that it's greater than 0 or "50+"
|
const amount = await page.getByTestId('inputOfferAmount'); |
||||
const offerNumText = await offerNumElem.textContent(); |
await amount.fill(String(randomNonZeroNumber + 1)); |
||||
if (offerNumText === null) { |
}); |
||||
throw new Error('Expected Activity Number greater than 0 but got null.'); |
|
||||
} else if (offerNumText === '50+') { |
await perfCollector.measureUserAction('submit-updated-offer', async () => { |
||||
// we're OK
|
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
||||
} else if (parseInt(offerNumText) > 0) { |
await expect(page.getByText('That offer was recorded.')).toBeVisible(); |
||||
// we're OK
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); |
||||
} else { |
}); |
||||
throw new Error(`Expected Activity Number of greater than 0 but got ${offerNumText}.`); |
|
||||
} |
// STEP 9: Verify updated offer
|
||||
|
await perfCollector.measureUserAction('navigate-to-projects-final', async () => { |
||||
// click on the number of new offers to go to the list page
|
await page.goto('./projects'); |
||||
await offerNumElem.click(); |
}); |
||||
await expect(page.getByText('New Offers To Your Projects', { exact: true })).toBeVisible(); |
|
||||
// get the icon child of the showOffersToUserProjects
|
await perfCollector.measureUserAction('click-offers-tab-final', async () => { |
||||
await page.getByTestId('showOffersToUserProjects').locator('div > svg.fa-chevron-right').click(); |
await page.getByRole('link', { name: 'Offers', exact: true }).click(); |
||||
await expect(page.getByText(description)).toBeVisible(); |
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-updated-offer', async () => { |
||||
|
await page.locator('li').filter({ hasText: description }).locator('a').first().click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-updated-offer', async () => { |
||||
|
const newItemDesc = page.getByTestId('description'); |
||||
|
await expect(newItemDesc).toHaveText(updatedDescription); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-edit-button-final', async () => { |
||||
|
await page.getByTestId('editClaimButton').click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-updated-amount', async () => { |
||||
|
const newAmount = page.getByTestId('inputOfferAmount'); |
||||
|
await expect(newAmount).toHaveValue((randomNonZeroNumber + 1).toString()); |
||||
|
}); |
||||
|
|
||||
|
// STEP 10: Check home page for new offers
|
||||
|
await perfCollector.measureUserAction('navigate-to-home', async () => { |
||||
|
await page.goto('./'); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-new-offers-indicator', async () => { |
||||
|
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); |
||||
|
const offerNumText = await offerNumElem.textContent(); |
||||
|
if (offerNumText === null) { |
||||
|
throw new Error('Expected Activity Number greater than 0 but got null.'); |
||||
|
} else if (offerNumText === '50+') { |
||||
|
// we're OK
|
||||
|
} else if (parseInt(offerNumText) > 0) { |
||||
|
// we're OK
|
||||
|
} else { |
||||
|
throw new Error(`Expected Activity Number of greater than 0 but got ${offerNumText}.`); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-new-offers-number', async () => { |
||||
|
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); |
||||
|
await offerNumElem.click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-new-offers-page', async () => { |
||||
|
await expect(page.getByText('New Offers To Your Projects', { exact: true })).toBeVisible(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('expand-offers-section', async () => { |
||||
|
await page.getByTestId('showOffersToUserProjects').locator('div > svg.fa-chevron-right').click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-offer-in-list', async () => { |
||||
|
await expect(page.getByText(description)).toBeVisible(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 11: Attach and validate performance data
|
||||
|
const { webVitals, performanceReport, summary } = await attachPerformanceData(testInfo, perfCollector); |
||||
|
const avgNavigationTime = perfCollector.navigationMetrics.reduce((sum, nav) => |
||||
|
sum + nav.metrics.loadComplete, 0) / perfCollector.navigationMetrics.length; |
||||
|
assertPerformanceMetrics(webVitals, initialMetrics, avgNavigationTime); |
||||
}); |
}); |
||||
|
|
||||
test('Affirm delivery of an offer', async ({ page }) => { |
test('Affirm delivery of an offer', async ({ page }, testInfo) => { |
||||
// go to the home page and check that the offer is shown as new
|
// STEP 1: Initialize the performance collector
|
||||
// await importUser(page);
|
const perfCollector = await createPerformanceCollector(page); |
||||
|
|
||||
await importUserFromAccount(page, "00"); |
// STEP 2: Import user and navigate to home
|
||||
await page.goto('./'); |
await perfCollector.measureUserAction('import-user-account', async () => { |
||||
await page.getByTestId('closeOnboardingAndFinish').click(); |
await importUserFromAccount(page, "00"); |
||||
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); |
}); |
||||
await expect(offerNumElem).toBeVisible(); |
|
||||
|
|
||||
// click on the number of new offers to go to the list page
|
await perfCollector.measureUserAction('navigate-to-home', async () => { |
||||
await offerNumElem.click(); |
await page.goto('./'); |
||||
|
}); |
||||
// get the link that comes after the showOffersToUserProjects and click it
|
const initialMetrics = await perfCollector.collectNavigationMetrics('home-page-load'); |
||||
await page.getByTestId('showOffersToUserProjects').locator('a').click(); |
await testInfo.attach('initial-page-load-metrics', { |
||||
|
contentType: 'application/json', |
||||
// get the first item of the list and click on the icon with file-lines
|
body: JSON.stringify(initialMetrics, null, 2) |
||||
const firstItem = page.getByTestId('listRecentOffersToUserProjects').locator('li').first(); |
}); |
||||
await expect(firstItem).toBeVisible(); |
|
||||
await firstItem.locator('svg.fa-file-lines').click(); |
await perfCollector.measureUserAction('close-onboarding', async () => { |
||||
await expect(page.getByText('Verifiable Claim Details', { exact: true })).toBeVisible(); |
await page.getByTestId('closeOnboardingAndFinish').click(); |
||||
|
}); |
||||
// click on the 'Affirm Delivery' button
|
|
||||
await page.getByRole('button', { name: 'Affirm Delivery' }).click(); |
// STEP 3: Check new offers indicator
|
||||
// fill our offer info and submit
|
await perfCollector.measureUserAction('verify-new-offers-indicator', async () => { |
||||
await page.getByPlaceholder('What was given').fill('Whatever the offer says'); |
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); |
||||
await page.getByRole('spinbutton').fill('2'); |
await expect(offerNumElem).toBeVisible(); |
||||
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
}); |
||||
await expect(page.getByText('That gift was recorded.')).toBeVisible(); |
|
||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
// STEP 4: Navigate to offers list
|
||||
|
await perfCollector.measureUserAction('click-new-offers-number', async () => { |
||||
|
// Close any dialog overlays that might be blocking clicks
|
||||
|
await page.waitForTimeout(1000); |
||||
|
const closeButtons = page.locator('button[aria-label*="close"], button[aria-label*="Close"], .dialog-overlay button, [role="dialog"] button'); |
||||
|
const count = await closeButtons.count(); |
||||
|
|
||||
|
for (let i = 0; i < count; i++) { |
||||
|
try { |
||||
|
await closeButtons.nth(i).click({ timeout: 2000 }); |
||||
|
} catch (e) { |
||||
|
// Ignore errors if button is not clickable
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Wait for any animations to complete
|
||||
|
await page.waitForTimeout(500); |
||||
|
|
||||
|
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber'); |
||||
|
await offerNumElem.click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-offers-link', async () => { |
||||
|
await page.getByTestId('showOffersToUserProjects').locator('a').click(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 5: Affirm delivery
|
||||
|
await perfCollector.measureUserAction('select-first-offer', async () => { |
||||
|
const firstItem = page.getByTestId('listRecentOffersToUserProjects').locator('li').first(); |
||||
|
await expect(firstItem).toBeVisible(); |
||||
|
await firstItem.locator('svg.fa-file-lines').click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-claim-details', async () => { |
||||
|
await expect(page.getByText('Verifiable Claim Details', { exact: true })).toBeVisible(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('click-affirm-delivery', async () => { |
||||
|
await page.getByRole('button', { name: 'Affirm Delivery' }).click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('fill-delivery-details', async () => { |
||||
|
await page.getByPlaceholder('What was given').fill('Whatever the offer says'); |
||||
|
await page.getByRole('spinbutton').fill('2'); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('submit-delivery', async () => { |
||||
|
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
||||
|
await expect(page.getByText('That gift was recorded.')).toBeVisible(); |
||||
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); |
||||
|
}); |
||||
|
|
||||
|
// STEP 6: Attach and validate performance data
|
||||
|
const { webVitals, performanceReport, summary } = await attachPerformanceData(testInfo, perfCollector); |
||||
|
const avgNavigationTime = perfCollector.navigationMetrics.reduce((sum, nav) => |
||||
|
sum + nav.metrics.loadComplete, 0) / perfCollector.navigationMetrics.length; |
||||
|
assertPerformanceMetrics(webVitals, initialMetrics, avgNavigationTime); |
||||
}); |
}); |
||||
|
|
||||
|
Loading…
Reference in new issue