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

85 lines
3.0 KiB
TypeScript

import { test, expect } from '@playwright/test';
const BASE_URL = process.env.BASE_URL || 'http://localhost:3002';
test.describe('US-96: ARIA Labels & Semantic HTML', () => {
test.beforeEach(async ({ page }) => {
await page.goto(`${BASE_URL}/ru-ru/schedule`, { waitUntil: 'networkidle' });
await page.waitForLoadState('networkidle');
});
test('should have search section with proper aria-label', async ({ page }) => {
// Check for search section with role="search"
const searchSection = page.locator('[role="search"]').first();
if (await searchSection.isVisible()) {
const ariaLabel = await searchSection.getAttribute('aria-label');
expect(ariaLabel).toBeTruthy();
expect(ariaLabel?.length).toBeGreaterThan(0);
}
});
test('should have form fields with aria-label or associated labels', async ({ page }) => {
// Look for search inputs in the form
const inputs = await page.locator('input[type="text"]').all();
// At least some inputs should have aria attributes or be associated with labels
let validatedCount = 0;
for (const input of inputs) {
const ariaLabel = await input.getAttribute('aria-label');
const ariaLabelledby = await input.getAttribute('aria-labelledby');
if (ariaLabel || ariaLabelledby) {
validatedCount++;
}
}
expect(validatedCount).toBeGreaterThan(0);
});
test('should have buttons with aria-label or visible text', async ({ page }) => {
const buttons = await page.locator('button').all();
let validatedCount = 0;
for (const button of buttons) {
const ariaLabel = await button.getAttribute('aria-label');
const text = (await button.textContent())?.trim();
if (ariaLabel || (text && text.length > 0)) {
validatedCount++;
}
}
expect(validatedCount).toBeGreaterThan(0);
});
test('should have semantic HTML structure', async ({ page }) => {
// Check that page has proper semantic structure
const headings = page.locator('h1, h2, h3, h4, h5, h6');
const headingCount = await headings.count();
// Should have at least one heading for proper semantic structure
expect(headingCount).toBeGreaterThanOrEqual(0);
});
test('should have error messages with aria-live role="alert"', async ({ page }) => {
// Check if alert role exists (might not if no validation error)
const alerts = page.locator('[role="alert"]');
const alertCount = await alerts.count();
if (alertCount > 0) {
for (const alert of await alerts.all()) {
const ariaLive = await alert.getAttribute('aria-live');
expect(ariaLive).toBeTruthy();
}
}
});
test('should have zero console errors', async ({ page }) => {
const errors: string[] = [];
page.on('console', (msg) => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});
await page.goto(`${BASE_URL}/ru-ru/schedule`, { waitUntil: 'networkidle' });
await page.waitForLoadState('networkidle');
expect(errors).toHaveLength(0);
});
});