feat(需求): ①全站分页pageSize统一默认10+10/20/50/100选项(9页默认值15/20→10+6个兜底常量统一+撞款台账升级OldPagination+商品类目树顶层标准分页) ②修复6页OldPagination缺import分页器不渲染(不符合ASIN/查询ASIN/最低价ASIN/生成记录/店铺密钥/店铺管理)+查询ASIN操作列按钮间距+最低价范围筛选number类型报错 ③e2e断言对齐现状(顶栏h1/移除收起按钮后规格同步)+国家显示中文断言固化

This commit is contained in:
2026-09-07 02:36:35 +08:00
parent 056abcd473
commit 678605e9fb
44 changed files with 590 additions and 175 deletions
+3 -3
View File
@@ -5,7 +5,7 @@ import { expect, test, type Page } from '@playwright/test'
async function openAdmin(page: Page) {
await page.goto('/admin-vue/')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
}
test('test_task_249_shell_light_normal_primary_path', async ({ page }) => {
@@ -40,8 +40,8 @@ test('test_task_249_shell_light_invalid_input_rejected', async ({ page }) => {
page.on('pageerror', (error) => errors.push(error.message))
await openAdmin(page)
await page.goto('/admin-vue/account/menus')
await expect(page.locator('main h2')).toHaveText('菜单管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('菜单管理')
await page.goto('/admin-vue/account/groups')
await expect(page.locator('main h2')).toHaveText('数据权限分组')
await expect(page.locator('.admin-topbar h1')).toHaveText('数据权限分组')
expect(errors).toEqual([])
})
+3 -3
View File
@@ -32,13 +32,13 @@ test('test_dup_console_render_ledger_tab_normal_variant_input', async ({ page })
await expect(page.locator('.dup-head h2')).toHaveText('店铺数据撞款监控')
await page.getByRole('button', { name: /全部ASIN台账/ }).click()
await expect(page.locator('table.ledger tbody tr').first()).toBeVisible({ timeout: 15000 })
await expect(page.locator('.pager')).toBeVisible()
await expect(page.locator('.old-pagination')).toBeVisible()
expect(errors).toEqual([])
await page.locator('.table-wrap').screenshot({ path: 'test-results/dup-console-admin-ledger.jpg' })
})
test('test_dup_console_palette_matches_reference_tokens', async ({ page }) => {
// reference 设计令牌在页面落定:主蓝 #2E5BE6、红 #D63A4A、弱红底、单元底色等。
// reference 设计令牌在页面落定:主蓝 #2E5BE6、红 #D63A4A、弱红底、单元底色等(按钮蓝白统一为 #4f78a5
await page.goto('/admin-vue/shop-center/duplicate-check')
await expect(page.locator('.kpi')).toHaveCount(7)
const got = await page.evaluate(() => {
@@ -60,7 +60,7 @@ test('test_dup_console_palette_matches_reference_tokens', async ({ page }) => {
kDotDanger: cs('.kpi.danger .k-dot', 'backgroundColor'),
}
})
expect(got.btnPrimary).toBe('rgb(46, 91, 230)')
expect(got.btnPrimary).toBe('rgb(79, 120, 165)') // 全站按钮主色统一 #4f78a5d385d999 起)
expect(got.btnPrimaryColor).toBe('rgb(255, 255, 255)')
expect(got.kpiDanger).toBe('rgb(214, 58, 74)')
expect(got.kpiPrimary).toBe('rgb(46, 91, 230)')
@@ -1,5 +1,8 @@
import { expect, test, type Page } from '@playwright/test'
// 响应式壳层对齐现状(task-276 已移除侧边栏收起按钮/is-collapsed 机制):
// 断言主题改为「窄屏不破版、核心地标与标题可用」。
async function open(page: Page, width: number, path = '/admin-vue/') {
await page.setViewportSize({ width, height: 900 })
await page.goto(path)
@@ -7,60 +10,51 @@ async function open(page: Page, width: number, path = '/admin-vue/') {
test('test_task_017_desktop_shell_responsive_normal_primary_path', async ({ page }) => {
await open(page, 1440)
await expect(page.locator('h2')).toHaveText('用户管理')
const shell = page.locator('.admin-shell')
await expect(shell).not.toHaveClass(/is-collapsed/)
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
await expect(page.locator('.admin-brand-copy strong')).toHaveText('数富AI')
await expect(page.locator('.sidebar-collapse')).toHaveAttribute('aria-expanded', 'true')
})
test('test_task_017_desktop_shell_responsive_normal_variant_input', async ({ page }) => {
await open(page, 1280)
await expect(page.locator('h2')).toHaveText('用户管理')
await expect(page.locator('.admin-shell')).not.toHaveClass(/is-collapsed/)
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
})
test('test_task_017_desktop_shell_responsive_normal_repeated_operation_is_idempotent', async ({ page }) => {
await open(page, 1440)
await expect(page.locator('.sidebar-collapse')).toHaveAttribute('aria-expanded', 'true')
const toggle = page.locator('.sidebar-collapse')
await toggle.click()
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await toggle.click()
await expect(page.locator('.admin-shell')).not.toHaveClass(/is-collapsed/)
await expect(toggle).toHaveAttribute('aria-expanded', 'true')
await page.reload()
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
})
test('test_task_017_desktop_shell_responsive_boundary_empty_input', async ({ page }) => {
await open(page, 640)
await expect(page.locator('h2')).toHaveText('用户管理')
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await expect(page.locator('.brand-copy, .admin-brand-copy')).toHaveCount(0)
await expect(page.locator('.sidebar-collapse')).toHaveAttribute('aria-expanded', 'false')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
// 窄屏侧栏自适应收缩(当前 85px 窄栏),不遮主内容标题。
await expect(page.locator('.admin-topbar h1')).toBeVisible()
})
test('test_task_017_desktop_shell_responsive_boundary_single_item', async ({ page }) => {
await open(page, 700)
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await page.locator('.sidebar-collapse').click()
await expect(page.locator('.admin-shell')).not.toHaveClass(/is-collapsed/)
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.locator('.admin-brand-copy strong')).toHaveText('数富AI')
})
test('test_task_017_desktop_shell_responsive_boundary_limit_or_missing_field', async ({ page }) => {
await open(page, 900)
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await open(page, 901, '/admin-vue/account/users')
await expect(page.locator('.admin-shell')).not.toHaveClass(/is-collapsed/)
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
})
test('test_task_017_desktop_shell_responsive_invalid_input_rejected', async ({ page }) => {
// 手动折叠偏好持久化,刷新后仍保持(不因页面重载而回弹)。
// 折叠偏好了;刷新后壳层保持正常渲染(不因重载变样)。
await open(page, 1440)
await page.locator('.sidebar-collapse').click()
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await page.reload()
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
})
test('test_task_017_desktop_shell_responsive_dependency_failure_returns_actionable_message', async ({ page }) => {
@@ -1,8 +1,11 @@
import { expect, test, type Page } from '@playwright/test'
// 壳层可访问性对齐现状(task-276 已移除侧边栏收起按钮/is-collapsed 机制):
// 断言主题改为「跳转链接、地标唯一性、标题层级、键盘可达」。
async function openUsers(page: Page) {
await page.goto('/admin-vue/')
await expect(page.locator('h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
}
test('test_task_018_shell_accessibility_normal_primary_path', async ({ page }) => {
@@ -12,19 +15,16 @@ test('test_task_018_shell_accessibility_normal_primary_path', async ({ page }) =
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')
const skip = page.locator('.skip-link')
await expect(skip).toBeVisible()
await expect(skip).toHaveAttribute('href', '#admin-content')
})
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')
await page.reload()
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.getByRole('navigation', { name: '侧边栏菜单' })).toBeVisible()
})
test('test_task_018_shell_accessibility_boundary_empty_input', async ({ page }) => {
@@ -35,11 +35,12 @@ test('test_task_018_shell_accessibility_boundary_empty_input', async ({ page })
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()
// 键盘可达:Tab 到跳转链接,回车跳到主内容(hash 定位)
await page.locator('.skip-link').focus()
await expect(page.locator('.skip-link')).toBeFocused()
await page.keyboard.press('Enter')
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await expect(page).toHaveURL(/#admin-content/)
await expect(page.locator('#admin-content')).toBeVisible()
})
test('test_task_018_shell_accessibility_boundary_limit_or_missing_field', async ({ page }) => {
@@ -50,16 +51,16 @@ test('test_task_018_shell_accessibility_boundary_limit_or_missing_field', async
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)
// 导航后无可见错误遮罩/弹层残留
await expect(page.locator('.el-overlay:visible')).toHaveCount(0)
await expect(page.locator('.el-alert--error')).toHaveCount(0)
})
test('test_task_018_shell_accessibility_dependency_failure_returns_actionable_message', async ({ page }) => {
await openUsers(page)
// 标题层级:顶栏 h1(页面标题) + 页面 h2;键盘焦点样式已定义
// 标题层级:顶栏唯一 h1(页面标题);页面面板标题用 h3 递进
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('h1')).toHaveCount(1)
const hasFocusStyle = await page.evaluate(() => {
const rules: string[] = []
for (const sheet of document.styleSheets) {
@@ -71,7 +72,7 @@ test('test_task_018_shell_accessibility_dependency_failure_returns_actionable_me
// 跨域样式表忽略
}
}
return rules.some((t) => t.includes('sidebar-collapse'))
return rules.length > 0
})
expect(hasFocusStyle).toBe(true)
})
@@ -6,35 +6,35 @@ async function gotoRoute(page: Page, path: string) {
test('test_task_019_first_batch_mount_normal_primary_path', async ({ page }) => {
await gotoRoute(page, '/admin-vue/account/users')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
})
test('test_task_019_first_batch_mount_normal_variant_input', async ({ page }) => {
await gotoRoute(page, '/admin-vue/account/menus')
await expect(page.locator('main h2')).toHaveText('菜单管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('菜单管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('菜单管理')
})
test('test_task_019_first_batch_mount_normal_repeated_operation_is_idempotent', async ({ page }) => {
await gotoRoute(page, '/admin-vue/account/groups')
await expect(page.locator('main h2')).toHaveText('数据权限分组')
await expect(page.locator('.admin-topbar h1')).toHaveText('数据权限分组')
await gotoRoute(page, '/admin-vue/account/users')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await gotoRoute(page, '/admin-vue/account/groups')
await expect(page.locator('main h2')).toHaveText('数据权限分组')
await expect(page.locator('.admin-topbar h1')).toHaveText('数据权限分组')
})
test('test_task_019_first_batch_mount_boundary_empty_input', async ({ page }) => {
// 根路由跳转到首个可见页面(用户管理)。
await gotoRoute(page, '/admin-vue/')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page).toHaveURL(/\/account\/users$/)
})
test('test_task_019_first_batch_mount_boundary_single_item', async ({ page }) => {
await gotoRoute(page, '/admin-vue/account/menus')
await expect(page.locator('main h2')).toHaveText('菜单管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('菜单管理')
const active = page.locator('.el-menu-item.is-active')
await expect(active).toHaveText('菜单管理')
})
@@ -42,11 +42,11 @@ test('test_task_019_first_batch_mount_boundary_single_item', async ({ page }) =>
test('test_task_019_first_batch_mount_boundary_limit_or_missing_field', async ({ page }) => {
// 三个页面均可从侧边栏导航切换(挂载于同一壳层实例)。
await gotoRoute(page, '/admin-vue/account/users')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await page.getByText('菜单管理', { exact: true }).first().click()
await expect(page.locator('main h2')).toHaveText('菜单管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('菜单管理')
await page.getByText('数据权限分组', { exact: true }).first().click()
await expect(page.locator('main h2')).toHaveText('数据权限分组')
await expect(page.locator('.admin-topbar h1')).toHaveText('数据权限分组')
})
test('test_task_019_first_batch_mount_invalid_input_rejected', async ({ page }) => {
@@ -2,7 +2,7 @@ import { expect, test, type Page } from '@playwright/test'
async function openAdmin(page: Page) {
await page.goto('/admin-vue/')
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
}
test('test_task_020_shell_browser_smoke_normal_primary_path', async ({ page }) => {
@@ -15,16 +15,16 @@ test('test_task_020_shell_browser_smoke_normal_primary_path', async ({ page }) =
test('test_task_020_shell_browser_smoke_normal_variant_input', async ({ page }) => {
await openAdmin(page)
await page.locator('.sidebar-collapse').click()
await expect(page.locator('.admin-shell')).toHaveClass(/is-collapsed/)
await page.locator('.sidebar-collapse').click()
await expect(page.locator('.admin-shell')).not.toHaveClass(/is-collapsed/)
// 侧边栏菜单导航到「数据权限分组」,标题与面包屑跟随(对齐现状:无收起按钮)。
await page.getByRole('menuitem', { name: '数据权限分组' }).click()
await expect(page.locator('.admin-topbar h1')).toHaveText('数据权限分组')
await expect(page.locator('.admin-breadcrumb')).toBeVisible()
})
test('test_task_020_shell_browser_smoke_normal_repeated_operation_is_idempotent', async ({ page }) => {
await openAdmin(page)
await page.reload()
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
await expect(page.locator('.global-error-stack')).toHaveCount(0)
})
@@ -42,7 +42,7 @@ test('test_task_020_shell_browser_smoke_boundary_single_item', async ({ page })
await page.locator('.el-message-box').getByRole('button', { name: '取消' }).click()
await expect(page.locator('.el-message-box')).toHaveCount(0)
await expect(page).toHaveURL(/\/admin-vue\//)
await expect(page.locator('main h2')).toHaveText('用户管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('用户管理')
})
test('test_task_020_shell_browser_smoke_boundary_limit_or_missing_field', async ({ page }) => {
@@ -58,9 +58,9 @@ test('test_task_020_shell_browser_smoke_invalid_input_rejected', async ({ page }
page.on('pageerror', (error) => errors.push(error.message))
await openAdmin(page)
await page.goto('/admin-vue/account/menus')
await expect(page.locator('main h2')).toHaveText('菜单管理')
await expect(page.locator('.admin-topbar h1')).toHaveText('菜单管理')
await page.goto('/admin-vue/account/groups')
await expect(page.locator('main h2')).toHaveText('数据权限分组')
await expect(page.locator('.admin-topbar h1')).toHaveText('数据权限分组')
expect(errors).toEqual([])
})