375bcfb0fa
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.
302 lines
11 KiB
TypeScript
302 lines
11 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import type { Page } from '@playwright/test';
|
|
import {
|
|
buildRouteParam,
|
|
generateDestination,
|
|
generateDestinations,
|
|
getToday,
|
|
getTomorrow,
|
|
CITIES,
|
|
} from '@e2e/support/test-utilities';
|
|
|
|
const today = getToday();
|
|
const tomorrow = getTomorrow();
|
|
|
|
// ============================================================================
|
|
// Popular Requests Tests
|
|
// ============================================================================
|
|
|
|
test.describe('Popular Requests', () => {
|
|
test.describe('Page Navigation', () => {
|
|
test('should display popular requests section', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const popularRequests = page.locator('[data-testid="popular-requests"]');
|
|
await expect(popularRequests).toBeVisible();
|
|
});
|
|
|
|
test('should display popular requests title', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const title = page.locator('[data-testid="popular-requests-title"]');
|
|
await expect(title).toBeVisible();
|
|
await expect(title).toContainText('Популярные направления');
|
|
});
|
|
});
|
|
|
|
test.describe('Request Display', () => {
|
|
test('should display departure city', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await expect(request).toBeVisible();
|
|
|
|
const departureCity = request.locator('[data-testid="request-departure-city"]');
|
|
await expect(departureCity).toBeVisible();
|
|
});
|
|
|
|
test('should display arrival city', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await expect(request).toBeVisible();
|
|
|
|
const arrivalCity = request.locator('[data-testid="request-arrival-city"]');
|
|
await expect(arrivalCity).toBeVisible();
|
|
});
|
|
|
|
test('should display flight count', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await expect(request).toBeVisible();
|
|
|
|
const flightCount = request.locator('[data-testid="request-flight-count"]');
|
|
await expect(flightCount).toBeVisible();
|
|
});
|
|
|
|
test('should display date range', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await expect(request).toBeVisible();
|
|
|
|
const dateRange = request.locator('[data-testid="request-date-range"]');
|
|
await expect(dateRange).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Request Interaction', () => {
|
|
test('should navigate to flight board on click', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await request.click();
|
|
|
|
await expect(page).toHaveURL(/onlineboard\/departure\/MOW-\d{8}/);
|
|
});
|
|
|
|
test('should navigate to flight board with correct city', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await request.click();
|
|
|
|
await expect(page).toHaveURL(/onlineboard\/departure\/[A-Z]{3}-\d{8}/);
|
|
});
|
|
|
|
test('should open flight board for arrival direction', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const request = page.locator('[data-testid="popular-request"]').first();
|
|
await request.click();
|
|
|
|
await expect(page).toHaveURL(/onlineboard\/arrival\/[A-Z]{3}-\d{8}/);
|
|
});
|
|
});
|
|
|
|
test.describe('Request Sorting', () => {
|
|
test('should sort by flight count', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const sortButton = page.locator('[data-testid="sort-button"]');
|
|
await sortButton.click();
|
|
|
|
const sortOption = page.locator('[data-testid="sort-option-flight-count"]');
|
|
await sortOption.click();
|
|
|
|
const requests = page.locator('[data-testid="popular-request"]');
|
|
const count1 = await requests
|
|
.nth(0)
|
|
.locator('[data-testid="request-flight-count"]')
|
|
.textContent();
|
|
const count2 = await requests
|
|
.nth(1)
|
|
.locator('[data-testid="request-flight-count"]')
|
|
.textContent();
|
|
|
|
if (count1 && count2) {
|
|
expect(parseInt(count1.replace(/\D/g, ''))).toBeGreaterThanOrEqual(
|
|
parseInt(count2.replace(/\D/g, '')),
|
|
);
|
|
}
|
|
});
|
|
|
|
test('should sort by date', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const sortButton = page.locator('[data-testid="sort-button"]');
|
|
await sortButton.click();
|
|
|
|
const sortOption = page.locator('[data-testid="sort-option-date"]');
|
|
await sortOption.click();
|
|
|
|
const requests = page.locator('[data-testid="popular-request"]');
|
|
await expect(requests).toHaveCount(20);
|
|
});
|
|
});
|
|
|
|
test.describe('Request Filtering', () => {
|
|
test('should filter by departure city', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const filterInput = page.locator('[data-testid="filter-input"]');
|
|
await filterInput.fill('Moscow');
|
|
|
|
const requests = page.locator('[data-testid="popular-request"]');
|
|
await expect(requests).toHaveCount(20);
|
|
});
|
|
|
|
test('should clear filter', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const filterInput = page.locator('[data-testid="filter-input"]');
|
|
await filterInput.fill('Moscow');
|
|
|
|
const clearButton = page.locator('[data-testid="clear-filter"]');
|
|
await clearButton.click();
|
|
|
|
const requests = page.locator('[data-testid="popular-request"]');
|
|
await expect(requests).toHaveCount(20);
|
|
});
|
|
});
|
|
|
|
test.describe('Request Pagination', () => {
|
|
test('should display pagination controls', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const pagination = page.locator('[data-testid="pagination"]');
|
|
await expect(pagination).toBeVisible();
|
|
});
|
|
|
|
test('should navigate to next page', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const nextButton = page.locator('[data-testid="pagination-next"]');
|
|
await nextButton.click();
|
|
|
|
const requests = page.locator('[data-testid="popular-request"]');
|
|
await expect(requests).toHaveCount(20);
|
|
});
|
|
|
|
test('should navigate to previous page', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const nextButton = page.locator('[data-testid="pagination-next"]');
|
|
await nextButton.click();
|
|
|
|
const prevButton = page.locator('[data-testid="pagination-prev"]');
|
|
await prevButton.click();
|
|
|
|
const requests = page.locator('[data-testid="popular-request"]');
|
|
await expect(requests).toHaveCount(20);
|
|
});
|
|
});
|
|
|
|
test.describe('Error Handling', () => {
|
|
test('should handle network error', async ({ page }) => {
|
|
await page.route('**/api/popular-requests/**', (route) => {
|
|
return route.abort('internetdisconnected');
|
|
});
|
|
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const networkError = page.locator('[data-testid="network-error"]');
|
|
await expect(networkError).toBeVisible();
|
|
});
|
|
|
|
test('should handle empty results', async ({ page }) => {
|
|
await page.route('**/api/popular-requests/**', (route) => {
|
|
return route.fulfill({
|
|
status: 200,
|
|
json: { requests: [], total: 0 },
|
|
});
|
|
});
|
|
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const noResults = page.locator('[data-testid="no-results"]');
|
|
await expect(noResults).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Accessibility', () => {
|
|
test('should have proper ARIA labels', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const popularRequests = page.locator('[data-testid="popular-requests"]');
|
|
await expect(popularRequests).toHaveAttribute('role', 'region');
|
|
});
|
|
|
|
test('should be keyboard navigable', async ({ page }) => {
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
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/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const popularRequests = page.locator('[data-testid="popular-requests"]');
|
|
await expect(popularRequests).toBeVisible();
|
|
});
|
|
|
|
test('should be responsive on tablet', async ({ page }) => {
|
|
await page.setViewportSize({ width: 768, height: 1024 });
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const popularRequests = page.locator('[data-testid="popular-requests"]');
|
|
await expect(popularRequests).toBeVisible();
|
|
});
|
|
|
|
test('should be responsive on desktop', async ({ page }) => {
|
|
await page.setViewportSize({ width: 1920, height: 1080 });
|
|
await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', today)}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const popularRequests = page.locator('[data-testid="popular-requests"]');
|
|
await expect(popularRequests).toBeVisible();
|
|
});
|
|
});
|
|
});
|