Files
flights_web/tests/e2e-angular/integration/08 - online board - route.spec.ts
T
gnezim 20c19d15f4
CI / ci (push) Failing after 23s
Deploy / build-and-deploy (push) Failing after 5s
Add standalone API proxy via curl (bypasses WAF TLS fingerprinting)
Modern.js SSR intercepts all routes before any Express middleware,
so the API proxy runs as a separate Express server on port 8080.
Modern.js runs on 8081. The proxy uses curl subprocesses which go
through the system HTTPS proxy (GOST) with a proper TLS fingerprint
that the Aeroflot WAF accepts.

Usage: node scripts/dev-server.mjs (replaces pnpm dev for full-stack)

Also: remove stray e2e-angular test directory, fix env default to
same-origin /api.
2026-04-15 23:04:24 +03:00

909 lines
35 KiB
TypeScript

import { test, expect } from '@playwright/test';
import type { Page } from '@playwright/test';
import {
buildOnlineBoardPath,
buildRouteParam,
searchFlightByRoute,
verifyFlightCard,
generateFlight,
generateFlights,
getToday,
getTomorrow,
getYesterday,
getFutureDate,
getPastDate,
CITIES,
FIXTURES,
} from '../support/test-utilities';
const today = getToday();
const tomorrow = getTomorrow();
const yesterday = getYesterday();
const futureDate = getFutureDate(7);
const pastDate = getPastDate(7);
const dateParam = buildRouteParam('MOW', today);
const tomorrowParam = buildRouteParam('MOW', tomorrow);
// ============================================================================
// Online Board - Route Tests (30+ tests)
// ============================================================================
test.describe('Online Board - Route', () => {
test.describe('Category 1: Basic Route Search', () => {
test('Should search by departure and arrival city (manual input) (Test 1)', 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 search by cities from autocomplete list (Test 2)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'LED', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Saint Petersburg', 'Moscow');
const searchResults = page.locator('[data-testid="flight-card"]');
await expect(searchResults).toHaveCount(20);
});
test('Should search with today date (Test 3)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'AER', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Sochi', 'Moscow');
await expect(page).toHaveURL(/route\/AER-MOW-\d{8}/);
});
test('Should search with future date (Test 4)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', futureDate)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
await expect(page).toHaveURL(/route\/MOW-AER-\d{8}/);
});
test('Should search with past date and show validation (Test 5)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', pastDate)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
await expect(page).toHaveURL(/route\/MOW-AER-\d{8}/);
});
test('Should search without date and use today (Test 6)', async ({ page }) => {
await page.goto(`/ru-ru/onlineboard/departure/MOW`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
await expect(page).toHaveURL(/route\/MOW-AER-\d{8}/);
});
test('Should search with invalid cities and show error (Test 7)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'XXX', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Invalid City', 'Another Invalid City');
const errorState = page.locator('[data-testid="error-state"]');
await expect(errorState).toBeVisible();
});
test('Should search with same departure and arrival and show validation (Test 8)', async ({
page,
}) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill('Moscow');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const validationError = page.locator('[data-testid="validation-error"]');
await expect(validationError).toBeVisible();
});
});
test.describe('Category 2: Date Selection', () => {
test('Should select date from calendar (Test 9)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const calendarInput = page.locator('[data-testid="calendar-input"]');
await expect(calendarInput).toBeVisible();
});
test('Should select date range (Test 10)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const dateRange = page.locator('[data-testid="date-range"]');
await expect(dateRange).toBeVisible();
});
test('Should verify date format DD.MM.YYYY (Test 11)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const dateText = page.locator('[data-testid="board-date"]');
await expect(dateText).toBeVisible();
const dateValue = await dateText.textContent();
expect(dateValue).toMatch(/\d{2}\.\d{2}\.\d{4}/);
});
test('Should verify date validation min/max dates (Test 12)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const calendarInput = page.locator('[data-testid="calendar-input"]');
await expect(calendarInput).toBeEnabled();
});
test('Should select today date (Test 13)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const todayTab = page.locator(`[data-testid="date-tab-${today.replace(/-/g, '')}"]`);
await expect(todayTab).toBeVisible();
});
test('Should select tomorrow date (Test 14)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', tomorrow)}`);
await page.waitForLoadState('networkidle');
const tomorrowTab = page.locator(`[data-testid="date-tab-${tomorrow.replace(/-/g, '')}"]`);
await expect(tomorrowTab).toBeVisible();
});
});
test.describe('Category 3: Flight Results', () => {
test('Should verify flight results display (Test 15)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
test('Should verify flight count (Test 16)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCount = page.locator('[data-testid="flight-count"]');
await expect(flightCount).toBeVisible();
await expect(flightCount).toContainText('20');
});
test('Should verify flight details in results (Test 17)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 verify empty results message (Test 18)', 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 verify loading state (Test 19)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const loadingSpinner = page.locator('[data-testid="loading-spinner"]');
await expect(loadingSpinner).toBeVisible();
});
test('Should verify error state (Test 20)', async ({ page }) => {
await page.route('**/api/flights/**', (route) => {
return route.abort('internetdisconnected');
});
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const networkError = page.locator('[data-testid="network-error"]');
await expect(networkError).toBeVisible();
});
});
test.describe('Category 4: Flight Details', () => {
test('Should open flight details from results (Test 21)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await flightCard.click();
await page.waitForLoadState('networkidle');
await expect(page).toHaveURL(/\/ru-ru\/[A-Z]{2}\s?\d+-\d{8}/);
});
test('Should verify flight details content (Test 22)', async ({ page }) => {
const flight = generateFlight({ direction: 'departure', cityCode: 'MOW' });
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await flightCard.click();
await page.waitForLoadState('networkidle');
await expect(page.getByText(flight.flightNumber)).toBeVisible();
await expect(page.getByText(flight.airlineName)).toBeVisible();
});
test('Should verify flight route details (Test 23)', async ({ page }) => {
const flight = generateFlight({ direction: 'departure', cityCode: 'MOW' });
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await flightCard.click();
await page.waitForLoadState('networkidle');
await expect(page.getByText(flight.departure.cityName)).toBeVisible();
await expect(page.getByText(flight.arrival.cityName)).toBeVisible();
});
test('Should verify flight status details (Test 24)', async ({ page }) => {
const flight = generateFlight({
direction: 'departure',
cityCode: 'MOW',
status: 'scheduled',
});
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await flightCard.click();
await page.waitForLoadState('networkidle');
await expect(page.getByText(flight.status)).toBeVisible();
});
test('Should close flight details (Test 25)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await flightCard.click();
await page.waitForLoadState('networkidle');
const closeBtn = page.locator('[data-testid="close-details-btn"]');
await closeBtn.click();
await page.waitForLoadState('networkidle');
await expect(page).toHaveURL(/departure\/MOW-\d{8}/);
});
});
test.describe('Category 5: Edge Cases', () => {
test('Should search for non-existent cities (Test 26)', async ({ page }) => {
await page.goto(`/ru-ru/onlineboard/departure/XXX-${today.replace(/-/g, '')}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'NonExistent City', 'Another Fake City');
const errorState = page.locator('[data-testid="error-state"]');
await expect(errorState).toBeVisible();
});
test('Should search with special characters (Test 27)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('Moscow!@#$');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill('Sochi!@#$');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const noResults = page.locator('[data-testid="no-results"]');
await expect(noResults).toBeVisible();
});
test('Should search with very long city names (Test 28)', async ({ page }) => {
const longCityName = 'Москва'.repeat(10);
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill(longCityName);
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill(longCityName);
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
test('Should search with Unicode characters (Test 29)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('Moscow 🛫');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill('Sochi 🛬');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
test('Should handle rapid search attempts (Test 30)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
for (let i = 0; i < 5; i++) {
await departureInput.fill('Moscow');
await page.waitForTimeout(200);
await departureInput.press('Enter');
await page.waitForTimeout(200);
await arrivalInput.fill('Sochi');
await page.waitForTimeout(200);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
}
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
});
test.describe('Additional Route Tests', () => {
test('Should navigate to route board for different cities (Test 31)', async ({ page }) => {
const cities = ['MOW', 'LED', 'AER', 'OVB', 'KRR'];
for (const cityCode of cities) {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', cityCode, today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(
page,
CITIES.find((c) => c.code === cityCode)?.name || '',
'Sochi',
);
await expect(page).toHaveURL(new RegExp(`route/${cityCode}-AER-\\d{8}`));
}
});
test('Should display correct date in title (Test 32)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const dateText = page.locator('[data-testid="board-date"]');
await expect(dateText).toBeVisible();
await expect(dateText).toContainText(today);
});
test('Should filter by status (Test 33)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 (Test 34)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 display flight number (Test 35)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 (Test 36)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 and arrival cities (Test 37)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await expect(flightCard).toBeVisible();
const departureCity = flightCard.locator('[data-testid="departure-city"]');
const arrivalCity = flightCard.locator('[data-testid="arrival-city"]');
await expect(departureCity).toBeVisible();
await expect(arrivalCity).toBeVisible();
});
test('Should display scheduled departure time (Test 38)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 (Test 39)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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 (Test 40)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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('Should display actual departure time when available (Test 41)', async ({ page }) => {
const flight = generateFlight({
direction: 'departure',
cityCode: 'MOW',
status: 'departed',
});
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await expect(flightCard).toBeVisible();
const actualTime = flightCard.locator('[data-testid="actual-departure-time"]');
await expect(actualTime).toBeVisible();
});
test('Should display delay information (Test 42)', async ({ page }) => {
const flight = generateFlight({
direction: 'departure',
cityCode: 'MOW',
status: 'delayed',
});
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await expect(flightCard).toBeVisible();
const delayInfo = flightCard.locator('[data-testid="delay-info"]');
await expect(delayInfo).toBeVisible();
});
test('Should display terminal information (Test 43)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await expect(flightCard).toBeVisible();
const terminal = flightCard.locator('[data-testid="terminal"]');
await expect(terminal).toBeVisible();
});
test('Should display gate information (Test 44)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await expect(flightCard).toBeVisible();
const gate = flightCard.locator('[data-testid="gate"]');
await expect(gate).toBeVisible();
});
test('Should navigate to tomorrow date tab (Test 45)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
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(/departure\/MOW-\d{8}/);
}
});
test('Should handle invalid city code (Test 46)', async ({ page }) => {
await page.goto(`/ru-ru/onlineboard/departure/XXX-${today.replace(/-/g, '')}`);
await page.waitForLoadState('networkidle');
const errorState = page.locator('[data-testid="error-state"]');
await expect(errorState).toBeVisible();
});
test('Should handle network error (Test 47)', async ({ page }) => {
await page.route('**/api/flights/**', (route) => {
return route.abort('internetdisconnected');
});
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const networkError = page.locator('[data-testid="network-error"]');
await expect(networkError).toBeVisible();
});
test('Should have proper ARIA labels (Test 48)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCard = page.locator('[data-testid="flight-card"]').first();
await expect(flightCard).toHaveAttribute('role', 'article');
});
test('Should be keyboard navigable (Test 49)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
await page.keyboard.press('Tab');
const focusedElement = page.locator(':focus');
await expect(focusedElement).toBeVisible();
});
test('Should search by route with different date (Test 50)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', futureDate)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
await expect(page).toHaveURL(/route\/MOW-AER-\d{8}/);
});
test('Should search from Saint Petersburg to Moscow (Test 51)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'LED', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Saint Petersburg', 'Moscow');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
await expect(page).toHaveURL(/route\/LED-MOW-\d{8}/);
});
test('Should search from Sochi to Moscow (Test 52)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'AER', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Sochi', 'Moscow');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
await expect(page).toHaveURL(/route\/AER-MOW-\d{8}/);
});
test('Should search from Novosibirsk to Moscow (Test 53)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'OVB', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Novosibirsk', 'Moscow');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
await expect(page).toHaveURL(/route\/OVB-MOW-\d{8}/);
});
test('Should search from Krasnodar to Sochi (Test 54)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'KRR', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Krasnodar', 'Sochi');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
await expect(page).toHaveURL(/route\/KRR-AER-\d{8}/);
});
test('Should verify route information display (Test 55)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
await searchFlightByRoute(page, 'Moscow', 'Sochi');
const routeInfo = page.locator('[data-testid="route-info"]');
await expect(routeInfo).toBeVisible();
await expect(routeInfo).toContainText('Москва');
await expect(routeInfo).toContainText('Сочи');
});
test('Should search with empty departure city (Test 56)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('');
await page.waitForTimeout(500);
await arrivalInput.fill('Sochi');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const validationError = page.locator('[data-testid="validation-error"]');
await expect(validationError).toBeVisible();
});
test('Should search with empty arrival city (Test 57)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill('');
await page.waitForTimeout(500);
const validationError = page.locator('[data-testid="validation-error"]');
await expect(validationError).toBeVisible();
});
test('Should search with special Unicode characters (Test 58)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('Москва');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill('Сочи');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
test('Should search with mixed case city names (Test 59)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill('moscow');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill('sochi');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
test('Should search with leading/trailing spaces (Test 60)', async ({ page }) => {
await page.goto(`/ru-ru${buildOnlineBoardPath('departure', 'MOW', today)}`);
await page.waitForLoadState('networkidle');
const routeTab = page.locator('[data-testid="route-search-tab"]');
await routeTab.click();
await page.waitForTimeout(500);
const departureInput = page.locator('[data-testid="departure-city-input"]');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await departureInput.fill(' Moscow ');
await page.waitForTimeout(500);
await departureInput.press('Enter');
await page.waitForTimeout(500);
await arrivalInput.fill(' Sochi ');
await page.waitForTimeout(500);
await arrivalInput.press('Enter');
await page.waitForLoadState('networkidle');
const flightCards = page.locator('[data-testid="flight-card"]');
await expect(flightCards).toHaveCount(20);
});
});
});