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.
 
 
 
 

150 lines
6.1 KiB

/**
* @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');
// });