Files
flights_web/tests/e2e-angular/integration/templates/schedule-search.template.ts
T
gnezim 375bcfb0fa Add e2e test suite from flights-front with Angular API mocks
Copies Playwright e2e tests (58 specs, 300+ tests) designed for cross-app
testing. Adapts API mocks to match real Aeroflot dictionary format (title
objects with multilingual keys), adds board/schedule/days endpoint mocks,
and provides Angular-specific Playwright config on port 4203.
2026-04-15 23:07:44 +03:00

428 lines
16 KiB
TypeScript

import { test, expect } from '@playwright/test';
import type { Page } from '@playwright/test';
import {
buildSchedulePath,
buildRouteParam,
generateScheduleEntry,
generateScheduleEntries,
getToday,
getTomorrow,
CITIES,
} from '../support/test-utilities';
const today = getToday();
const tomorrow = getTomorrow();
const dateFrom = today;
const dateTo = tomorrow;
// ============================================================================
// Schedule Search Tests
// ============================================================================
test.describe('Schedule Search', () => {
test.describe('Page Navigation', () => {
test('should navigate to schedule page', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
await expect(page).toHaveURL(/schedule/);
await expect(page).toHaveTitle(/Расписание/);
});
test('should navigate to schedule with pre-filled search', async ({ page }) => {
await page.goto(`/ru-ru/schedule?from=MOW&to=AER&dateFrom=${dateFrom}&dateTo=${dateTo}`);
await page.waitForLoadState('networkidle');
await expect(page).toHaveURL(/schedule/);
});
});
test.describe('Search Form', () => {
test('should display search form', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const form = page.locator('[data-testid="schedule-search-form"]');
await expect(form).toBeVisible();
});
test('should display departure city input', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await expect(departureInput).toBeVisible();
});
test('should display arrival city input', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await expect(arrivalInput).toBeVisible();
});
test('should display date range inputs', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const dateFromInput = page.locator('[data-testid="date-from-input"]');
await expect(dateFromInput).toBeVisible();
const dateToInput = page.locator('[data-testid="date-to-input"]');
await expect(dateToInput).toBeVisible();
});
test('should display search button', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const searchButton = page.locator('[data-testid="search-button"]');
await expect(searchButton).toBeVisible();
});
});
test.describe('Search Functionality', () => {
test('should search by departure and arrival cities', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const results = page.locator('[data-testid="schedule-entry"]');
await expect(results).toHaveCount(50);
});
test('should search with date range', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const dateFromInput = page.locator('[data-testid="date-from-input"]');
await dateFromInput.fill(dateFrom);
const dateToInput = page.locator('[data-testid="date-to-input"]');
await dateToInput.fill(dateTo);
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const results = page.locator('[data-testid="schedule-entry"]');
await expect(results).toHaveCount(50);
});
test('should show validation error for missing departure city', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
const error = page.locator('[data-testid="validation-error"]');
await expect(error).toBeVisible();
});
test('should show validation error for missing arrival city', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
const error = page.locator('[data-testid="validation-error"]');
await expect(error).toBeVisible();
});
test('should show no results when no schedules found', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Unknown City');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Unknown City');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const noResults = page.locator('[data-testid="no-results"]');
await expect(noResults).toBeVisible();
await expect(noResults).toContainText('Нет результатов');
});
});
test.describe('Schedule Entry Display', () => {
test('should display flight number', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const flightNumber = entry.locator('[data-testid="flight-number"]');
await expect(flightNumber).toBeVisible();
});
test('should display airline name', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const airlineName = entry.locator('[data-testid="airline-name"]');
await expect(airlineName).toBeVisible();
});
test('should display aircraft type', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const aircraftType = entry.locator('[data-testid="aircraft-type"]');
await expect(aircraftType).toBeVisible();
});
test('should display departure time', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const departureTime = entry.locator('[data-testid="departure-time"]');
await expect(departureTime).toBeVisible();
});
test('should display arrival time', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const arrivalTime = entry.locator('[data-testid="arrival-time"]');
await expect(arrivalTime).toBeVisible();
});
test('should display days of week', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const daysOfWeek = entry.locator('[data-testid="days-of-week"]');
await expect(daysOfWeek).toBeVisible();
});
test('should display effective date range', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entry = page.locator('[data-testid="schedule-entry"]').first();
await expect(entry).toBeVisible();
const dateRange = entry.locator('[data-testid="date-range"]');
await expect(dateRange).toBeVisible();
});
});
test.describe('Filtering', () => {
test('should filter by direct flights only', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const directFilter = page.locator('[data-testid="direct-filter"]');
await directFilter.click();
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entries = page.locator('[data-testid="schedule-entry"]');
await expect(entries).toHaveCount(50);
});
test('should filter by airline', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
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 departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
await page.waitForLoadState('networkidle');
const entries = page.locator('[data-testid="schedule-entry"]');
await expect(entries).toHaveCount(50);
});
});
test.describe('Error Handling', () => {
test('should handle invalid date format', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="departure-city-input"]');
await departureInput.fill('Moscow');
const arrivalInput = page.locator('[data-testid="arrival-city-input"]');
await arrivalInput.fill('Sochi');
const dateFromInput = page.locator('[data-testid="date-from-input"]');
await dateFromInput.fill('invalid-date');
const searchButton = page.locator('[data-testid="search-button"]');
await searchButton.click();
const error = page.locator('[data-testid="validation-error"]');
await expect(error).toBeVisible();
});
test('should handle network error', async ({ page }) => {
await page.route('**/api/schedule/**', (route) => {
return route.abort('internetdisconnected');
});
await page.goto(`/ru-ru${buildSchedulePath()}`);
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${buildSchedulePath()}`);
await page.waitForLoadState('networkidle');
const form = page.locator('[data-testid="schedule-search-form"]');
await expect(form).toHaveAttribute('role', 'form');
});
test('should be keyboard navigable', async ({ page }) => {
await page.goto(`/ru-ru${buildSchedulePath()}`);
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();
});
});
});