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 perfCollector.measureUserAction('import-user-account', async () => { |
||||
await importUser(page, '00'); |
await importUser(page, '00'); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('navigate-to-discover', async () => { |
||||
await page.goto('./discover'); |
await page.goto('./discover'); |
||||
|
}); |
||||
|
const initialMetrics = await perfCollector.collectNavigationMetrics('discover-page-load'); |
||||
|
await testInfo.attach('initial-page-load-metrics', { |
||||
|
contentType: 'application/json', |
||||
|
body: JSON.stringify(initialMetrics, null, 2) |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('close-onboarding', async () => { |
||||
await page.getByTestId('closeOnboardingAndFinish').click(); |
await page.getByTestId('closeOnboardingAndFinish').click(); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('select-first-project', async () => { |
||||
|
await page.locator('ul#listDiscoverResults li:first-child a').click(); |
||||
|
}); |
||||
|
|
||||
await page.locator('ul#listDiscoverResults li:first-child a').click() |
// STEP 4: Wait for project page to load
|
||||
// wait for the project page to load
|
await perfCollector.measureUserAction('wait-for-project-load', async () => { |
||||
await page.waitForLoadState('networkidle'); |
await page.waitForLoadState('networkidle'); |
||||
// click the give button, inside the first div
|
}); |
||||
|
|
||||
|
// 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 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.getByPlaceholder('What was given').fill(finalTitle); |
||||
await page.getByRole('spinbutton').fill(randomNonZeroNumber.toString()); |
await page.getByRole('spinbutton').fill(randomNonZeroNumber.toString()); |
||||
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('submit-gift', async () => { |
||||
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
await page.getByRole('button', { name: 'Sign & Send' }).click(); |
||||
await expect(page.getByText('That gift was recorded.')).toBeVisible(); |
await expect(page.getByText('That gift was recorded.')).toBeVisible(); |
||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss info alert
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); |
||||
|
}); |
||||
|
|
||||
// refresh the page
|
// STEP 7: Verify gift appears in list
|
||||
|
await perfCollector.measureUserAction('refresh-page', async () => { |
||||
await page.reload(); |
await page.reload(); |
||||
// check that the give is in the list
|
}); |
||||
|
|
||||
|
await perfCollector.measureUserAction('verify-gift-in-list', async () => { |
||||
await page |
await page |
||||
.getByTestId(selector) |
.getByTestId(selector) |
||||
.locator('div ul li:first-child') |
.locator('div ul li:first-child') |
||||
.filter({ hasText: finalTitle }) |
.filter({ hasText: finalTitle }) |
||||
.isVisible(); |
.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); |
||||
}); |
}); |
||||
|
Loading…
Reference in new issue