import { expect, test } from '@playwright/test' const sybProductRoute = [{ path: '/goauto-order-workbench', component: 'Layout', menuName: 'GoAutoOrderWorkbench', title: '订单工作台', visible: '0', children: [{ path: '/syb-products', component: '/goauto/syb-products/index', menuName: 'GoAutoSybProducts', title: 'SYB 商品', visible: '0' }] }] test('SYB 商品首次网络失败时静默重试一次并恢复列表', async({ page, context }) => { await context.addCookies([{ name: 'Admin-Token', value: 'prototype-test-token', domain: 'localhost', path: '/' }]) let listCalls = 0 await page.route('**/api/**', async route => { const url = new URL(route.request().url()) if (url.pathname.startsWith('/src/api/')) return route.continue() if (url.pathname.endsWith('/api/v1/getinfo')) return route.fulfill({ json: { code: 200, data: { roles: ['admin'], name: '管理员', avatar: '', introduction: '', permissions: [] }}}) if (url.pathname.endsWith('/api/v1/menurole')) return route.fulfill({ json: { code: 200, data: sybProductRoute }}) if (url.pathname.endsWith('/api/admin/v1/syb-products')) { listCalls += 1 if (listCalls === 1) return route.abort('connectionrefused') return route.fulfill({ json: { code: 200, data: { items: [{ id: 72, orderCode: 'RETRY-72', shopeeItemId: '10072', productTitle: '网络恢复后的商品', quantity: 1, parseStatus: 'success' }], total: 1, page: 1, pageSize: 20 }}}) } if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/batch-preview')) return route.fulfill({ json: { code: 200, data: { items: [{ sybProductId: 72, eligible: false, reason: '测试数据未关联商品', processStage: 'manual_action', processStageLabel: '待人工处理', processStageReason: '测试数据未关联商品' }], eligibleCount: 0, skippedCount: 1 }}}) return route.fulfill({ json: { code: 200, data: [] }}) }) await page.goto('/#/syb-products') await expect(page.getByText('网络恢复后的商品')).toBeVisible() expect(listCalls).toBe(2) await expect(page.getByText('服务器连接异常,请检查服务器!')).toHaveCount(0) }) test('SYB 商品业务错误不重试', async({ page, context }) => { await context.addCookies([{ name: 'Admin-Token', value: 'prototype-test-token', domain: 'localhost', path: '/' }]) let listCalls = 0 await page.route('**/api/**', async route => { const url = new URL(route.request().url()) if (url.pathname.startsWith('/src/api/')) return route.continue() if (url.pathname.endsWith('/api/v1/getinfo')) return route.fulfill({ json: { code: 200, data: { roles: ['admin'], name: '管理员', avatar: '', introduction: '', permissions: [] }}}) if (url.pathname.endsWith('/api/v1/menurole')) return route.fulfill({ json: { code: 200, data: sybProductRoute }}) if (url.pathname.endsWith('/api/admin/v1/syb-products')) { listCalls += 1 return route.fulfill({ json: { code: 500, msg: '测试业务错误' }}) } return route.fulfill({ json: { code: 200, data: [] }}) }) await page.goto('/#/syb-products') await expect(page.getByText('测试业务错误')).toBeVisible() expect(listCalls).toBe(1) }) test('SYB 列表先展示,采购准备在独立请求完成后更新', async({ page, context }) => { await context.addCookies([{ name: 'Admin-Token', value: 'prototype-test-token', domain: 'localhost', path: '/' }]) await page.route('**/api/**', async route => { const url = new URL(route.request().url()) if (url.pathname.startsWith('/src/api/')) return route.continue() if (url.pathname.endsWith('/api/v1/getinfo')) return route.fulfill({ json: { code: 200, data: { roles: ['admin'], name: '管理员', avatar: '', introduction: '', permissions: [] }}}) if (url.pathname.endsWith('/api/v1/menurole')) return route.fulfill({ json: { code: 200, data: sybProductRoute }}) if (url.pathname.endsWith('/api/admin/v1/syb-products')) return route.fulfill({ json: { code: 200, data: { items: [{ id: 73, orderCode: 'FAST-73', shopeeItemId: '10073', productTitle: '先显示的商品', quantity: 1, parseStatus: 'success' }], total: 1, page: 1, pageSize: 20 }}}) if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/batch-preview')) { await new Promise(resolve => setTimeout(resolve, 3000)) return route.fulfill({ json: { code: 200, data: { items: [{ sybProductId: 73, pddProductId: 173, eligible: true, minUnitPriceCent: 100, maxUnitPriceCent: 300, processStage: 'purchase_ready', processStageLabel: '可创建采购', processStageReason: '当前条件可以创建采购任务' }], eligibleCount: 1, skippedCount: 0 }}}) } return route.fulfill({ json: { code: 200, data: [] }}) }) await page.goto('/#/syb-products') await expect(page.getByText('先显示的商品')).toBeVisible({ timeout: 2000 }) await expect(page.getByText('正在检查')).toBeVisible() await expect(page.getByText('可以创建')).toBeVisible({ timeout: 5000 }) }) test('采购准备失败不清空 SYB 列表且不弹全局错误', async({ page, context }) => { await context.addCookies([{ name: 'Admin-Token', value: 'prototype-test-token', domain: 'localhost', path: '/' }]) await page.route('**/api/**', async route => { const url = new URL(route.request().url()) if (url.pathname.startsWith('/src/api/')) return route.continue() if (url.pathname.endsWith('/api/v1/getinfo')) return route.fulfill({ json: { code: 200, data: { roles: ['admin'], name: '管理员', avatar: '', introduction: '', permissions: [] }}}) if (url.pathname.endsWith('/api/admin/v1/syb-products')) return route.fulfill({ json: { code: 200, data: { items: [{ id: 74, orderCode: 'FAIL-74', shopeeItemId: '10074', productTitle: '仍然可见的商品', quantity: 1, parseStatus: 'success' }], total: 1, page: 1, pageSize: 20 }}}) if (url.pathname.endsWith('/api/v1/menurole')) return route.fulfill({ json: { code: 200, data: sybProductRoute }}) if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/batch-preview')) return route.fulfill({ status: 500, json: { code: 500, msg: '预检测试失败' }}) return route.fulfill({ json: { code: 200, data: [] }}) }) await page.goto('/#/syb-products') await expect(page.getByText('仍然可见的商品')).toBeVisible() await expect(page.getByText('采购准备检查失败,请点击刷新重试')).toBeVisible() await expect(page.getByText('预检测试失败')).toHaveCount(0) }) test('新的查询结果不会被旧采购预检覆盖', async({ page, context }) => { await context.addCookies([{ name: 'Admin-Token', value: 'prototype-test-token', domain: 'localhost', path: '/' }]) await page.route('**/api/**', async route => { const url = new URL(route.request().url()) if (url.pathname.startsWith('/src/api/')) return route.continue() if (url.pathname.endsWith('/api/v1/getinfo')) return route.fulfill({ json: { code: 200, data: { roles: ['admin'], name: '管理员', avatar: '', introduction: '', permissions: [] }}}) if (url.pathname.endsWith('/api/v1/menurole')) return route.fulfill({ json: { code: 200, data: sybProductRoute }}) if (url.pathname.endsWith('/api/admin/v1/syb-products')) { const searched = url.searchParams.get('orderCodes') === 'NEW-76' const item = searched ? { id: 76, orderCode: 'NEW-76', shopeeItemId: '10076', productTitle: '新商品', quantity: 1, parseStatus: 'success' } : { id: 75, orderCode: 'OLD-75', shopeeItemId: '10075', productTitle: '旧商品', quantity: 1, parseStatus: 'success' } return route.fulfill({ json: { code: 200, data: { items: [item], total: 1, page: 1, pageSize: 20 }}}) } if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/batch-preview')) { const [id] = route.request().postDataJSON().sybProductIds if (id === 75) { await new Promise(resolve => setTimeout(resolve, 1200)) return route.fulfill({ json: { code: 200, data: { items: [{ sybProductId: 75, pddProductId: 175, eligible: true, processStage: 'purchase_ready', processStageLabel: '可创建采购', processStageReason: '当前条件可以创建采购任务' }], eligibleCount: 1, skippedCount: 0 }}}) } return route.fulfill({ json: { code: 200, data: { items: [{ sybProductId: 76, eligible: false, reason: '新商品暂不可创建', processStage: 'manual_action', processStageLabel: '待人工处理', processStageReason: '新商品暂不可创建' }], eligibleCount: 0, skippedCount: 1 }}}) } return route.fulfill({ json: { code: 200, data: [] }}) }) await page.goto('/#/syb-products') await expect(page.getByText('旧商品')).toBeVisible() await page.getByPlaceholder('每行一个订单号,最多 100 个').fill('NEW-76') await page.getByRole('button', { name: '查询' }).click() await expect(page.getByText('新商品', { exact: true })).toBeVisible() await expect(page.getByText('新商品暂不可创建')).toBeVisible() await page.waitForTimeout(1500) await expect(page.getByText('新商品暂不可创建')).toBeVisible() await expect(page.getByText('可以创建', { exact: true })).toHaveCount(0) })