You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
12 KiB
291 lines
12 KiB
import { test, expect, Page } from '@playwright/test';
|
|
import { importUser, importUserFromAccount } from './testUtils';
|
|
import { createPerformanceCollector, attachPerformanceData, assertPerformanceMetrics } from './performanceUtils';
|
|
|
|
test('Record an offer', async ({ page }, testInfo) => {
|
|
test.setTimeout(60000);
|
|
|
|
// 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 description = `Offering of ${randomString}`;
|
|
const updatedDescription = `Updated ${description}`;
|
|
const randomNonZeroNumber = Math.floor(Math.random() * 998) + 1;
|
|
|
|
// STEP 3: Import user and navigate to discover page
|
|
await perfCollector.measureUserAction('import-user-account', async () => {
|
|
await importUserFromAccount(page, "00");
|
|
});
|
|
|
|
await perfCollector.measureUserAction('navigate-to-discover', async () => {
|
|
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)
|
|
});
|
|
|
|
// STEP 4: Close onboarding and select project
|
|
await perfCollector.measureUserAction('close-onboarding', async () => {
|
|
await page.getByTestId('closeOnboardingAndFinish').click();
|
|
});
|
|
|
|
await perfCollector.measureUserAction('select-project', async () => {
|
|
await page.locator('ul#listDiscoverResults li:nth-child(1)').click();
|
|
});
|
|
|
|
// 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');
|
|
|
|
await perfCollector.measureUserAction('expand-details', async () => {
|
|
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;
|
|
await perfCollector.measureUserAction('verify-public-server', async () => {
|
|
await expect(serverPage.getByText(description)).toBeVisible();
|
|
await expect(serverPage.getByText('did:none:HIDDEN')).toBeVisible();
|
|
});
|
|
|
|
// STEP 8: Update the offer
|
|
await perfCollector.measureUserAction('navigate-back-to-projects', async () => {
|
|
await page.goto('./projects');
|
|
});
|
|
|
|
await perfCollector.measureUserAction('click-offers-tab-again', async () => {
|
|
await page.getByRole('link', { name: 'Offers', exact: true }).click();
|
|
});
|
|
|
|
await perfCollector.measureUserAction('click-offer-to-edit', async () => {
|
|
await page.locator('li').filter({ hasText: description }).locator('a').first().click();
|
|
});
|
|
|
|
await perfCollector.measureUserAction('click-edit-button', async () => {
|
|
await page.getByTestId('editClaimButton').click();
|
|
});
|
|
|
|
await perfCollector.measureUserAction('verify-edit-form', async () => {
|
|
await page.locator('heading', { hasText: 'What is offered' }).isVisible();
|
|
const itemDesc = await page.getByTestId('itemDescription');
|
|
await expect(itemDesc).toHaveValue(description);
|
|
const amount = await page.getByTestId('inputOfferAmount');
|
|
await expect(amount).toHaveValue(randomNonZeroNumber.toString());
|
|
});
|
|
|
|
await perfCollector.measureUserAction('update-offer-values', async () => {
|
|
const itemDesc = await page.getByTestId('itemDescription');
|
|
await itemDesc.fill(updatedDescription);
|
|
const amount = await page.getByTestId('inputOfferAmount');
|
|
await amount.fill(String(randomNonZeroNumber + 1));
|
|
});
|
|
|
|
await perfCollector.measureUserAction('submit-updated-offer', async () => {
|
|
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 9: Verify updated offer
|
|
await perfCollector.measureUserAction('navigate-to-projects-final', async () => {
|
|
await page.goto('./projects');
|
|
});
|
|
|
|
await perfCollector.measureUserAction('click-offers-tab-final', async () => {
|
|
await page.getByRole('link', { name: 'Offers', exact: true }).click();
|
|
});
|
|
|
|
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 }, testInfo) => {
|
|
// STEP 1: Initialize the performance collector
|
|
const perfCollector = await createPerformanceCollector(page);
|
|
|
|
// STEP 2: Import user and navigate to home
|
|
await perfCollector.measureUserAction('import-user-account', async () => {
|
|
await importUserFromAccount(page, "00");
|
|
});
|
|
|
|
await perfCollector.measureUserAction('navigate-to-home', async () => {
|
|
await page.goto('./');
|
|
});
|
|
const initialMetrics = await perfCollector.collectNavigationMetrics('home-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();
|
|
});
|
|
|
|
// STEP 3: Check new offers indicator
|
|
await perfCollector.measureUserAction('verify-new-offers-indicator', async () => {
|
|
const offerNumElem = page.getByTestId('newOffersToUserProjectsActivityNumber');
|
|
await expect(offerNumElem).toBeVisible();
|
|
});
|
|
|
|
// 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);
|
|
});
|
|
|
|
|