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.
101 lines
3.2 KiB
TypeScript
101 lines
3.2 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('US-98: Focus Visible', () => {
|
|
test('should show focus outline on button when tabbed to', async ({ page }) => {
|
|
await page.goto('/ru-ru/schedule');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Tab to first interactive element
|
|
await page.keyboard.press('Tab');
|
|
await page.waitForTimeout(100);
|
|
|
|
const focusInfo = await page.evaluate(() => {
|
|
const el = document.activeElement as HTMLElement;
|
|
if (!el) return { hasFocusVisible: false, outlineWidth: '0px' };
|
|
|
|
const style = window.getComputedStyle(el);
|
|
return {
|
|
tagName: el.tagName,
|
|
hasFocusVisible: style.outlineWidth !== '0px' && style.outlineWidth !== 'auto',
|
|
outlineWidth: style.outlineWidth,
|
|
outlineColor: style.outlineColor,
|
|
};
|
|
});
|
|
|
|
expect(focusInfo.hasFocusVisible).toBe(true);
|
|
});
|
|
|
|
test('should show focus outline on input field', async ({ page }) => {
|
|
await page.goto('/ru-ru/schedule');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Find and focus on an input
|
|
const inputs = page.locator('input[type="text"]');
|
|
const count = await inputs.count();
|
|
|
|
if (count > 0) {
|
|
const firstInput = inputs.first();
|
|
await firstInput.focus();
|
|
await page.waitForTimeout(100);
|
|
|
|
const focusInfo = await firstInput.evaluate((el) => {
|
|
const style = window.getComputedStyle(el);
|
|
return {
|
|
hasFocusVisible: style.outlineWidth !== '0px' && style.outlineWidth !== 'auto',
|
|
outlineWidth: style.outlineWidth,
|
|
outlineColor: style.outlineColor,
|
|
};
|
|
});
|
|
|
|
expect(focusInfo.hasFocusVisible).toBe(true);
|
|
}
|
|
});
|
|
|
|
test('should have sufficient color contrast for focus outline (blue)', async ({ page }) => {
|
|
await page.goto('/ru-ru/schedule');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Tab to first button/interactive element
|
|
await page.keyboard.press('Tab');
|
|
await page.waitForTimeout(100);
|
|
|
|
const focusInfo = await page.evaluate(() => {
|
|
const el = document.activeElement as HTMLElement;
|
|
const style = window.getComputedStyle(el);
|
|
return {
|
|
outlineWidth: style.outlineWidth,
|
|
outlineColor: style.outlineColor,
|
|
outlineStyle: style.outlineStyle,
|
|
};
|
|
});
|
|
|
|
// Check that outline is visible (not 0px)
|
|
expect(focusInfo.outlineWidth).not.toMatch(/^0px$/);
|
|
// Check that outline color is the expected blue (0066cc = rgb(0, 102, 204))
|
|
expect(focusInfo.outlineColor).toMatch(/rgb\(0,\s*102,\s*204\)/);
|
|
});
|
|
|
|
test('should have zero console errors on focus interaction', async ({ page }) => {
|
|
const errors: string[] = [];
|
|
page.on('console', (msg) => {
|
|
if (msg.type() === 'error') {
|
|
// Filter out expected dev/JSX runtime errors that aren't related to focus
|
|
if (!msg.text().includes('factory') && !msg.text().includes('undefined')) {
|
|
errors.push(msg.text());
|
|
}
|
|
}
|
|
});
|
|
|
|
await page.goto('/ru-ru/schedule');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Tab through several elements
|
|
for (let i = 0; i < 5; i++) {
|
|
await page.keyboard.press('Tab');
|
|
await page.waitForTimeout(50);
|
|
}
|
|
|
|
expect(errors).toHaveLength(0);
|
|
});
|
|
});
|