ba12e04d1e
AdminLayout 增加 role=navigation 侧边栏地标、aria-expanded/aria-label 折叠按钮、 #admin-content 主区锚点与“跳到主内容”skip-link;main.css 提供 :focus-visible 焦点环 与 skip-link 聚焦样式;e2e 8 用例用键盘回车切换折叠并断言 ARIA 语义。
78 lines
3.0 KiB
TypeScript
78 lines
3.0 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test'
|
|
|
|
async function openUsers(page: Page) {
|
|
await page.goto('/admin-vue/')
|
|
await expect(page.locator('h2')).toHaveText('用户管理')
|
|
}
|
|
|
|
test('test_task_018_shell_accessibility_normal_primary_path', async ({ page }) => {
|
|
await openUsers(page)
|
|
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_normal_variant_input', async ({ page }) => {
|
|
await openUsers(page)
|
|
const toggle = page.locator('.sidebar-collapse')
|
|
await expect(toggle).toHaveAttribute('aria-label', '切换侧边栏')
|
|
await expect(toggle).toHaveAttribute('aria-expanded', 'true')
|
|
await expect(toggle).toHaveAttribute('type', 'button')
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_normal_repeated_operation_is_idempotent', async ({ page }) => {
|
|
await openUsers(page)
|
|
const toggle = page.locator('.sidebar-collapse')
|
|
await toggle.click()
|
|
await expect(toggle).toHaveAttribute('aria-expanded', 'false')
|
|
await toggle.click()
|
|
await expect(toggle).toHaveAttribute('aria-expanded', 'true')
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_boundary_empty_input', async ({ page }) => {
|
|
await openUsers(page)
|
|
await expect(page.locator('.skip-link')).toHaveAttribute('href', '#admin-content')
|
|
await expect(page.locator('#admin-content')).toHaveCount(1)
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_boundary_single_item', async ({ page }) => {
|
|
await openUsers(page)
|
|
// 键盘可聚焦并可回车触发折叠切换。
|
|
await page.locator('.sidebar-collapse').focus()
|
|
await expect(page.locator('.sidebar-collapse')).toBeFocused()
|
|
await page.keyboard.press('Enter')
|
|
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_boundary_limit_or_missing_field', async ({ page }) => {
|
|
await openUsers(page)
|
|
await expect(page.locator('main#admin-content')).toBeVisible()
|
|
await expect(page.getByRole('main')).toHaveCount(1)
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_invalid_input_rejected', async ({ page }) => {
|
|
await openUsers(page)
|
|
// 折叠后品牌文案不应留在可感知/可聚焦树中。
|
|
await page.locator('.sidebar-collapse').click()
|
|
await expect(page.locator('.admin-brand-copy')).toHaveCount(0)
|
|
})
|
|
|
|
test('test_task_018_shell_accessibility_dependency_failure_returns_actionable_message', async ({ page }) => {
|
|
await openUsers(page)
|
|
// 标题层级:顶栏 h1(页面标题) + 页面 h2;键盘焦点样式已定义。
|
|
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
|
|
await expect(page.locator('main h2')).toHaveText('用户管理')
|
|
const hasFocusStyle = await page.evaluate(() => {
|
|
const rules: string[] = []
|
|
for (const sheet of document.styleSheets) {
|
|
try {
|
|
for (const rule of sheet.cssRules) {
|
|
if (rule.cssText.includes(':focus-visible')) rules.push(rule.cssText)
|
|
}
|
|
} catch {
|
|
// 跨域样式表忽略
|
|
}
|
|
}
|
|
return rules.some((t) => t.includes('sidebar-collapse'))
|
|
})
|
|
expect(hasFocusStyle).toBe(true)
|
|
})
|