Files
flights_web/tests/e2e-angular/integration/templates/flights-map.template.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

335 lines
12 KiB
TypeScript

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();
});
});
});