import { test, expect } from '@playwright/test'; import type { Page } from '@playwright/test'; import { buildFlightsMapPath, buildRouteParam, generateFlight, generateFlights, getToday, getTomorrow, CITIES, } from '@e2e/support/test-utilities'; const today = getToday(); const tomorrow = getTomorrow(); // ============================================================================ // Flights Map Tests // ============================================================================ test.describe('Flights Map', () => { test.describe('Page Navigation', () => { test('should navigate to flights map page', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); await expect(page).toHaveURL(/flights-map/); await expect(page).toHaveTitle(/Карта полетов/); }); test('should display map container', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const mapContainer = page.locator('[data-testid="map-container"]'); await expect(mapContainer).toBeVisible(); }); }); test.describe('Map Display', () => { test('should display flight markers', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const markers = page.locator('[data-testid="flight-marker"]'); await expect(markers).toHaveCount(20); }); test('should display flight popup on marker click', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const marker = page.locator('[data-testid="flight-marker"]').first(); await marker.click(); const popup = page.locator('[data-testid="flight-popup"]'); await expect(popup).toBeVisible(); }); test('should display flight details in popup', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const marker = page.locator('[data-testid="flight-marker"]').first(); await marker.click(); const flightNumber = page.locator('[data-testid="popup-flight-number"]'); await expect(flightNumber).toBeVisible(); }); test('should display route line between airports', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const routeLine = page.locator('[data-testid="route-line"]'); await expect(routeLine).toBeVisible(); }); }); test.describe('Filtering', () => { test('should filter by departure city', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const departureFilter = page.locator('[data-testid="departure-filter"]'); await departureFilter.click(); const moscowOption = page.locator('[data-testid="filter-option-MOW"]'); await moscowOption.click(); const markers = page.locator('[data-testid="flight-marker"]'); await expect(markers).toHaveCount(20); }); test('should filter by arrival city', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const arrivalFilter = page.locator('[data-testid="arrival-filter"]'); await arrivalFilter.click(); const sochiOption = page.locator('[data-testid="filter-option-AER"]'); await sochiOption.click(); const markers = page.locator('[data-testid="flight-marker"]'); await expect(markers).toHaveCount(20); }); test('should filter by status', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); 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 markers = page.locator('[data-testid="flight-marker"]'); await expect(markers).toHaveCount(20); }); test('should clear all filters', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const clearFilters = page.locator('[data-testid="clear-filters"]'); await clearFilters.click(); const markers = page.locator('[data-testid="flight-marker"]'); await expect(markers).toHaveCount(20); }); }); test.describe('Flight Details Panel', () => { test('should display flight details panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const panel = page.locator('[data-testid="flight-details-panel"]'); await expect(panel).toBeVisible(); }); test('should display flight number in panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const flightNumber = page.locator('[data-testid="panel-flight-number"]'); await expect(flightNumber).toBeVisible(); }); test('should display airline name in panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const airlineName = page.locator('[data-testid="panel-airline-name"]'); await expect(airlineName).toBeVisible(); }); test('should display departure and arrival cities in panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const departureCity = page.locator('[data-testid="panel-departure-city"]'); await expect(departureCity).toBeVisible(); const arrivalCity = page.locator('[data-testid="panel-arrival-city"]'); await expect(arrivalCity).toBeVisible(); }); test('should display scheduled times in panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const depTime = page.locator('[data-testid="panel-departure-time"]'); await expect(depTime).toBeVisible(); const arrTime = page.locator('[data-testid="panel-arrival-time"]'); await expect(arrTime).toBeVisible(); }); test('should display aircraft type in panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const aircraftType = page.locator('[data-testid="panel-aircraft-type"]'); await expect(aircraftType).toBeVisible(); }); test('should display flight status in panel', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const status = page.locator('[data-testid="panel-status"]'); await expect(status).toBeVisible(); }); }); test.describe('Map Controls', () => { test('should have zoom in button', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const zoomIn = page.locator('[data-testid="zoom-in"]'); await expect(zoomIn).toBeVisible(); }); test('should have zoom out button', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const zoomOut = page.locator('[data-testid="zoom-out"]'); await expect(zoomOut).toBeVisible(); }); test('should have full screen button', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const fullScreen = page.locator('[data-testid="full-screen"]'); await expect(fullScreen).toBeVisible(); }); test('should have layer toggle', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const layerToggle = page.locator('[data-testid="layer-toggle"]'); await expect(layerToggle).toBeVisible(); }); }); test.describe('Cluster Markers', () => { test('should display cluster markers for multiple flights', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const cluster = page.locator('[data-testid="cluster-marker"]'); if ((await cluster.count()) > 0) { await expect(cluster).toBeVisible(); } }); test('should expand cluster on click', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const cluster = page.locator('[data-testid="cluster-marker"]').first(); if ((await cluster.count()) > 0) { await cluster.click(); await page.waitForTimeout(500); const markers = page.locator('[data-testid="flight-marker"]'); await expect(markers).toHaveCount(20); } }); }); test.describe('Error Handling', () => { test('should handle network error', async ({ page }) => { await page.route('**/api/flights-map/**', (route) => { return route.abort('internetdisconnected'); }); await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const networkError = page.locator('[data-testid="network-error"]'); await expect(networkError).toBeVisible(); }); test('should handle map loading error', async ({ page }) => { await page.route('**/api/maps/**', (route) => { return route.abort('internetdisconnected'); }); await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const mapError = page.locator('[data-testid="map-error"]'); await expect(mapError).toBeVisible(); }); }); test.describe('Accessibility', () => { test('should have proper ARIA labels', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const mapContainer = page.locator('[data-testid="map-container"]'); await expect(mapContainer).toHaveAttribute('role', 'application'); }); test('should be keyboard navigable', async ({ page }) => { await page.goto(`/ru-ru${buildFlightsMapPath()}`); 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(); }); }); test.describe('Responsive Design', () => { test('should be responsive on mobile', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const mapContainer = page.locator('[data-testid="map-container"]'); await expect(mapContainer).toBeVisible(); }); test('should be responsive on tablet', async ({ page }) => { await page.setViewportSize({ width: 768, height: 1024 }); await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const mapContainer = page.locator('[data-testid="map-container"]'); await expect(mapContainer).toBeVisible(); }); test('should be responsive on desktop', async ({ page }) => { await page.setViewportSize({ width: 1920, height: 1080 }); await page.goto(`/ru-ru${buildFlightsMapPath()}`); await page.waitForLoadState('networkidle'); const mapContainer = page.locator('[data-testid="map-container"]'); await expect(mapContainer).toBeVisible(); }); }); });