import { test, expect } from '@playwright/test'; import type { Page } from '@playwright/test'; import { buildOnlineBoardPath, buildRouteParam, searchFlightByRoute, verifyFlightCard, generateFlight, generateFlights, getToday, getTomorrow, CITIES, } from '../support/test-utilities'; const today = getToday(); const tomorrow = getTomorrow(); const dateParam = buildRouteParam('MOW', today); const tomorrowParam = buildRouteParam('MOW', tomorrow); // ============================================================================ // Online Board - Route Tests // ============================================================================ test.describe('Online Board - Route', () => { test.describe('Page Navigation', () => { test('should navigate to route board for Moscow to Sochi', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/route\/MOW-AER-\d{8}/); await expect(page).toHaveTitle(/Москва - Сочи/); }); test('should navigate to route board for Saint Petersburg to Moscow', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/LED-MOW-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/route\/LED-MOW-\d{8}/); }); test('should navigate to route board for Novosibirsk to Moscow', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/OVB-MOW-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/route\/OVB-MOW-\d{8}/); }); }); test.describe('Route Search', () => { test('should search route by departure and arrival cities', async ({ page }) => { await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`); await page.waitForLoadState('networkidle'); await searchFlightByRoute(page, 'Moscow', 'Sochi'); const searchResults = page.locator('[data-testid="flight-card"]'); await expect(searchResults).toHaveCount(20); }); test('should show no results when route not found', async ({ page }) => { await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`); await page.waitForLoadState('networkidle'); await searchFlightByRoute(page, 'Moscow', 'Unknown City'); const noResults = page.locator('[data-testid="no-results"]'); await expect(noResults).toBeVisible(); await expect(noResults).toContainText('Нет результатов'); }); test('should validate departure city', async ({ page }) => { await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`); await page.waitForLoadState('networkidle'); await searchFlightByRoute(page, '', 'Sochi'); const error = page.locator('[data-testid="validation-error"]'); await expect(error).toBeVisible(); }); test('should validate arrival city', async ({ page }) => { await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`); await page.waitForLoadState('networkidle'); await searchFlightByRoute(page, 'Moscow', ''); const error = page.locator('[data-testid="validation-error"]'); await expect(error).toBeVisible(); }); }); test.describe('Flight Display', () => { test('should display flights for selected route', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCards = page.locator('[data-testid="flight-card"]'); await expect(flightCards).toHaveCount(20); }); test('should display route information', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const routeInfo = page.locator('[data-testid="route-info"]'); await expect(routeInfo).toBeVisible(); await expect(routeInfo).toContainText('Москва'); await expect(routeInfo).toContainText('Сочи'); }); test('should display flight count', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCount = page.locator('[data-testid="flight-count"]'); await expect(flightCount).toBeVisible(); }); }); test.describe('Date Navigation', () => { test('should navigate to tomorrow', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const dateTab = page.locator(`[data-testid="date-tab-${tomorrow.replace(/-/g, '')}"]`); if ((await dateTab.count()) > 0) { await dateTab.click(); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/route\/MOW-AER-\d{8}/); } }); test('should display correct date in title', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const dateText = page.locator('[data-testid="board-date"]'); await expect(dateText).toBeVisible(); }); }); test.describe('Filtering', () => { test('should filter by status', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const statusFilter = page.locator('[data-testid="status-filter"]'); await statusFilter.click(); const scheduledOption = page.locator('[data-testid="filter-option-scheduled"]'); await scheduledOption.click(); const filteredFlights = page.locator('[data-testid="flight-card"]'); await expect(filteredFlights).toHaveCount(20); }); test('should filter by airline', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const airlineFilter = page.locator('[data-testid="airline-filter"]'); await airlineFilter.click(); const aeroflotOption = page.locator('[data-testid="filter-option-SU"]'); await aeroflotOption.click(); const filteredFlights = page.locator('[data-testid="flight-card"]'); await expect(filteredFlights).toHaveCount(20); }); test('should filter by time range', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const timeFilter = page.locator('[data-testid="time-filter"]'); await timeFilter.click(); const timeOption = page.locator('[data-testid="filter-option-morning"]'); await timeOption.click(); const filteredFlights = page.locator('[data-testid="flight-card"]'); await expect(filteredFlights).toHaveCount(20); }); }); test.describe('Flight Card', () => { test('should display flight number', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const flightNumber = flightCard.locator('[data-testid="flight-number"]'); await expect(flightNumber).toBeVisible(); }); test('should display airline name', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const airlineName = flightCard.locator('[data-testid="airline-name"]'); await expect(airlineName).toBeVisible(); }); test('should display departure city', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const departureCity = flightCard.locator('[data-testid="departure-city"]'); await expect(departureCity).toBeVisible(); }); test('should display arrival city', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const arrivalCity = flightCard.locator('[data-testid="arrival-city"]'); await expect(arrivalCity).toBeVisible(); }); test('should display scheduled departure time', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const depTime = flightCard.locator('[data-testid="scheduled-departure-time"]'); await expect(depTime).toBeVisible(); }); test('should display scheduled arrival time', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const arrTime = flightCard.locator('[data-testid="scheduled-arrival-time"]'); await expect(arrTime).toBeVisible(); }); test('should display flight duration', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toBeVisible(); const duration = flightCard.locator('[data-testid="flight-duration"]'); await expect(duration).toBeVisible(); }); }); test.describe('Error Handling', () => { test('should handle invalid route parameters', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/XXX-YYY-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const errorState = page.locator('[data-testid="error-state"]'); await expect(errorState).toBeVisible(); }); test('should handle network error', async ({ page }) => { await page.route('**/api/flights/**', (route) => { return route.abort('internetdisconnected'); }); await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const networkError = page.locator('[data-testid="network-error"]'); await expect(networkError).toBeVisible(); }); }); test.describe('Accessibility', () => { test('should have proper ARIA labels', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); const flightCard = page.locator('[data-testid="flight-card"]').first(); await expect(flightCard).toHaveAttribute('role', 'article'); }); test('should be keyboard navigable', async ({ page }) => { await page.goto(`/ru-ru/onlineboard/route/MOW-AER-${today.replace(/-/g, '')}`); await page.waitForLoadState('networkidle'); await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); const focusedElement = page.locator(':focus'); await expect(focusedElement).toBeVisible(); }); }); });