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

909 lines
34 KiB
TypeScript

import { test, expect } from '@playwright/test';
const BASE_URL = process.env.BASE_URL || 'http://localhost:5173';
test.describe('Flights Map (US-65 to US-69)', () => {
test.describe('US-65: Flights Map Tab Navigation', () => {
test('should navigate to flights map page from main board', async ({ page }) => {
// Navigate to main board
await page.goto(`${BASE_URL}/ru-ru/onlineboard`);
await page.waitForLoadState('networkidle');
// Look for flights map tab (third tab)
const flightsMapTab = page.locator('[data-testid="flights-map-tab"]');
if (await flightsMapTab.isVisible()) {
await flightsMapTab.click();
await page.waitForLoadState('networkidle');
// Verify URL changed to flights map
expect(page.url()).toContain('flights-map');
// Verify page title
const title = page.locator('h1');
await expect(title).toContainText(/map|карт/i);
}
});
test('should display map container on flights map page', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Check for map container
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
});
test('should display filter panel', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Check for filter panel
const filterPanel = page.locator('[data-testid="flights-map-filter"]');
await expect(filterPanel).toBeVisible();
});
test('should show loading state initially', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
// Page should load and display map
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible({ timeout: 10000 });
});
test('should have tab for flights map in navigation', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/onlineboard`);
await page.waitForLoadState('networkidle');
// Check if flights map tab exists in navigation
const tabNavigation = page.locator('[role="tablist"]');
if (await tabNavigation.isVisible()) {
const tabs = tabNavigation.locator('[role="tab"]');
const tabCount = await tabs.count();
expect(tabCount).toBeGreaterThanOrEqual(2); // At least Online Board and Schedule
}
});
test('should render page without console errors', async ({ page }) => {
const errors: string[] = [];
page.on('console', (msg) => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
expect(errors.filter((e) => !e.includes('sourcemap'))).toEqual([]);
});
});
test.describe('US-66: Route Display on Map', () => {
test('should display routes after selecting departure city', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Get departure input
const departureInput = page.locator('[data-testid="map-departure-input"]');
if (await departureInput.isVisible()) {
// Type departure city
await departureInput.fill('Moscow');
await page.waitForLoadState('networkidle');
// Select first suggestion
const suggestions = page.locator('[data-testid="city-suggestion"]');
if ((await suggestions.count()) > 0) {
await suggestions.first().click();
await page.waitForLoadState('networkidle');
// Verify map container still visible
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
}
}
});
test('should render polylines for routes', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Check for map svg (Leaflet renders routes as SVG)
const svgElements = page.locator('svg');
const svgCount = await svgElements.count();
expect(svgCount).toBeGreaterThan(0);
});
test('should apply color to routes', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Check for colored elements (polylines)
const svgPaths = page.locator('svg path');
const pathCount = await svgPaths.count();
// If any paths exist, they should be rendered
if (pathCount > 0) {
const firstPath = svgPaths.first();
const stroke = await firstPath.evaluate((el) => window.getComputedStyle(el).stroke);
expect(stroke).toBeTruthy();
}
});
test('should handle multiple routes', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
if (await departureInput.isVisible()) {
await departureInput.fill('Moscow');
await page.waitForLoadState('networkidle');
// Wait for suggestions
const suggestions = page.locator('[data-testid="city-suggestion"]');
if ((await suggestions.count()) > 0) {
await suggestions.first().click();
await page.waitForLoadState('networkidle');
// Map should display multiple routes
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
}
}
});
test('should update routes when filters change', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
// Change filter and verify map updates
const domesticToggle = page.locator('[data-testid="map-domestic-toggle"]');
if (await domesticToggle.isVisible()) {
await domesticToggle.click();
await page.waitForLoadState('networkidle');
// Map should still be visible after filter change
await expect(mapContainer).toBeVisible();
}
});
});
test.describe('US-67: Departure City Selection', () => {
test('should render departure city input', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await expect(departureInput).toBeVisible();
});
test('should show suggestions when typing in departure input', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Mos');
await page.waitForTimeout(700); // Wait for debounce
// Check for suggestions dropdown
const suggestions = page.locator('[data-testid="city-suggestion"]');
const count = await suggestions.count();
expect(count).toBeGreaterThan(0);
});
test('should filter suggestions by city name', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const suggestions = page.locator('[data-testid="city-suggestion"]');
const firstSuggestion = suggestions.first();
const text = await firstSuggestion.textContent();
expect(text?.toLowerCase()).toContain('moscow');
});
test('should support city code input', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('MOW');
await page.waitForTimeout(700);
const suggestions = page.locator('[data-testid="city-suggestion"]');
const count = await suggestions.count();
expect(count).toBeGreaterThan(0);
});
test('should select departure city from suggestions', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const suggestions = page.locator('[data-testid="city-suggestion"]');
if ((await suggestions.count()) > 0) {
await suggestions.first().click();
await page.waitForLoadState('networkidle');
// Input should contain selected city
const inputValue = await departureInput.inputValue();
expect(inputValue.length).toBeGreaterThan(0);
}
});
test('should require departure city', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
const required = await departureInput.evaluate((el: HTMLInputElement) => el.required);
expect(required).toBe(true);
});
});
test.describe('US-68: Arrival City Selection', () => {
test('should render arrival city input', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const arrivalInput = page.locator('[data-testid="map-arrival-input"]');
await expect(arrivalInput).toBeVisible();
});
test('should show suggestions when typing in arrival input', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// First select departure city
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const depSuggestions = page.locator('[data-testid="city-suggestion"]');
if ((await depSuggestions.count()) > 0) {
await depSuggestions.first().click();
await page.waitForLoadState('networkidle');
// Now type in arrival input
const arrivalInput = page.locator('[data-testid="map-arrival-input"]');
await arrivalInput.fill('Par');
await page.waitForTimeout(700);
const arrivalSuggestions = page.locator('[data-testid="city-suggestion"]');
const count = await arrivalSuggestions.count();
expect(count).toBeGreaterThan(0);
}
});
test('should filter suggestions by arrival city name', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const suggestions = page.locator('[data-testid="city-suggestion"]');
if ((await suggestions.count()) > 0) {
await suggestions.first().click();
const arrivalInput = page.locator('[data-testid="map-arrival-input"]');
await arrivalInput.fill('Paris');
await page.waitForTimeout(700);
const arrivalSuggestions = page.locator('[data-testid="city-suggestion"]');
if ((await arrivalSuggestions.count()) > 0) {
const text = await arrivalSuggestions.first().textContent();
expect(text?.toLowerCase()).toContain('par');
}
}
});
test('should support arrival city code', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const suggestions = page.locator('[data-testid="city-suggestion"]');
if ((await suggestions.count()) > 0) {
await suggestions.first().click();
const arrivalInput = page.locator('[data-testid="map-arrival-input"]');
await arrivalInput.fill('CDG');
await page.waitForTimeout(700);
const arrivalSuggestions = page.locator('[data-testid="city-suggestion"]');
expect(await arrivalSuggestions.count()).toBeGreaterThan(0);
}
});
test('should select arrival city and display route', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const depSuggestions = page.locator('[data-testid="city-suggestion"]');
if ((await depSuggestions.count()) > 0) {
await depSuggestions.first().click();
const arrivalInput = page.locator('[data-testid="map-arrival-input"]');
await arrivalInput.fill('Paris');
await page.waitForTimeout(700);
const arrivalSuggestions = page.locator('[data-testid="city-suggestion"]');
if ((await arrivalSuggestions.count()) > 0) {
await arrivalSuggestions.first().click();
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
}
}
});
});
test.describe('US-69: Swap Cities Button', () => {
test('should display swap button between city inputs', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const swapButton = page.locator('[data-testid="swap-button"]');
await expect(swapButton).toBeVisible();
});
test('should swap cities when button is clicked', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
const arrivalInput = page.locator('[data-testid="map-arrival-input"]');
// Set initial cities
await departureInput.fill('Moscow');
await page.waitForTimeout(700);
const depSuggestions = page.locator('[data-testid="city-suggestion"]');
if ((await depSuggestions.count()) > 0) {
await depSuggestions.first().click();
await arrivalInput.fill('Paris');
await page.waitForTimeout(700);
const arrivalSuggestions = page.locator('[data-testid="city-suggestion"]');
if ((await arrivalSuggestions.count()) > 0) {
await arrivalSuggestions.first().click();
// Click swap button
const swapButton = page.locator('[data-testid="swap-button"]');
await swapButton.click();
await page.waitForLoadState('networkidle');
const depAfter = await departureInput.inputValue();
const arrAfter = await arrivalInput.inputValue();
// Cities should be swapped (approximately)
expect(depAfter.length).toBeGreaterThan(0);
expect(arrAfter.length).toBeGreaterThan(0);
}
}
});
test('should be keyboard accessible', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const swapButton = page.locator('[data-testid="swap-button"]');
// Focus on button
await swapButton.focus();
// Press Enter
await page.keyboard.press('Enter');
await page.waitForLoadState('networkidle');
// Page should still be functional
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
});
test('should be mobile-friendly size', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const swapButton = page.locator('[data-testid="swap-button"]');
await expect(swapButton).toBeVisible();
// Get button size
const box = await swapButton.boundingBox();
if (box) {
// Should be at least 44x44px for touch targets
expect(box.width).toBeGreaterThanOrEqual(40);
expect(box.height).toBeGreaterThanOrEqual(40);
}
});
test('should have accessible label', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const swapButton = page.locator('[data-testid="swap-button"]');
const ariaLabel = await swapButton.getAttribute('aria-label');
expect(ariaLabel).toBeTruthy();
});
});
test.describe('US-65-69: Responsive Design', () => {
test('should be responsive on mobile (375px)', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
const filterPanel = page.locator('[data-testid="flights-map-filter"]');
await expect(filterPanel).toBeVisible();
});
test('should be responsive on tablet (768px)', async ({ page }) => {
await page.setViewportSize({ width: 768, height: 1024 });
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
});
test('should be responsive on desktop (1440px)', async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 });
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
});
});
test.describe('US-65-69: Localization', () => {
test('should work in Russian locale (ru-ru)', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
});
test('should work in English locale (en-us)', async ({ page }) => {
await page.goto(`${BASE_URL}/en-us/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
});
});
test.describe('US-65-69: Accessibility', () => {
test('should render without accessibility violations', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Check for proper heading hierarchy
const heading = page.locator('h1');
await expect(heading).toBeVisible();
});
test('should be keyboard navigable', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Tab through interactive elements
await page.keyboard.press('Tab');
let focusedElement = await page.evaluate(() => document.activeElement?.tagName);
expect(['INPUT', 'BUTTON', 'A', 'SELECT']).toContain(focusedElement);
await page.keyboard.press('Tab');
focusedElement = await page.evaluate(() => document.activeElement?.tagName);
expect(['INPUT', 'BUTTON', 'A', 'SELECT']).toContain(focusedElement);
});
test('should have proper labels', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const departureInput = page.locator('[data-testid="map-departure-input"]');
const hasLabel = await departureInput.evaluate(
(el: HTMLInputElement) =>
el.placeholder || el.getAttribute('aria-label') || el.parentElement?.textContent,
);
expect(hasLabel).toBeTruthy();
});
});
test.describe('US-70: Zoom Functionality', () => {
test('should display zoom controls on map', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const zoomControl = page.locator('[data-testid="zoom-control"]');
await expect(zoomControl).toBeVisible();
const zoomInBtn = page.locator('[data-testid="zoom-in-button"]');
const zoomOutBtn = page.locator('[data-testid="zoom-out-button"]');
await expect(zoomInBtn).toBeVisible();
await expect(zoomOutBtn).toBeVisible();
});
test('should allow zooming in and out', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const zoomLevel = page.locator('[data-testid="zoom-level-display"]');
const initialZoom = await zoomLevel.textContent();
const zoomInBtn = page.locator('[data-testid="zoom-in-button"]');
await zoomInBtn.click();
await page.waitForTimeout(200);
const newZoom = await zoomLevel.textContent();
expect(parseInt(newZoom!)).toBeGreaterThan(parseInt(initialZoom!));
});
test('should enforce minimum zoom level (3)', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const zoomOutBtn = page.locator('[data-testid="zoom-out-button"]');
// Keep clicking zoom out until disabled
for (let i = 0; i < 5; i++) {
if (await zoomOutBtn.isDisabled()) {
break;
}
await zoomOutBtn.click();
await page.waitForTimeout(100);
}
// Button should be disabled at minimum zoom
await expect(zoomOutBtn).toBeDisabled();
});
test('should enforce maximum zoom level (6)', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const zoomInBtn = page.locator('[data-testid="zoom-in-button"]');
// Keep clicking zoom in until disabled
for (let i = 0; i < 5; i++) {
if (await zoomInBtn.isDisabled()) {
break;
}
await zoomInBtn.click();
await page.waitForTimeout(100);
}
// Button should be disabled at maximum zoom
await expect(zoomInBtn).toBeDisabled();
});
});
test.describe('US-71: Domestic Flights Filter', () => {
test('should display domestic filter toggle', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const domesticToggle = page.locator('[data-testid="toggle-domestic"]');
await expect(domesticToggle).toBeVisible();
});
test('should toggle domestic flights filter', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const domesticToggle = page.locator('[data-testid="toggle-domestic"]');
const isCheckedBefore = await domesticToggle.isChecked();
await domesticToggle.click();
await page.waitForTimeout(300);
const isCheckedAfter = await domesticToggle.isChecked();
expect(isCheckedAfter).toBe(!isCheckedBefore);
});
});
test.describe('US-72: International Flights Filter', () => {
test('should display international filter toggle', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const internationalToggle = page.locator('[data-testid="toggle-international"]');
await expect(internationalToggle).toBeVisible();
});
test('should toggle international flights filter', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const internationalToggle = page.locator('[data-testid="toggle-international"]');
const isCheckedBefore = await internationalToggle.isChecked();
await internationalToggle.click();
await page.waitForTimeout(300);
const isCheckedAfter = await internationalToggle.isChecked();
expect(isCheckedAfter).toBe(!isCheckedBefore);
});
});
test.describe('US-73: Connecting Flights Filter', () => {
test('should display connecting filter toggle', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const connectingToggle = page.locator('[data-testid="toggle-connecting"]');
await expect(connectingToggle).toBeVisible();
});
test('should toggle connecting flights filter', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const connectingToggle = page.locator('[data-testid="toggle-connecting"]');
const isCheckedBefore = await connectingToggle.isChecked();
await connectingToggle.click();
await page.waitForTimeout(300);
const isCheckedAfter = await connectingToggle.isChecked();
expect(isCheckedAfter).toBe(!isCheckedBefore);
});
});
test.describe('US-74: Panning', () => {
test('should allow map panning with mouse drag', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
const box = await mapContainer.boundingBox();
if (box) {
// Drag from center right to center left
await page.mouse.move(box.x + box.width * 0.7, box.y + box.height * 0.5);
await page.mouse.down();
await page.mouse.move(box.x + box.width * 0.3, box.y + box.height * 0.5);
await page.mouse.up();
await page.waitForTimeout(200);
// Map should still be visible (not broken by pan)
await expect(mapContainer).toBeVisible();
}
});
test('should prevent panning beyond world bounds', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
// Map should maintain bounds
const pageContent = await page.content();
expect(pageContent).toContain('map-container');
});
});
test.describe('US-75: Route Popup on Selection', () => {
test('should display route popup when route is clicked', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Search for a route first
const departureInput = page.locator('[data-testid="map-departure-input"]');
if (await departureInput.isVisible()) {
await departureInput.fill('Moscow');
await page.waitForTimeout(500);
const suggestions = page.locator('[data-testid="city-suggestion"]');
if ((await suggestions.count()) > 0) {
await suggestions.first().click();
await page.waitForLoadState('networkidle');
// Check if popup appears after searching
const popup = page.locator('[data-testid="route-popup"]');
// Popup may or may not be visible depending on implementation
// Just verify the map is still functional
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
}
}
});
test('should display route details in popup', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const mapContainer = page.locator('[data-testid="map-container"]');
await expect(mapContainer).toBeVisible();
// Popup structure should exist in DOM
const popup = page.locator('[data-testid="route-popup"]');
// Verify popup structure exists
if (await popup.isVisible()) {
const departure = popup.locator('[data-testid="popup-departure"]');
const arrival = popup.locator('[data-testid="popup-arrival"]');
await expect(departure).toBeTruthy();
await expect(arrival).toBeTruthy();
}
});
test('should close popup with close button', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const popup = page.locator('[data-testid="route-popup"]');
const closeButton = page.locator('[data-testid="popup-close-button"]');
// If popup is visible, close button should work
if (await popup.isVisible()) {
await closeButton.click();
await page.waitForTimeout(200);
// Popup should be hidden
const isHidden = await popup.evaluate(
(el) => window.getComputedStyle(el).display === 'none',
);
expect(isHidden || !(await popup.isVisible())).toBeTruthy();
}
});
test('should close popup on ESC key', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const popup = page.locator('[data-testid="route-popup"]');
if (await popup.isVisible()) {
await page.keyboard.press('Escape');
await page.waitForTimeout(200);
// Popup should be hidden
const isHidden = await popup.evaluate(
(el) => window.getComputedStyle(el).display === 'none',
);
expect(isHidden || !(await popup.isVisible())).toBeTruthy();
}
});
test('should display flight count in popup', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const popup = page.locator('[data-testid="route-popup"]');
if (await popup.isVisible()) {
const flightCount = popup.locator('[data-testid="popup-flight-count"]');
const text = await flightCount.textContent();
// Should contain a number
expect(text).toMatch(/\d+/);
}
});
test('should maintain popup position on map', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const popup = page.locator('[data-testid="route-popup"]');
const mapContainer = page.locator('[data-testid="map-container"]');
if (await popup.isVisible()) {
const popupBox = await popup.boundingBox();
const mapBox = await mapContainer.boundingBox();
if (popupBox && mapBox) {
// Popup should be within or near map container
expect(popupBox.x).toBeGreaterThanOrEqual(mapBox.x - 100);
expect(popupBox.y).toBeGreaterThanOrEqual(mapBox.y - 100);
}
}
});
});
test.describe('US-70-75: Integration Tests', () => {
test('should maintain zoom level when filters change', async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const zoomLevel = page.locator('[data-testid="zoom-level-display"]');
const initialZoom = await zoomLevel.textContent();
const domesticToggle = page.locator('[data-testid="toggle-domestic"]');
await domesticToggle.click();
await page.waitForTimeout(300);
const zoomAfterFilter = await zoomLevel.textContent();
expect(zoomAfterFilter).toBe(initialZoom);
});
test('should work across locales (ru-ru and en-us)', async ({ page }) => {
// Test ru-ru locale
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
let zoomControl = page.locator('[data-testid="zoom-control"]');
await expect(zoomControl).toBeVisible();
// Test en-us locale
await page.goto(`${BASE_URL}/en-us/flights-map`);
await page.waitForLoadState('networkidle');
zoomControl = page.locator('[data-testid="zoom-control"]');
await expect(zoomControl).toBeVisible();
const filters = page.locator('[data-testid="filter-toggles"]');
await expect(filters).toBeVisible();
});
test('should render without console errors', async ({ page }) => {
const errors: string[] = [];
page.on('console', (msg) => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
// Perform zoom action
const zoomInBtn = page.locator('[data-testid="zoom-in-button"]');
await zoomInBtn.click();
// Toggle a filter
const domesticToggle = page.locator('[data-testid="toggle-domestic"]');
await domesticToggle.click();
await page.waitForTimeout(300);
const filteredErrors = errors.filter((e) => !e.includes('sourcemap'));
expect(filteredErrors).toEqual([]);
});
test('should be responsive on mobile', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await page.goto(`${BASE_URL}/ru-ru/flights-map`);
await page.waitForLoadState('networkidle');
const zoomControl = page.locator('[data-testid="zoom-control"]');
const filters = page.locator('[data-testid="filter-toggles"]');
await expect(zoomControl).toBeVisible();
await expect(filters).toBeVisible();
// Verify zoom buttons work on mobile
const zoomInBtn = page.locator('[data-testid="zoom-in-button"]');
await zoomInBtn.click();
// Verify filters work on mobile
const domesticToggle = page.locator('[data-testid="toggle-domestic"]');
await domesticToggle.click();
await page.waitForTimeout(300);
});
});
});