/** * End-to-end tests using Playwright */ import { test, expect } from '@playwright/test'; // Helper function for network-resilient page navigation async function navigateWithRetry(page: any, url: string, maxRetries = 3): Promise { for (let i = 0; i < maxRetries; i++) { try { await page.goto(url, { waitUntil: 'networkidle', timeout: process.env.CI ? 45000 : 30000, }); return; // Success } catch (error) { if (i === maxRetries - 1) throw error; // Last attempt failed console.log(`Navigation attempt ${i + 1} failed, retrying...`); await page.waitForTimeout(2000); // Wait before retry } } } test.describe('Plex Playlist App', () => { test('should display app title', async ({ page }) => { await navigateWithRetry(page, '/'); // Wait for the app to fully load with network resilience await page.waitForSelector('h1', { timeout: 15000 }); await expect(page.locator('h1')).toContainText('Plex Playlist'); }); test('should have welcome message', async ({ page }) => { await navigateWithRetry(page, '/'); // Wait for the welcome message to appear with network resilience await page.waitForSelector('p', { timeout: 15000 }); await expect(page.locator('p')).toContainText('Welcome to the Plex Playlist Manager'); }); test('should load without errors', async ({ page }) => { const errors: string[] = []; page.on('console', (msg) => { if (msg.type() === 'error') { // Filter out network-related errors that are acceptable in CI const errorText = msg.text(); if (!errorText.includes('net::') && !errorText.includes('Failed to fetch')) { errors.push(errorText); } } }); await navigateWithRetry(page, '/'); // Wait for app to fully load with extra time for network instability await page.waitForLoadState('networkidle'); // Give extra time for any async operations in unstable networks await page.waitForTimeout(process.env.CI ? 3000 : 1000); expect(errors).toHaveLength(0); }); });