/** * @file Image Share Gift Recording Test * @description End-to-end test suite for verifying the gift recording functionality * through image sharing. Tests the complete flow from image upload to gift * verification on the home page. * * Key test scenarios: * - Image upload functionality * - Gift recording form interaction * - Onboarding flow handling * - Success confirmation * - Gift visibility on home page * * @author Matthew Raymer * @created 2024 * * Test Environment Requirements: * - Requires test user data (user '00') * - Needs access to test image files in public/img/icons * - Assumes service worker is properly configured * * @note There is a commented-out test for service worker photo-sharing functionality * that could be implemented in the future. */ import path from 'path'; import { test, expect } from '@playwright/test'; import { importUser, getOSSpecificTimeout } from './testUtils'; import { Page } from '@playwright/test'; const TEST_NAME = 'record-gift-from-image-share'; // Logging utility function - outputs clean, parseable log format const log = (type: 'INFO' | 'STEP' | 'SUCCESS' | 'WAIT', message: string) => { const timestamp = new Date().toISOString().split('T')[1].slice(0, -1); // HH:MM:SS format console.log(`${timestamp} ${type.padEnd(7)} ${message}`); }; // Screenshot helper function async function captureScreenshot(page: Page, name: string) { if (!page.isClosed()) { const filename = `test-results/${TEST_NAME}-${name.replace(/\s+/g, '-')}.png`; log('INFO', `Capturing screenshot: ${filename}`); await page.screenshot({ path: filename, fullPage: true }); return filename; } } test('Record item given from image-share', async ({ page }) => { try { log('INFO', '▶ Starting: Image Share Gift Recording Test'); await captureScreenshot(page, 'test-start'); const TIMEOUT = getOSSpecificTimeout(); log('INFO', `Using OS-specific timeout: ${TIMEOUT}ms`); let randomString = Math.random().toString(36).substring(2, 8); const finalTitle = `Gift ${randomString} from image-share`; log('INFO', `Generated test gift title: ${finalTitle}`); log('STEP', '1. Import test user'); await importUser(page, '00'); await captureScreenshot(page, '1-after-user-import'); log('STEP', '2. Navigate to test page'); await page.goto('./test', { timeout: TIMEOUT }); await captureScreenshot(page, '2-test-page'); log('STEP', '3. Upload image file'); const fileChooserPromise = page.waitForEvent('filechooser'); await page.getByTestId('fileInput').click(); const fileChooser = await fileChooserPromise; const testImagePath = path.join(__dirname, '..', 'public', 'img', 'icons', 'android-chrome-192x192.png'); log('INFO', `Uploading test image from: ${testImagePath}`); await fileChooser.setFiles(testImagePath); await captureScreenshot(page, '3-before-upload'); log('WAIT', 'Upload in progress...'); await page.waitForTimeout(2000); await page.waitForLoadState('networkidle', { timeout: TIMEOUT }); log('SUCCESS', 'Upload complete'); await captureScreenshot(page, '3-after-upload'); log('STEP', '4. Record gift'); await page.getByRole('button').filter({ hasText: /gift/i }).click(); await page.waitForLoadState('networkidle', { timeout: TIMEOUT }); await captureScreenshot(page, '4-gift-form'); log('STEP', '5. Fill gift details'); await expect(page.getByPlaceholder('What was received')).toBeVisible({ timeout: TIMEOUT }); await page.getByPlaceholder('What was received').fill(finalTitle); await page.getByRole('spinbutton').fill('2'); await captureScreenshot(page, '5-filled-form'); log('STEP', '6. Submit gift'); await page.getByRole('button', { name: 'Sign & Send' }).click(); await captureScreenshot(page, '6-after-submit'); log('STEP', '7. Handle confirmation'); await page.getByTestId('closeOnboardingAndFinish').click(); await expect(page.getByText('That gift was recorded.')).toBeVisible({ timeout: TIMEOUT }); await page.locator('div[role="alert"] button > svg.fa-xmark').click(); await captureScreenshot(page, '7-after-confirmation'); log('STEP', '8. Verify on home page'); await page.goto('./'); await page.waitForLoadState('networkidle', { timeout: TIMEOUT }); const item1 = page.locator('li').filter({ hasText: finalTitle }); await expect(item1).toBeVisible({ timeout: TIMEOUT }); await captureScreenshot(page, '8-home-page-verification'); log('SUCCESS', '✓ Test completed successfully'); } catch (error) { await captureScreenshot(page, `failure-${Date.now()}`); log('INFO', `Test failed: ${error instanceof Error ? error.message : String(error)}`); throw error; } }); // // I believe there's a way to test this service worker feature. // // The following is what I got from ChatGPT. I wonder if it doesn't work because it's not registering the service worker correctly. // // test('Trigger a photo-sharing fetch event in service worker with POST to /share-target', async ({ page }) => { // await importUser(page, '00'); // // // Create a FormData object with a photo // const photoPath = path.join(__dirname, '..', 'public', 'img', 'icons', 'android-chrome-192x192.png'); // const photoContent = await fs.readFileSync(photoPath); // const [response] = await Promise.all([ // page.waitForResponse(response => response.url().includes('/share-target')), // also check for response.status() === 303 ? // page.evaluate(async (photoContent) => { // const formData = new FormData(); // formData.append('photo', new Blob([photoContent], { type: 'image/png' }), 'test-photo.jpg'); // // const response = await fetch('/share-target', { // method: 'POST', // body: formData, // }); // // return response; // }, photoContent) // ]); // // // Verify the response redirected to /shared-photo // //expect(response.status).toBe(303); // console.log('response headers', response.headers()); // console.log('response status', response.status()); // console.log('response url', response.url()); // expect(response.url()).toContain('/shared-photo'); // });