Deploy to Production / Build & Verify (push) Failing after 5m56s
Ping Search Engines / Notify Search Engines (push) Successful in 2s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 2s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Smoke Tests (P0) (push) Failing after 11m26s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m42s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 12m2s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 16m14s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 17m45s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 25m23s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 20s
E2E Test Suite / Mobile Device Tests (push) Failing after 2h49m9s
Uptime Monitor / Health & Response Time (push) Failing after 2s
Uptime Monitor / SSL Certificate (push) Successful in 2s
Uptime Monitor / Send Alerts (push) Failing after 3s
Uptime Monitor / Record Uptime Success (push) Has been skipped
140 lines
4.4 KiB
TypeScript
140 lines
4.4 KiB
TypeScript
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
|
|
});
|
|
}
|
|
});
|