import { test, expect } from '@playwright/test'; test.describe('Fixes Validation Tests', () => { test.beforeEach(async ({ page }) => { // Clear cookies before each test await page.context().clearCookies(); }); test('Validate trip page loads without syntax errors', async ({ page }) => { console.log('๐Ÿงช Testing: Trip page loads without syntax errors'); // First, create a trip to get access await page.goto('http://localhost:3002'); // Fill out trip creation form await page.fill('input#trip-name', 'Test Trip for Access'); await page.fill('input#creator-name', 'Test User'); await page.selectOption('select#currency', 'USD'); await page.click('button:has-text("Create Trip")'); // Wait for trip creation await expect(page.locator('text=Trip Created!')).toBeVisible({ timeout: 10000 }); // Get share code and go to trip await page.click('button:has-text("Go to Trip Dashboard")'); // Check that trip page loads without syntax errors await expect(page.locator('text=Test Trip for Access')).toBeVisible({ timeout: 10000 }); // Check for key elements that should be present await expect(page.locator('text=Welcome back,')).toBeVisible(); await expect(page.locator('text=Test User')).toBeVisible(); await expect(page.locator('text=Add Expense')).toBeVisible(); await expect(page.locator('text=Add Person')).toBeVisible(); await expect(page.locator('text=Share & Export')).toBeVisible(); console.log('โœ… Trip page loads successfully without syntax errors'); }); test('Validate footer positioning is sticky', async ({ page }) => { console.log('๐Ÿงช Testing: Footer positioning is sticky'); // Test on dashboard page await page.goto('http://localhost:3002'); await page.fill('input#trip-name', 'Footer Test Trip'); await page.fill('input#creator-name', 'Test User'); await page.click('button:has-text("Create Trip")'); await page.click('button:has-text("Go to Trip Dashboard")'); // Wait for trip page to load await expect(page.locator('text=Footer Test Trip')).toBeVisible({ timeout: 10000 }); // Get viewport height and footer position const viewportHeight = await page.viewportSize().height; const footerElement = page.locator('.bg-white.border-t'); // Footer element // Check that footer is at the bottom of viewport const footerBox = await footerElement.boundingBox(); expect(footerBox).toBeTruthy(); if (footerBox) { // Footer should be at the bottom of the viewport const distanceFromBottom = viewportHeight - (footerBox.y + footerBox.height); expect(distanceFromBottom).toBeLessThan(10); // Allow small margin console.log(`โœ… Footer is positioned ${distanceFromBottom}px from bottom of viewport`); } // Test on dashboard page await page.click('button[title="View all trips"]'); await expect(page.locator('text=My Trips')).toBeVisible(); // Check footer positioning on dashboard const dashboardFooter = page.locator('.bg-white.border-t'); const dashboardFooterBox = await dashboardFooter.boundingBox(); expect(dashboardFooterBox).toBeTruthy(); if (dashboardFooterBox) { const dashboardDistanceFromBottom = viewportHeight - (dashboardFooterBox.y + dashboardFooterBox.height); expect(dashboardDistanceFromBottom).toBeLessThan(10); console.log(`โœ… Dashboard footer is positioned ${dashboardDistanceFromBottom}px from bottom`); } }); test('Validate create button functionality', async ({ page }) => { console.log('๐Ÿงช Testing: Create button functionality'); // Test create button on dashboard await page.goto('http://localhost:3002'); await page.fill('input#trip-name', 'Create Button Test'); await page.fill('input#creator-name', 'Test User'); await page.click('button:has-text("Create Trip")'); await page.click('button:has-text("Go to Trip Dashboard")'); // Wait for trip page to load await expect(page.locator('text=Create Button Test')).toBeVisible({ timeout: 10000 }); // Navigate to dashboard await page.click('button[title="View all trips"]'); await expect(page.locator('text=My Trips')).toBeVisible(); // Test create button in footer const createButton = page.locator('a[href="/"]').filter({ hasText: 'Create' }); await expect(createButton).toBeVisible(); // Click create button await createButton.click(); // Should navigate to home page await expect(page.locator('h1')).toContainText('Tritri'); await expect(page.locator('text=Split expenses fairly with your group')).toBeVisible(); console.log('โœ… Create button in footer works correctly'); }); test('Validate add expense button functionality', async ({ page }) => { console.log('๐Ÿงช Testing: Add expense button functionality'); // Create a trip first await page.goto('http://localhost:3002'); await page.fill('input#trip-name', 'Expense Test Trip'); await page.fill('input#creator-name', 'Test User'); await page.click('button:has-text("Create Trip")'); await page.click('button:has-text("Go to Trip Dashboard")'); // Wait for trip page to load await expect(page.locator('text=Expense Test Trip')).toBeVisible({ timeout: 10000 }); // Test main "Add Expense" button const addExpenseButton = page.locator('button:has-text("Add Expense")').first(); await expect(addExpenseButton).toBeVisible(); // Click add expense button await addExpenseButton.click(); // Should open expense modal await expect(page.locator('text=Add Expense')).toBeVisible(); await expect(page.locator('label:has-text("Description")')).toBeVisible(); await expect(page.locator('label:has-text("Amount")')).toBeVisible(); // Close modal await page.click('button:has-text("Cancel")'); await expect(page.locator('text=Add Expense')).not.toBeVisible(); // Test footer "Add" button const footerAddButton = page.locator('button:has-text("Add")'); await expect(footerAddButton).toBeVisible(); // Click footer add button await footerAddButton.click(); // Should also open expense modal await expect(page.locator('text=Add Expense')).toBeVisible(); console.log('โœ… Add expense buttons work correctly'); }); test('Validate API connectivity for trip loading', async ({ page }) => { console.log('๐Ÿงช Testing: API connectivity for trip loading'); // Enable console logging to see API errors page.on('console', msg => { if (msg.type() === 'error') { console.log('Browser console error:', msg.text()); } }); // Create a trip await page.goto('http://localhost:3002'); await page.fill('input#trip-name', 'API Test Trip'); await page.fill('input#creator-name', 'Test User'); await page.click('button:has-text("Create Trip")'); // Wait for trip creation await expect(page.locator('text=Trip Created!')).toBeVisible({ timeout: 15000 }); // Get share code const shareCodeElement = page.locator('text=Share this code with your group:'); await expect(shareCodeElement).toBeVisible(); // Go to trip dashboard await page.click('button:has-text("Go to Trip Dashboard")'); // Check if trip loads or shows error try { await expect(page.locator('text=API Test Trip')).toBeVisible({ timeout: 10000 }); console.log('โœ… Trip loads successfully, API is working'); } catch (error) { // Check for error message const errorMessage = page.locator('text=Failed to load trip data'); if (await errorMessage.isVisible()) { console.log('โŒ Trip failed to load - API connectivity issue detected'); // Check API health const apiResponse = await page.request.get('http://localhost:8000/health'); if (apiResponse.status() !== 200) { console.log('โŒ Backend API is not responding'); } else { console.log('โœ… Backend API is responding, but trip loading failed'); } } throw error; } }); test('Validate multi-trip identity system', async ({ page }) => { console.log('๐Ÿงช Testing: Multi-trip identity system'); // Create first trip await page.goto('http://localhost:3002'); await page.fill('input#trip-name', 'First Trip'); await page.fill('input#creator-name', 'Multi User'); await page.click('button:has-text("Create Trip")'); await page.click('button:has-text("Go to Trip Dashboard")'); // Verify first trip access await expect(page.locator('text=First Trip')).toBeVisible({ timeout: 10000 }); // Navigate to home to create second trip await page.goto('http://localhost:3002'); // Should redirect to dashboard because user has existing trips await expect(page.locator('text=My Trips')).toBeVisible(); // Check that first trip is in dashboard await expect(page.locator('text=First Trip')).toBeVisible(); // Create second trip await page.click('text=Create Trip'); await page.fill('input#trip-name', 'Second Trip'); await page.fill('input#creator-name', 'Multi User'); await page.click('button:has-text("Create Trip")'); await page.click('button:has-text("Go to Trip Dashboard")'); // Verify second trip access await expect(page.locator('text=Second Trip')).toBeVisible({ timeout: 10000 }); // Check dashboard has both trips await page.click('button[title="View all trips"]'); await expect(page.locator('text=First Trip')).toBeVisible(); await expect(page.locator('text=Second Trip')).toBeVisible(); console.log('โœ… Multi-trip identity system working correctly'); }); test('Validate responsive design with sticky footer', async ({ page }) => { console.log('๐Ÿงช Testing: Responsive design with sticky footer'); // Test mobile viewport await page.setViewportSize({ width: 375, height: 667 }); // iPhone SE await page.goto('http://localhost:3002'); // Create and access trip await page.fill('input#trip-name', 'Responsive Test Trip'); await page.fill('input#creator-name', 'Test User'); await page.click('button:has-text("Create Trip")'); await page.click('button:has-text("Go to Trip Dashboard")'); await expect(page.locator('text=Responsive Test Trip')).toBeVisible({ timeout: 10000 }); // Check footer is visible and sticky on mobile const footerElement = page.locator('.bg-white.border-t'); await expect(footerElement).toBeVisible(); const viewportHeight = 667; const footerBox = await footerElement.boundingBox(); expect(footerBox).toBeTruthy(); if (footerBox) { const distanceFromBottom = viewportHeight - (footerBox.y + footerBox.height); expect(distanceFromBottom).toBeLessThan(10); console.log(`โœ… Mobile footer positioning: ${distanceFromBottom}px from bottom`); } // Test tablet viewport await page.setViewportSize({ width: 768, height: 1024 }); // iPad const tabletFooterBox = await footerElement.boundingBox(); if (tabletFooterBox) { const tabletDistanceFromBottom = 1024 - (tabletFooterBox.y + tabletFooterBox.height); expect(tabletDistanceFromBottom).toBeLessThan(10); console.log(`โœ… Tablet footer positioning: ${tabletDistanceFromBottom}px from bottom`); } console.log('โœ… Responsive design with sticky footer working correctly'); }); test('Validate error handling and recovery', async ({ page }) => { console.log('๐Ÿงช Testing: Error handling and recovery'); // Try to access a non-existent trip await page.goto('http://localhost:3002/trip/99999'); // Should redirect to join page because user is not identified await expect(page.locator('text=Join Existing Trip')).toBeVisible({ timeout: 10000 }); // Try to access without proper identification await page.goto('http://localhost:3002'); await page.evaluate(() => localStorage.clear()); // Clear identity // Should go to home page for new users await expect(page.locator('h1')).toContainText('Tritri'); console.log('โœ… Error handling and recovery working correctly'); }); });