Files
michaelschiemer/tests/e2e/critical-paths/homepage.spec.ts
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

121 lines
3.7 KiB
TypeScript

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', /.+/);
});
});