import { test, expect } from '@playwright/test'; test.describe('Navigation Tests', () => { test('header navigation links work', async ({ page }) => { await page.goto('/'); // Check main nav links const navLinks = [ { text: 'About', path: '/about' }, { text: 'Services', path: '/services' }, { text: 'Portfolio', path: '/portfolio' }, { text: 'Blog', path: '/blog' }, { text: 'Contact', path: '/contact' }, ]; for (const link of navLinks) { await page.goto('/'); // Use getByRole for more reliable link selection const navLink = page.getByRole('link', { name: link.text, exact: true }).first(); if (await navLink.isVisible()) { await navLink.click(); await expect(page).toHaveURL(new RegExp(link.path)); } } }); test('logo links to home page', async ({ page }) => { await page.goto('/about'); const logo = page.locator('header a').first(); await logo.click(); await expect(page).toHaveURL('/'); }); test('footer links work', async ({ page }) => { await page.goto('/'); // Check footer quick links const footer = page.locator('footer'); await expect(footer).toBeVisible(); // Check privacy link in footer - use first() to handle multiple matches const privacyLink = footer.locator('a[href="/privacy"]').first(); if (await privacyLink.isVisible()) { await privacyLink.click(); await expect(page).toHaveURL('/privacy'); } await page.goto('/'); // Check terms link in footer - use first() to handle multiple matches const termsLink = page.locator('footer a[href="/terms"]').first(); if (await termsLink.isVisible()) { await termsLink.click(); await expect(page).toHaveURL('/terms'); } }); test('CTA button in header works', async ({ page }) => { await page.goto('/'); const ctaButton = page.locator('header a[href="/contact"], header button').first(); if (await ctaButton.isVisible()) { await ctaButton.click(); await expect(page).toHaveURL('/contact'); } }); }); test.describe('Mobile Navigation Tests', () => { test.use({ viewport: { width: 375, height: 667 } }); test('mobile menu toggle works', async ({ page }) => { await page.goto('/'); // Look for hamburger menu button const menuButton = page.locator('button[aria-label*="menu"], button[aria-expanded], [data-menu-toggle]').first(); if (await menuButton.isVisible()) { await menuButton.click(); // Wait for menu animation await page.waitForTimeout(300); // Check if mobile menu dialog/panel becomes visible const mobileMenu = page.locator('[role="dialog"], [class*="mobile"], nav.flex-1').first(); await expect(mobileMenu).toBeVisible(); } }); test('mobile navigation links work', async ({ page }) => { await page.goto('/'); // Try to open mobile menu first const menuButton = page.locator('button[aria-label*="menu"], button[aria-expanded], [data-menu-toggle]').first(); if (await menuButton.isVisible()) { await menuButton.click(); await page.waitForTimeout(300); // Wait for animation } // Check if About link works const aboutLink = page.locator('a[href="/about"]').first(); if (await aboutLink.isVisible()) { await aboutLink.click(); await expect(page).toHaveURL('/about'); } }); }); test.describe('Responsive Layout Tests', () => { const viewports = [ { name: 'mobile', width: 375, height: 667 }, { name: 'tablet', width: 768, height: 1024 }, { name: 'desktop', width: 1920, height: 1080 }, ]; for (const viewport of viewports) { test(`page renders correctly at ${viewport.name} size`, async ({ page }) => { await page.setViewportSize({ width: viewport.width, height: viewport.height }); await page.goto('/'); // Check header is visible const header = page.locator('header'); await expect(header).toBeVisible(); // Check main content area exists const main = page.locator('main'); await expect(main).toBeVisible(); // Check footer is visible const footer = page.locator('footer'); await expect(footer).toBeVisible(); // No horizontal overflow const bodyWidth = await page.evaluate(() => document.body.scrollWidth); expect(bodyWidth).toBeLessThanOrEqual(viewport.width + 20); // Small tolerance }); } });