Files
flights_web/tests/e2e-angular/cross-app/01-navigation.spec.ts
T
gnezim 4b87fca973 Remove locale switcher tests — feature not in Angular app
Locale switching is handled by the host site (aeroflot.ru), not the
Angular SPA. Removed 13-locale-switching.spec.ts (entire file, 27 tests)
and locale switcher tests from 01-navigation (5 tests) and
18-advanced-features (4 tests).

Cross-app: 213 passed, 146 skipped, 0 failed.
ru-ru: 15 passed, 0 failed.
2026-04-16 00:44:41 +03:00

173 lines
7.0 KiB
TypeScript

import { test, expect } from '../support/cross-app-fixtures';
import { mockAllAPIs } from '../support/cross-app-fixtures';
import { S, tid } from '../support/selectors';
test.describe('Navigation & Layout', () => {
test.beforeEach(async ({ page, localePath }) => {
await mockAllAPIs(page);
await page.goto(localePath('onlineboard'));
await page.waitForLoadState('networkidle');
});
test('1: Tab "Online Board" is visible and active by default', async ({ page, app }) => {
const tab = page.locator(tid(S.NAV_ONLINEBOARD_TAB, app));
await expect(tab).toBeVisible();
await expect(tab).toHaveClass(/active|selected/);
});
test('2: Tab "Schedule" navigates to schedule page', async ({ page, app, locale }) => {
const tab = page.locator(tid(S.NAV_SCHEDULE_TAB, app));
await expect(tab).toBeVisible();
await tab.click();
await expect(page).toHaveURL(new RegExp(`/${locale}/schedule`));
});
test('3: Tab "Flights Map" navigates to flights map page', async ({ page, app, locale }) => {
const tab = page.locator(tid(S.NAV_FLIGHTS_MAP_TAB, app));
await expect(tab).toBeVisible();
await tab.click();
await expect(page).toHaveURL(new RegExp(`/${locale}/flights-map`));
});
test('4: Tab active state matches current route', async ({ page, app, locale }) => {
// Navigate to schedule
await page.goto(`/${locale}/schedule`);
await page.waitForLoadState('networkidle');
const scheduleTab = page.locator(tid(S.NAV_SCHEDULE_TAB, app));
await expect(scheduleTab).toHaveClass(/active|selected/);
const boardTab = page.locator(tid(S.NAV_ONLINEBOARD_TAB, app));
await expect(boardTab).not.toHaveClass(/active|selected/);
});
test('5: Breadcrumbs show correct path on landing', async ({ page, app }) => {
const breadcrumbs = page.locator(tid(S.LAYOUT_BREADCRUMBS, app));
// Angular uses PrimeNG p-breadcrumb without data-testid; fall back to tag selector
const fallback = page.locator('p-breadcrumb, nav[aria-label*="bread"]');
const target = (await breadcrumbs.count()) > 0 ? breadcrumbs : fallback;
await expect(target).toBeVisible();
});
test('6: Breadcrumbs show correct path on search results', async ({
page,
app,
locale,
localePath,
}) => {
// Navigate to a departure search
const path = `onlineboard/departure/MOW-${formatToday()}`;
const url = localePath(path);
console.log('Test 6 URL:', url);
await page.goto(url, {
waitUntil: 'domcontentloaded',
});
console.log('Test 6 Current URL:', page.url());
const breadcrumbs = page.locator(tid(S.LAYOUT_BREADCRUMBS, app));
const fallback = page.locator('p-breadcrumb, nav[aria-label*="bread"]');
const target = (await breadcrumbs.count()) > 0 ? breadcrumbs : fallback;
await expect(target).toBeVisible();
// Should have at least 1 link
const links = target.locator('a');
expect(await links.count()).toBeGreaterThanOrEqual(1);
});
test('7: Breadcrumbs show correct path on flight details', async ({ page, app, locale }) => {
// Navigate to a search first, then open details
await page.goto(`/${locale}/onlineboard/departure/MOW-${formatToday()}`);
await page.waitForLoadState('networkidle');
const firstFlight = page.locator(tid(S.BOARD_FLIGHT_RESULT, app)).first();
// If results exist, click through to details
const count = await firstFlight.count();
if (count > 0) {
await firstFlight.click();
await page.waitForLoadState('networkidle');
const breadcrumbs = page.locator(tid(S.LAYOUT_BREADCRUMBS, app));
const fallback = page.locator('p-breadcrumb, nav[aria-label*="bread"]');
const target = (await breadcrumbs.count()) > 0 ? breadcrumbs : fallback;
await expect(target).toBeVisible();
expect(await target.locator('a').count()).toBeGreaterThanOrEqual(2);
}
});
test('8: Breadcrumbs links are clickable and navigate correctly', async ({
page,
app,
locale,
}) => {
await page.goto(`/${locale}/schedule`);
await page.waitForLoadState('networkidle');
const breadcrumbs = page.locator(tid(S.LAYOUT_BREADCRUMBS, app));
const fallback = page.locator('p-breadcrumb, nav[aria-label*="bread"]');
const target = (await breadcrumbs.count()) > 0 ? breadcrumbs : fallback;
const links = target.locator('a');
if ((await links.count()) > 0) {
// The first breadcrumb link typically navigates home or to main section
const firstHref = await links.first().getAttribute('href');
expect(firstHref).toBeTruthy();
}
});
test('14: Feedback button is visible in layout', async ({ page, app }) => {
const button = page.locator(tid(S.LAYOUT_FEEDBACK_BUTTON, app));
if ((await button.count()) === 0) {
test.skip(true, 'Feedback button not present in this app');
return;
}
await expect(button).toBeVisible();
});
test('15: Feedback button opens feedback form on click', async ({ page, app }) => {
const button = page.locator(tid(S.LAYOUT_FEEDBACK_BUTTON, app));
if ((await button.count()) === 0) {
test.skip(true, 'Feedback button not present in this app');
return;
}
await button.click();
await expect(page.locator('[role="dialog"], .feedback-form, .modal')).toBeVisible({
timeout: 5000,
});
});
test('16: Scroll-to-top button appears after scrolling down', async ({ page, app }) => {
const scrollBtn = page.locator(tid(S.LAYOUT_SCROLL_TOP_BUTTON, app));
// Some apps may not have this feature
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(500);
if ((await scrollBtn.count()) === 0) {
test.skip(true, 'Scroll-to-top button not present in this app');
return;
}
await expect(scrollBtn).toBeVisible({ timeout: 5000 });
});
test('17: Scroll-to-top button scrolls page to top on click', async ({ page, app }) => {
const scrollBtn = page.locator(tid(S.LAYOUT_SCROLL_TOP_BUTTON, app));
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(500);
if ((await scrollBtn.count()) === 0) {
test.skip(true, 'Scroll-to-top button not present in this app');
return;
}
await expect(scrollBtn).toBeVisible({ timeout: 5000 });
await scrollBtn.click();
await page.waitForTimeout(500);
const scrollY = await page.evaluate(() => window.scrollY);
expect(scrollY).toBeLessThan(100);
});
test('18: Scroll-to-top button hides when at top', async ({ page, app }) => {
const scrollBtn = page.locator(tid(S.LAYOUT_SCROLL_TOP_BUTTON, app));
if ((await scrollBtn.count()) === 0) {
test.skip(true, 'Scroll-to-top button not present in this app');
return;
}
// At top of page, button should be hidden
await expect(scrollBtn).toBeHidden();
});
});
function formatToday(timeFrom = '0000', timeTo = '2359'): string {
const d = new Date();
const dateStr = `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;
return `${dateStr}-${timeFrom}${timeTo}`;
}