/** * End-to-End Contact Management Tests * * Comprehensive test suite for Time Safari's contact management and gift recording features. * Tests run sequentially to avoid state conflicts and API rate limits. * * Test Flow: * 1. Contact Creation & Verification * - Add contact using DID * - Verify contact appears in list * - Rename contact and verify change * - Check contact appears in "Record Something" section * * 2. Gift Recording Flow * - Generate unique gift details * - Record gift to contact * - Verify gift confirmation * - Check gift appears in activity feed * * 3. Contact Import/Export Tests * - Copy contact details to clipboard * - Delete existing contact * - Import contact from clipboard * - Verify imported contact details * * Test Data Generation: * - Gift titles: "Gift " + 16-char random string * - Gift amounts: Random 1-99 value * - Contact names: Predefined test values * - DIDs: Uses test accounts (e.g., did:ethr:0x000...) * * Key Selectors: * - Contact list: 'li[data-testid="contactListItem"]' * - Gift recording: '#sectionRecordSomethingGiven' * - Contact name: '[data-testid="contactName"] input' * - Alert dialogs: 'div[role="alert"]' * * Timeouts & Retries: * - Uses OS-specific timeouts (longer for Linux) * - Implements retry logic for network operations * - Waits for UI animations and state changes * * Alert Handling: * - Closes onboarding dialogs * - Handles registration prompts * - Verifies alert dismissal * * State Requirements: * - Clean database state * - No existing contacts for test DIDs * - Available API rate limits * * @example Basic contact addition * ```typescript * await page.goto('./contacts'); * await page.getByPlaceholder('URL or DID, Name, Public Key') * .fill('did:ethr:0x000...., User Name'); * await page.locator('button > svg.fa-plus').click(); * ``` */ import { test, expect } from '@playwright/test'; import { importUser } from './testUtils'; import { createPerformanceCollector, attachPerformanceData, assertPerformanceMetrics } from './performanceUtils'; test('Check usage limits', async ({ page }, testInfo) => { // STEP 1: Initialize the performance collector const perfCollector = await createPerformanceCollector(page); // STEP 2: Check without ID first await perfCollector.measureUserAction('navigate-to-account', async () => { await page.goto('./account'); }); const initialMetrics = await perfCollector.collectNavigationMetrics('account-page-load'); await testInfo.attach('initial-page-load-metrics', { contentType: 'application/json', body: JSON.stringify(initialMetrics, null, 2) }); await perfCollector.measureUserAction('verify-no-usage-limits', async () => { await expect(page.locator('div.bg-slate-100.rounded-md').filter({ hasText: 'Usage Limits' })).toBeHidden(); }); // STEP 3: Import user 01 await perfCollector.measureUserAction('import-user-account', async () => { const did = await importUser(page, '01'); }); // STEP 4: Verify usage limits section await perfCollector.measureUserAction('verify-usage-limits-section', async () => { await expect(page.locator('#sectionUsageLimits')).toBeVisible(); await expect(page.locator('#sectionUsageLimits')).toContainText('You have done'); await expect(page.locator('#sectionUsageLimits')).toContainText('You have uploaded'); }); await perfCollector.measureUserAction('verify-usage-limit-texts', async () => { await expect(page.getByText('Your claims counter resets')).toBeVisible(); await expect(page.getByText('Your registration counter resets')).toBeVisible(); await expect(page.getByText('Your image counter resets')).toBeVisible(); await expect(page.getByRole('button', { name: 'Recheck Limits' })).toBeVisible(); }); // STEP 5: Set name await perfCollector.measureUserAction('click-set-name-button', async () => { await page.getByRole('button', { name: 'Set Your Name' }).click(); }); await perfCollector.measureUserAction('fill-and-save-name', async () => { const name = 'User ' + '01'.slice(0, 2); await page.getByPlaceholder('Name').fill(name); await page.getByRole('button', { name: 'Save', exact: true }).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); });