52b55df7b2
判死线(治 28131 型「主线程卡死、心跳线程照发」): - 判据改看 biz_task_scope_state.last_chunk_at(HTTP 心跳不刷新它);从未上报跳过不判 - 中央线覆盖 DELETE_BRAND/PRODUCT_RISK_RESOLVE/PRICE_TRACK/SHOP_MATCH/PATROL_DELETE/QUERY_ASIN/WITHDRAW - 自带线接入 COLLECT_DATA/SIMILAR_ASIN/APPEARANCE_PATENT/SHOP_DATA_CRAWL/PUBLISH/BRAND - 客户端心跳带处理位置 progressText,判死文案含最后位置;no-result-upload-timeout-minutes 默认 180(0 关闭) 同期带上另一工作流的待发改动:跟价换 IP 重试、品牌检测重试上限与 LLM 并发下调、 教程包后台管理页与 V126 迁移、admin-vue 教程记录页。
80 lines
3.7 KiB
TypeScript
80 lines
3.7 KiB
TypeScript
import { expect, test, type Page } from '@playwright/test'
|
|
|
|
// 教程管理页验收(module 记录与版本):列表新增「版本号」列 + 上传时间列,
|
|
// 默认按上传时间降序;版本号/上传时间表头可点击切换升降序;空版本历史行沉底。
|
|
// 依赖 scripts/mock-admin-server.mjs 的教程包夹具(4 条,其中 1 条无版本号、1 条 09-01 历史行)。
|
|
|
|
async function openTutorial(page: Page) {
|
|
await page.goto('/admin-vue/records/tutorial')
|
|
await expect(page.locator('.admin-topbar h1')).toHaveText('教程管理')
|
|
await expect(page.locator('.panel-box tbody tr').first()).toBeVisible()
|
|
}
|
|
|
|
const versionTexts = (page: Page) =>
|
|
page.locator('.panel-box tbody tr td:nth-child(3)').allTextContents()
|
|
|
|
const fileTexts = (page: Page) =>
|
|
page.locator('.panel-box tbody tr td:nth-child(2) .file-name').allTextContents()
|
|
|
|
test('test_tutorial_list_default_desc_by_upload_time', async ({ page }) => {
|
|
await openTutorial(page)
|
|
|
|
// 表头:版本号、上传时间(均带排序标记)
|
|
await expect(page.locator('.sort-version')).toHaveText(/版本号/)
|
|
await expect(page.locator('.sort-time')).toHaveText(/上传时间/)
|
|
// 默认排序状态:上传时间降序(▼),版本号未激活(▲▼)
|
|
await expect(page.locator('.sort-time .sort-mark')).toHaveText('▼')
|
|
await expect(page.locator('.sort-version .sort-mark')).toHaveText('▲▼')
|
|
|
|
// 默认按上传时间降序:09-14 → 09-12 → 09-10 → 09-01;空版本行沉底
|
|
expect(await versionTexts(page)).toEqual(['v3.10.0', 'v3.2.0', 'v3.1.0', '—'])
|
|
expect(await fileTexts(page)).toEqual([
|
|
'数富AI-教学客户端-v4.zip',
|
|
'数富AI-教学客户端-v3.zip',
|
|
'数富AI-教学客户端-v2.zip',
|
|
'数富AI-教学客户端.zip',
|
|
])
|
|
// 当前生效 = 最新上传(夹具里 09-14 那条),不随列表排序变化
|
|
await expect(page.locator('.tag-active')).toHaveCount(1)
|
|
await expect(page.locator('.tag-active').locator('xpath=..')).toHaveText(/数富AI-教学客户端-v4\.zip/)
|
|
})
|
|
|
|
test('test_tutorial_sort_toggle_by_version_and_time', async ({ page }) => {
|
|
await openTutorial(page)
|
|
|
|
// 点「版本号」:首次为降序(v3.10.0 按自然序大于 v3.2.0),空版本行仍在末尾
|
|
await page.locator('.sort-version').click()
|
|
await expect(page.locator('.sort-version .sort-mark')).toHaveText('▼')
|
|
expect(await versionTexts(page)).toEqual(['v3.10.0', 'v3.2.0', 'v3.1.0', '—'])
|
|
|
|
// 再点一次切升序
|
|
await page.locator('.sort-version').click()
|
|
await expect(page.locator('.sort-version .sort-mark')).toHaveText('▲')
|
|
expect(await versionTexts(page)).toEqual(['v3.1.0', 'v3.2.0', 'v3.10.0', '—'])
|
|
|
|
// 点回「上传时间」:切换字段时回到降序默认
|
|
await page.locator('.sort-time').click()
|
|
await expect(page.locator('.sort-time .sort-mark')).toHaveText('▼')
|
|
await expect(page.locator('.sort-version .sort-mark')).toHaveText('▲▼')
|
|
expect(await fileTexts(page)).toEqual([
|
|
'数富AI-教学客户端-v4.zip',
|
|
'数富AI-教学客户端-v3.zip',
|
|
'数富AI-教学客户端-v2.zip',
|
|
'数富AI-教学客户端.zip',
|
|
])
|
|
})
|
|
|
|
test('test_tutorial_upload_dialog_has_version_field', async ({ page }) => {
|
|
await openTutorial(page)
|
|
|
|
await page.getByRole('button', { name: '上传教程包' }).click()
|
|
const dialog = page.locator('.el-dialog')
|
|
await expect(dialog).toBeVisible()
|
|
await expect(dialog.locator('.el-form-item').first()).toContainText('版本号')
|
|
await expect(dialog.locator('input').first()).toHaveAttribute('maxlength', '64')
|
|
|
|
// 不选文件直接提交:提示仍以 zip 为必填(版本号可空)
|
|
await dialog.getByRole('button', { name: '上传教程包' }).click()
|
|
await expect(dialog.locator('.el-alert')).toContainText('请选择 zip 压缩包')
|
|
})
|