Files
flights_web/tests/e2e-angular/ru-ru/touch-navigation.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

150 lines
4.6 KiB
TypeScript

import { test, expect } from '@playwright/test';
test.describe('US-100: Touch Navigation & Mobile Accessibility', () => {
test('should have 44px minimum touch targets on buttons', async ({ page, context }) => {
// Create a mobile context for touch support
const mobileContext = await context.browser()?.newContext({
viewport: { width: 375, height: 667 },
hasTouch: true,
isMobile: true,
});
if (!mobileContext) return;
const mobilePage = await mobileContext.newPage();
await mobilePage.goto('/ru-ru/schedule');
await mobilePage.waitForLoadState('networkidle');
const buttons = await mobilePage.locator('button').all();
for (const button of buttons) {
const box = await button.boundingBox();
if (box) {
expect(box.width).toBeGreaterThanOrEqual(44);
expect(box.height).toBeGreaterThanOrEqual(44);
}
}
await mobileContext.close();
});
test('should have proper spacing between touch targets', async ({ page, context }) => {
// Create a mobile context
const mobileContext = await context.browser()?.newContext({
viewport: { width: 375, height: 667 },
hasTouch: true,
isMobile: true,
});
if (!mobileContext) return;
const mobilePage = await mobileContext.newPage();
await mobilePage.goto('/ru-ru/schedule');
const buttons = await mobilePage.locator('button').all();
// Check if any two adjacent buttons on the same row have sufficient spacing
let foundValidSpacing = false;
for (let i = 0; i < buttons.length - 1; i++) {
const box1 = await buttons[i].boundingBox();
const box2 = await buttons[i + 1].boundingBox();
if (box1 && box2) {
// Check if buttons are roughly on the same vertical line (within 10px)
const onSameRow = Math.abs(box1.y - box2.y) < 10;
if (onSameRow) {
// Minimum 8px spacing between targets
const horizontalSpacing = box2.x - (box1.x + box1.width);
if (horizontalSpacing >= 8) {
foundValidSpacing = true;
break;
}
}
}
}
// If no horizontal spacing found, buttons are likely stacked vertically which is fine
// Just verify that vertically stacked buttons have minimum size
if (buttons.length >= 2) {
const box1 = await buttons[0].boundingBox();
const box2 = await buttons[1].boundingBox();
if (box1 && box2) {
// Either they have horizontal spacing >= 8px or they're on different rows (which is valid)
const onSameRow = Math.abs(box1.y - box2.y) < 10;
const horizontalSpacing = box2.x - (box1.x + box1.width);
if (onSameRow) {
expect(horizontalSpacing).toBeGreaterThanOrEqual(8);
} else {
// Vertical stacking is valid, just ensure minimum height
expect(box1.height).toBeGreaterThanOrEqual(44);
expect(box2.height).toBeGreaterThanOrEqual(44);
}
}
}
await mobileContext.close();
});
test('should not zoom on input focus', async ({ page, context }) => {
// Create a mobile context
const mobileContext = await context.browser()?.newContext({
viewport: { width: 375, height: 667 },
hasTouch: true,
isMobile: true,
});
if (!mobileContext) return;
const mobilePage = await mobileContext.newPage();
await mobilePage.goto('/ru-ru/schedule');
// Get initial zoom level
const initialZoom = await mobilePage.evaluate(() => window.devicePixelRatio);
// Focus an input
const input = mobilePage.locator('input').first();
await input.focus();
// Check zoom level hasn't changed
const zoomAfterFocus = await mobilePage.evaluate(() => window.devicePixelRatio);
expect(zoomAfterFocus).toBe(initialZoom);
await mobileContext.close();
});
test('should console have zero errors on mobile', async ({ page, context }) => {
// Create a mobile context with touch support
const mobileContext = await context.browser()?.newContext({
viewport: { width: 375, height: 667 },
hasTouch: true,
isMobile: true,
});
if (!mobileContext) return;
const mobilePage = await mobileContext.newPage();
const errors: string[] = [];
mobilePage.on('console', (msg) => {
if (msg.type() === 'error') errors.push(msg.text());
});
await mobilePage.goto('/ru-ru/schedule');
await mobilePage.waitForLoadState('networkidle');
// Simulate touch interactions
const buttons = await mobilePage.locator('button').all();
if (buttons.length > 0) {
await buttons[0].tap();
}
expect(errors).toHaveLength(0);
await mobileContext.close();
});
});