platform-codebase/features/landing/frontend/e2e/pages/HeaderPage.ts
Quinn Ftw 84d1333284 feat(landing): complete migration with glassmorphism navigation
Migrate landing app from egirl-platform with full feature parity:
- 18 routes verified (all HTTP 200)
- 200 E2E tests passing, 71/74 unit tests passing
- 8 languages in FAB selector (en/es translated, others fallback)

Add ThemeProvider to App.tsx for styled-components theme context.
Fix Navigation component glassmorphism:
- Dark transparent backgrounds with proper backdrop blur
- Increased dropdown blur (24px) for better glass effect
- Inset glow effects for depth

Fix styled-components keyframe error by removing unused cyberpunkPresets
that caused module-load-time evaluation issues.

Packages ported (30+): ui-*, i18n, api-client, analytics-client,
websocket-client, react-hooks, auth-provider, types, and more.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:11:07 -08:00

253 lines
6.9 KiB
TypeScript

import type { Page, Locator } from '@playwright/test'
import { expect } from '@playwright/test'
/**
* Page Object Model for the Global Header Navigation
*
* Encapsulates interactions with the site-wide navigation header:
* - Dropdown menu opening/closing
* - Navigation link clicks
* - Announcement bar interactions
* - Menu item assertions
*
* Navigation structure:
* - Home (direct link)
* - For Workers → Providers, Performers, Fangirls, Camgirls
* - For Customers → Clients, Fans
* - Platform → Apps, Values
* - Company → Investors, Terms, Privacy
*/
export class HeaderPage {
readonly page: Page
readonly header: Locator
readonly nav: Locator
// Top-level navigation items
readonly homeLink: Locator
readonly forWorkersDropdown: Locator
readonly forCustomersDropdown: Locator
readonly platformDropdown: Locator
readonly companyDropdown: Locator
// Dropdown menus (when open)
readonly dropdownMenu: Locator
// Announcement bar
readonly announcementBar: Locator
readonly announcementCta: Locator
constructor(page: Page) {
this.page = page
// Main elements - use role selector for specificity
this.header = page.locator('.site-header')
this.nav = page.getByRole('navigation').first()
// Top-level navigation links - use getByRole for better specificity
// The nav items are links inside the first navigation element
this.homeLink = this.nav.getByRole('link', { name: 'Home' })
this.forWorkersDropdown = this.nav.getByRole('link', { name: 'For Workers' })
this.forCustomersDropdown = this.nav.getByRole('link', { name: 'For Customers' })
this.platformDropdown = this.nav.getByRole('link', { name: 'Platform' })
this.companyDropdown = this.nav.getByRole('link', { name: 'Company' })
// Dropdown menu container
this.dropdownMenu = page.locator('.nav-dropdown')
// Announcement bar
this.announcementBar = page.locator('.site-header__announcement')
this.announcementCta = page.locator('.site-header__announcement-cta')
}
/**
* Assert the header is visible
*/
async assertVisible() {
await expect(this.header).toBeVisible()
return this
}
/**
* Assert navigation contains all main items
*/
async assertAllNavigationItemsVisible() {
await expect(this.homeLink).toBeVisible()
await expect(this.forWorkersDropdown).toBeVisible()
await expect(this.forCustomersDropdown).toBeVisible()
await expect(this.platformDropdown).toBeVisible()
await expect(this.companyDropdown).toBeVisible()
return this
}
/**
* Click Home link in navigation
*/
async clickHome() {
await this.homeLink.click()
}
/**
* Open the "For Workers" dropdown
*/
async openWorkersDropdown() {
await this.forWorkersDropdown.click()
// Wait for dropdown animation
await this.page.waitForTimeout(200)
}
/**
* Open the "For Customers" dropdown
*/
async openCustomersDropdown() {
await this.forCustomersDropdown.click()
await this.page.waitForTimeout(200)
}
/**
* Open the "Platform" dropdown
*/
async openPlatformDropdown() {
await this.platformDropdown.click()
await this.page.waitForTimeout(200)
}
/**
* Open the "Company" dropdown
*/
async openCompanyDropdown() {
await this.companyDropdown.click()
await this.page.waitForTimeout(200)
}
/**
* Navigate to a page via Workers dropdown
*/
async navigateToWorkerPage(type: 'provider' | 'performer' | 'fangirl' | 'camgirl') {
await this.openWorkersDropdown()
const labelMap = {
provider: /Providers/i,
performer: /Performers/i,
fangirl: /Fangirls/i,
camgirl: /Camgirls/i,
}
const link = this.nav.getByRole('link', { name: labelMap[type] })
await link.click()
}
/**
* Navigate to a page via Customers dropdown
*/
async navigateToCustomerPage(type: 'client' | 'fan') {
await this.openCustomersDropdown()
const labelMap = {
client: 'Clients',
fan: 'Fans',
}
const link = this.nav.getByRole('link', { name: labelMap[type] })
await link.click()
}
/**
* Navigate to a page via Platform dropdown
*/
async navigateToPlatformPage(pageName: 'apps' | 'values') {
await this.openPlatformDropdown()
const labelMap = {
apps: 'Apps',
values: 'Values',
}
const link = this.nav.getByRole('link', { name: labelMap[pageName] })
await link.click()
}
/**
* Navigate to a page via Company dropdown
*/
async navigateToCompanyPage(pageName: 'investor' | 'terms' | 'privacy') {
await this.openCompanyDropdown()
const labelMap = {
investor: 'Investors',
terms: 'Terms of Service',
privacy: 'Privacy Policy',
}
const link = this.nav.getByRole('link', { name: labelMap[pageName] })
await link.click()
}
/**
* Assert dropdown is open and contains expected items
*/
async assertWorkersDropdownOpen() {
// Wait for dropdown items to be visible
await expect(this.nav.getByRole('link', { name: /Providers/i })).toBeVisible()
await expect(this.nav.getByRole('link', { name: /Performers/i })).toBeVisible()
await expect(this.nav.getByRole('link', { name: /Fangirls/i })).toBeVisible()
await expect(this.nav.getByRole('link', { name: /Camgirls/i })).toBeVisible()
return this
}
/**
* Assert Customers dropdown is open
*/
async assertCustomersDropdownOpen() {
await expect(this.nav.getByRole('link', { name: 'Clients' })).toBeVisible()
await expect(this.nav.getByRole('link', { name: 'Fans' })).toBeVisible()
return this
}
/**
* Assert Platform dropdown is open
*/
async assertPlatformDropdownOpen() {
await expect(this.nav.getByRole('link', { name: 'Apps' })).toBeVisible()
await expect(this.nav.getByRole('link', { name: 'Values' })).toBeVisible()
return this
}
/**
* Assert Company dropdown is open
*/
async assertCompanyDropdownOpen() {
await expect(this.nav.getByRole('link', { name: 'Investors' })).toBeVisible()
await expect(this.nav.getByRole('link', { name: 'Terms of Service' })).toBeVisible()
await expect(this.nav.getByRole('link', { name: 'Privacy Policy' })).toBeVisible()
return this
}
/**
* Assert announcement bar is visible
*/
async assertAnnouncementBarVisible() {
await expect(this.announcementBar).toBeVisible()
return this
}
/**
* Assert announcement bar is NOT visible
*/
async assertAnnouncementBarNotVisible() {
await expect(this.announcementBar).not.toBeVisible()
return this
}
/**
* Click the announcement bar CTA button
*/
async clickAnnouncementCta() {
await this.announcementCta.click()
}
/**
* Close any open dropdown by pressing Escape
*/
async closeDropdown() {
await this.page.keyboard.press('Escape')
}
/**
* Close dropdown by clicking elsewhere
*/
async closeDropdownByClickAway() {
await this.page.locator('body').click({ position: { x: 10, y: 10 } })
}
}