import { test, expect } from '@playwright/test'; /** * Critical Path: Homepage Accessibility and Basic Functionality * * Tests the most critical user journey - accessing the homepage */ test.describe('Homepage', () => { test.beforeEach(async ({ page }) => { await page.goto('/'); }); test('should load homepage successfully', async ({ page }) => { // Check page loaded await expect(page).toHaveTitle(/michaelschiemer/i); // Check main content is visible await expect(page.locator('main')).toBeVisible(); }); test('should have valid HTML structure', async ({ page }) => { // Check essential meta tags const metaViewport = page.locator('meta[name="viewport"]'); await expect(metaViewport).toHaveAttribute('content', /width=device-width/); // Check for proper heading hierarchy const h1 = page.locator('h1').first(); await expect(h1).toBeVisible(); }); test('should have working navigation', async ({ page }) => { // Check navigation is present const nav = page.locator('nav').first(); await expect(nav).toBeVisible(); // Check navigation links are clickable const navLinks = page.locator('nav a'); const linkCount = await navLinks.count(); expect(linkCount).toBeGreaterThan(0); // First link should be clickable await expect(navLinks.first()).toBeVisible(); }); test('should load without JavaScript errors', async ({ page }) => { const errors: string[] = []; page.on('pageerror', (error) => { errors.push(error.message); }); await page.goto('/'); await page.waitForLoadState('networkidle'); // Assert no JavaScript errors expect(errors).toHaveLength(0); }); test('should have proper security headers', async ({ page }) => { const response = await page.goto('/'); // Check for security headers const headers = response?.headers(); expect(headers).toBeDefined(); if (headers) { // X-Frame-Options expect(headers['x-frame-options']).toBeDefined(); // X-Content-Type-Options expect(headers['x-content-type-options']).toBe('nosniff'); // Content-Security-Policy (if configured) // expect(headers['content-security-policy']).toBeDefined(); } }); test('should be responsive (mobile viewport)', async ({ page }) => { // Set mobile viewport await page.setViewportSize({ width: 375, height: 667 }); await page.goto('/'); // Check mobile menu is accessible const mobileMenu = page.locator('[data-mobile-menu], .mobile-menu, button[aria-label*="menu"]'); // Mobile menu should either be visible or exist in DOM const count = await mobileMenu.count(); expect(count).toBeGreaterThanOrEqual(0); }); test('should have accessible landmarks', async ({ page }) => { // Check for ARIA landmarks await expect(page.locator('[role="main"], main')).toBeVisible(); await expect(page.locator('[role="navigation"], nav')).toBeVisible(); // Footer should exist const footer = page.locator('[role="contentinfo"], footer'); await expect(footer).toBeVisible(); }); test('should load CSS and assets', async ({ page }) => { const response = await page.goto('/'); // Check status code expect(response?.status()).toBe(200); // Wait for all network requests to complete await page.waitForLoadState('networkidle'); // Check if stylesheets loaded const stylesheets = page.locator('link[rel="stylesheet"]'); const count = await stylesheets.count(); expect(count).toBeGreaterThan(0); // Verify at least one stylesheet is loaded const firstStylesheet = stylesheets.first(); await expect(firstStylesheet).toHaveAttribute('href', /.+/); }); });