Files
Clintchiz d402256547
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
First Init
2026-03-21 16:46:46 +05:30

70 lines
2.0 KiB
TypeScript

import { type Page, type Locator, expect } from '@playwright/test';
/**
* Page Object Model for Navigation
* Encapsulates header nav, footer nav, and mobile menu interactions
*/
export class NavigationPage {
readonly page: Page;
readonly header: Locator;
readonly footer: Locator;
readonly logo: Locator;
readonly mobileMenuButton: Locator;
readonly navLinks = {
home: '/href="/"',
about: '/about',
services: '/services',
portfolio: '/portfolio',
blog: '/blog',
contact: '/contact',
};
constructor(page: Page) {
this.page = page;
this.header = page.locator('header');
this.footer = page.locator('footer');
this.logo = page.locator('header a').first();
this.mobileMenuButton = page.locator('button[aria-label*="menu"], button[aria-expanded], [data-menu-toggle]').first();
}
async clickNavLink(path: string) {
await this.page.locator(`header a[href="${path}"]`).first().click();
await expect(this.page).toHaveURL(path);
}
async openMobileMenu() {
if (await this.mobileMenuButton.isVisible()) {
await this.mobileMenuButton.click();
await this.page.waitForTimeout(300); // Wait for animation
}
}
async closeMobileMenu() {
if (await this.mobileMenuButton.isVisible()) {
const isOpen = await this.mobileMenuButton.getAttribute('aria-expanded');
if (isOpen === 'true') {
await this.mobileMenuButton.click();
await this.page.waitForTimeout(300);
}
}
}
async scrollToFooter() {
await this.footer.scrollIntoViewIfNeeded();
await this.page.waitForTimeout(200);
}
async clickFooterLink(path: string) {
const link = this.footer.locator(`a[href="${path}"]`).first();
await link.click();
await expect(this.page).toHaveURL(path);
}
async verifyNoHorizontalOverflow(tolerance = 20) {
const bodyWidth = await this.page.evaluate(() => document.body.scrollWidth);
const viewportWidth = this.page.viewportSize()?.width ?? 1280;
expect(bodyWidth).toBeLessThanOrEqual(viewportWidth + tolerance);
}
}