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.
641 lines
22 KiB
TypeScript
641 lines
22 KiB
TypeScript
import { test, expect } from '../support/cross-app-fixtures';
|
|
import { mockAllAPIs } from '../support/cross-app-fixtures';
|
|
import { S, tid } from '../support/selectors';
|
|
|
|
/**
|
|
* Locale Switching Cross-App Test Suite (Tests 298-315)
|
|
*
|
|
* 18 tests covering:
|
|
* - Locale switcher visibility and accessibility
|
|
* - Dropdown display and interaction
|
|
* - Locale selection and navigation
|
|
* - Content translation verification
|
|
* - Locale persistence across pages and reloads
|
|
*/
|
|
|
|
// Map of supported locales to their display names
|
|
const LOCALE_NAMES: Record<string, string> = {
|
|
'ru-ru': 'Русский',
|
|
'en-us': 'English',
|
|
'es-es': 'Español',
|
|
'fr-fr': 'Français',
|
|
'it-it': 'Italiano',
|
|
'ja-jp': '日本語',
|
|
'ko-kr': '한국어',
|
|
'zh-cn': '中文',
|
|
'de-de': 'Deutsch',
|
|
};
|
|
|
|
// Sample translation keys and their expected values per locale
|
|
// Reference data for translation testing (some tests may use subset of these)
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const _TRANSLATION_SAMPLES: Record<string, Record<string, string>> = {
|
|
'ru-ru': {
|
|
'nav.flightBoard': 'Онлайн табло',
|
|
'nav.schedule': 'Расписание',
|
|
'search.find': 'Поиск',
|
|
},
|
|
'en-us': {
|
|
'nav.flightBoard': 'Online Board',
|
|
'nav.schedule': 'Schedule',
|
|
'search.find': 'Search',
|
|
},
|
|
'es-es': {
|
|
'nav.flightBoard': 'Tablero en línea',
|
|
'nav.schedule': 'Horario',
|
|
'search.find': 'Buscar',
|
|
},
|
|
'fr-fr': {
|
|
'nav.flightBoard': "Tableau d'affichage en direct",
|
|
'nav.schedule': 'Horaire',
|
|
'search.find': 'Rechercher',
|
|
},
|
|
'it-it': {
|
|
'nav.flightBoard': 'Scheda Online',
|
|
'nav.schedule': 'Programma',
|
|
'search.find': 'Cerca',
|
|
},
|
|
'ja-jp': {
|
|
'nav.flightBoard': 'オンラインボード',
|
|
'nav.schedule': 'スケジュール',
|
|
'search.find': '検索',
|
|
},
|
|
'ko-kr': {
|
|
'nav.flightBoard': '온라인 보드',
|
|
'nav.schedule': '일정',
|
|
'search.find': '검색',
|
|
},
|
|
'zh-cn': {
|
|
'nav.flightBoard': '在线板',
|
|
'nav.schedule': '航班时刻表',
|
|
'search.find': '搜索',
|
|
},
|
|
'de-de': {
|
|
'nav.flightBoard': 'Online-Tafel',
|
|
'nav.schedule': 'Fahrplan',
|
|
'search.find': 'Suchen',
|
|
},
|
|
};
|
|
|
|
test.describe('Locale Switching (Cross-App)', () => {
|
|
test.beforeEach(async ({ page, localePath }) => {
|
|
await mockAllAPIs(page);
|
|
await page.goto(localePath('/'));
|
|
await page.waitForLoadState('networkidle');
|
|
});
|
|
|
|
// ====================================================================
|
|
// SECTION 1: Locale Switcher Visibility & Accessibility (Tests 298-300)
|
|
// ====================================================================
|
|
|
|
test('298: Locale switcher button is visible in layout', async ({ page, app }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
await expect(switcher).toBeVisible();
|
|
});
|
|
|
|
test('299: Locale switcher button shows current locale code', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
// Switcher should display the current locale code (e.g., "RU-RU", "EN-US")
|
|
const localeCode = locale.toUpperCase();
|
|
await expect(switcher).toContainText(localeCode);
|
|
});
|
|
|
|
test('300: Locale switcher button is clickable', async ({ page, app }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
await expect(switcher).toBeEnabled();
|
|
// Verify it's actually a button or has button-like properties
|
|
const role = await switcher.getAttribute('role');
|
|
const isButton =
|
|
(await switcher.evaluate((el) => el instanceof HTMLButtonElement)) ||
|
|
role === 'button' ||
|
|
(await switcher.locator('button').count()) > 0;
|
|
expect(isButton).toBe(true);
|
|
});
|
|
|
|
// ====================================================================
|
|
// SECTION 2: Locale Dropdown Display (Tests 301-303)
|
|
// ====================================================================
|
|
|
|
test('301: Clicking switcher opens dropdown menu', async ({ page, app }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
await expect(options.first()).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
test('302: Dropdown shows all 9 available locales', async ({ page, app }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
const optionCount = await options.count();
|
|
// Should have at least the 9 tested locales
|
|
expect(optionCount).toBeGreaterThanOrEqual(9);
|
|
});
|
|
|
|
test('303: Dropdown displays locale names/codes correctly', async ({ page, app }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
|
|
// Verify options display native names or codes
|
|
const optionTexts: string[] = [];
|
|
for (let i = 0; i < Math.min(await options.count(), 9); i++) {
|
|
const text = await options.nth(i).textContent();
|
|
if (text) optionTexts.push(text);
|
|
}
|
|
|
|
// Should have some recognizable locale text
|
|
const hasLocaleText = optionTexts.some(
|
|
(text) =>
|
|
text.includes('English') ||
|
|
text.includes('Русский') ||
|
|
text.includes('Español') ||
|
|
text.includes('Français') ||
|
|
text.includes('en-us') ||
|
|
text.includes('ru-ru'),
|
|
);
|
|
expect(hasLocaleText).toBe(true);
|
|
});
|
|
|
|
// ====================================================================
|
|
// SECTION 3: Locale Selection & Navigation (Tests 304-307)
|
|
// ====================================================================
|
|
|
|
test('304: Selecting different locale closes dropdown', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
await expect(options.first()).toBeVisible();
|
|
|
|
// Click first visible option (if not current locale)
|
|
const firstOption = options.first();
|
|
const firstLocaleCode = await firstOption.getAttribute('data-locale');
|
|
|
|
if (firstLocaleCode && firstLocaleCode !== locale.split('-')[0]) {
|
|
await firstOption.click();
|
|
// Wait for navigation and dropdown to close
|
|
await page.waitForLoadState('networkidle');
|
|
await page.waitForTimeout(300);
|
|
|
|
// Dropdown should be hidden
|
|
await expect(options.first()).toBeHidden();
|
|
} else {
|
|
test.skip(true, 'No alternate locale available to test');
|
|
}
|
|
});
|
|
|
|
test('305: Selecting locale changes URL prefix', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
|
|
// Find option matching target locale by data-locale or text content
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocale.split('-')[0]}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
// Try by native name
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
// URL should contain new locale prefix
|
|
await expect(page).toHaveURL(new RegExp(`/${targetLocale}/`));
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('306: Page content reloads after locale change', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
// Get initial content
|
|
const initialLocale = locale;
|
|
|
|
const targetLocale = initialLocale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocale.split('-')[0]}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const contentAfter = await page.locator('body').textContent();
|
|
// Content should have changed (some text different between locales)
|
|
// This is a loose check - exact comparison may be fragile
|
|
expect(contentAfter).toBeTruthy();
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('307: Selected locale is highlighted in dropdown', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
|
|
// Find current locale option
|
|
let currentOption = options
|
|
.filter({ has: page.locator(`[data-locale="${locale.split('-')[0]}"]`) })
|
|
.first();
|
|
|
|
if ((await currentOption.count()) === 0) {
|
|
const localeName = LOCALE_NAMES[locale];
|
|
currentOption = options.filter({ hasText: new RegExp(localeName) }).first();
|
|
}
|
|
|
|
if ((await currentOption.count()) > 0) {
|
|
// Current option should have active class or aria-selected
|
|
const hasActiveClass = await currentOption.evaluate(
|
|
(el) => el.className.includes('active') || el.className.includes('selected'),
|
|
);
|
|
const isAriaSelected = await currentOption.getAttribute('aria-selected');
|
|
|
|
expect(hasActiveClass || isAriaSelected === 'true').toBe(true);
|
|
} else {
|
|
test.skip(true, 'Current locale option not found');
|
|
}
|
|
});
|
|
|
|
// ====================================================================
|
|
// SECTION 4: Content Translation Verification (Tests 308-312)
|
|
// ====================================================================
|
|
|
|
test('308: Page titles translate after locale change', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Verify page title or h1 contains translated content
|
|
const pageTitle = await page.title();
|
|
const h1 = await page.locator('h1').first().textContent();
|
|
const hasContent = pageTitle || h1;
|
|
expect(hasContent).toBeTruthy();
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('309: Button labels translate after locale change', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Get sample button text after
|
|
const buttonsAfter = await page.locator('button').first().textContent();
|
|
|
|
// At least some button text should exist and be localized
|
|
expect(buttonsAfter).toBeTruthy();
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('310: Placeholder text translates after locale change', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Look for input with placeholder
|
|
const inputWithPlaceholder = page.locator('input[placeholder]').first();
|
|
const placeholder = await inputWithPlaceholder.getAttribute('placeholder');
|
|
|
|
// Just verify placeholders exist and are not empty
|
|
if (placeholder) {
|
|
expect(placeholder.length).toBeGreaterThan(0);
|
|
}
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('311: Tab names translate after locale change', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Check for navigation tabs
|
|
const navTabs = page.locator('[role="tab"], [data-testid*="tab"]').first();
|
|
const tabText = await navTabs.textContent();
|
|
|
|
// Navigation should have tab labels
|
|
expect(tabText).toBeTruthy();
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('312: Error messages translate after locale change', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Look for error message or alert if present
|
|
const errorMsg = page.locator('[role="alert"], .error, [data-testid*="error"]').first();
|
|
const errorText = await errorMsg.textContent().catch(() => '');
|
|
|
|
// Error messages should be translatable (just verify they exist or are properly structured)
|
|
expect(typeof errorText).toBe('string');
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
// ====================================================================
|
|
// SECTION 5: Locale Persistence (Tests 313-315)
|
|
// ====================================================================
|
|
|
|
test('313: Selected locale persists on page reload', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
// Switch locale
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Verify URL changed
|
|
await expect(page).toHaveURL(new RegExp(`/${targetLocale}/`));
|
|
|
|
// Reload page
|
|
await page.reload();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Locale should persist in URL
|
|
await expect(page).toHaveURL(new RegExp(`/${targetLocale}/`));
|
|
|
|
// Switcher should show the same locale
|
|
const localeCode = targetLocale.toUpperCase();
|
|
await expect(switcher).toContainText(localeCode);
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('314: Switching pages maintains current locale', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
// Switch locale
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Current URL in target locale
|
|
const currentUrl = page.url();
|
|
expect(currentUrl).toContain(`/${targetLocale}/`);
|
|
|
|
// Try to navigate to schedule (or another page)
|
|
const scheduleTab = page.locator(tid(S.NAV_SCHEDULE_TAB, app));
|
|
if ((await scheduleTab.count()) > 0) {
|
|
await scheduleTab.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Should still be in target locale
|
|
await expect(page).toHaveURL(new RegExp(`/${targetLocale}/schedule`));
|
|
}
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
|
|
test('315: Browser history preserves locale context', async ({ page, app, locale }) => {
|
|
const switcher = page.locator(tid(S.LAYOUT_LOCALE_SWITCHER, app));
|
|
if ((await switcher.count()) === 0) {
|
|
test.skip(true, 'Locale switcher not present in this app');
|
|
return;
|
|
}
|
|
|
|
const targetLocale = locale === 'en-us' ? 'ru-ru' : 'en-us';
|
|
const targetLocaleCode = targetLocale.split('-')[0];
|
|
|
|
// Switch locale
|
|
await switcher.click();
|
|
const options = page.locator(tid(S.LAYOUT_LOCALE_OPTION, app));
|
|
let targetOption = options
|
|
.filter({ has: page.locator(`[data-locale="${targetLocaleCode}"]`) })
|
|
.first();
|
|
|
|
if ((await targetOption.count()) === 0) {
|
|
const targetName = LOCALE_NAMES[targetLocale];
|
|
targetOption = options.filter({ hasText: new RegExp(targetName) }).first();
|
|
}
|
|
|
|
if ((await targetOption.count()) > 0) {
|
|
await targetOption.click();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const newUrl = page.url();
|
|
expect(newUrl).toContain(`/${targetLocale}/`);
|
|
|
|
// Navigate back
|
|
await page.goBack();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Should be on previous locale
|
|
await expect(page).toHaveURL(new RegExp(`/${locale}/`));
|
|
|
|
// Navigate forward
|
|
await page.goForward();
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Should be back to target locale
|
|
await expect(page).toHaveURL(new RegExp(`/${targetLocale}/`));
|
|
} else {
|
|
test.skip(true, 'Target locale option not found');
|
|
}
|
|
});
|
|
});
|