Files
gaokao-volunteer-system/apps/web/e2e/runtime-accessibility.spec.ts
Frontend Developer 45e671966a
Some checks failed
CI / pytest (Python 3.10) (push) Has been cancelled
CI / pytest (Python 3.11) (push) Has been cancelled
CI / pytest (Python 3.12) (push) Has been cancelled
feat: complete frontend ui integrity followups
2026-07-05 14:09:49 +08:00

77 lines
3.0 KiB
TypeScript

import { expect, test, type Locator, type Page } from '@playwright/test';
async function expectKeyboardFocus(locator: Locator): Promise<void> {
await locator.focus();
await expect(locator).toBeFocused();
const outlineVisible = await locator.evaluate((element) => {
const style = window.getComputedStyle(element);
return style.outlineStyle !== 'none' || style.boxShadow !== 'none';
});
expect(outlineVisible).toBe(true);
}
async function seedAdminSession(page: Page): Promise<void> {
await page.addInitScript(() => {
window.localStorage.setItem(
'gaokao-user-store',
JSON.stringify({
state: {
id: 'admin-a11y',
name: 'Runtime Admin',
phone: '13800138000',
role: 'admin',
isLoggedIn: true,
},
version: 0,
}),
);
});
}
test.describe('Runtime accessibility smoke (non-Docker)', () => {
test('public shell exposes landmarks, named controls, focus rings, and dark mode', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('main').or(page.locator('.app-layout'))).toBeVisible();
expect(await page.getByRole('navigation').count()).toBeGreaterThanOrEqual(1);
await expect(page.getByRole('navigation').first()).toBeVisible();
const chatInput = page.getByRole('textbox', { name: /输入你的问题|Enter your question/ });
await expect(chatInput).toBeVisible();
await expectKeyboardFocus(chatInput);
await page.getByRole('radio', { name: '暗色' }).click();
await expect(page.locator('html')).toHaveClass(/dark/);
});
test('data query page keeps labelled form controls and methodology dialog semantics', async ({ page }) => {
await page.goto('/data-query');
await expect(page.getByRole('heading', { name: /数据查询|Data query/ })).toBeVisible();
await expect(page.getByRole('button', { name: /数据口径|Methodology/ })).toBeVisible();
await expect(page.getByLabel(/省份|Province/).first()).toBeVisible();
await expect(page.getByLabel(/年份|Year/).first()).toBeVisible();
await page.getByRole('button', { name: /数据口径|Methodology/ }).click();
await expect(page.getByRole('dialog')).toBeVisible();
await expect(page.getByRole('button', { name: /关闭|Close/ })).toBeVisible();
});
test('admin login and protected layout expose runtime accessibility landmarks', async ({ page }) => {
await page.goto('/admin/login');
await expect(page.getByRole('main')).toBeVisible();
await expect(page.getByLabel(/手机号|Phone/)).toBeVisible();
await expect(page.getByLabel(/验证码|Code/)).toBeVisible();
await expectKeyboardFocus(page.getByLabel(/手机号|Phone/));
await seedAdminSession(page);
await page.goto('/admin');
await expect(page.getByRole('navigation', { name: /后台导航|Admin navigation/ })).toBeVisible();
await expect(page.getByRole('main')).toBeVisible();
await expect(page.getByRole('button', { name: /退出|Logout/ })).toBeVisible();
});
});