import { TIMEOUTS } from '../../utils/timeouts'; import { test, expect } from '../../utils/test-setup'; /** * 跨端数据同步 E2E 测试 * * 测试目标:验证后台创建订单后,企业小程序能否正确显示该订单 * * 测试流程: * 1. 后台操作:登录 → 导航到订单管理 → 创建测试订单 → 验证创建成功 * 2. 小程序验证:登录 → 导航到订单列表 → 验证订单存在 → 查看详情 * * 测试要点: * - 使用两个独立的 browser context(后台和小程序) * - 记录数据同步时间 * - 使用 data-testid 选择器 * - 遵循项目测试规范 */ test.describe('跨端数据同步测试 - 后台创建订单到企业小程序', () => { let orderName: string; test.describe.serial('后台创建订单', () => { test('应该成功登录后台并创建订单', async ({ page: adminPage }) => { // 记录开始时间 const startTime = Date.now(); // 1. 后台登录 await adminPage.goto('http://localhost:8080/admin/login'); await adminPage.getByPlaceholder('请输入用户名').fill('admin'); await adminPage.getByPlaceholder('请输入密码').fill('admin123'); await adminPage.getByRole('button', { name: '登录' }).click(); await adminPage.waitForURL('**/admin/dashboard', { timeout: TIMEOUTS.PAGE_LOAD }); console.debug('[后台] 登录成功'); // 2. 导航到订单管理页面 await adminPage.goto('http://localhost:8080/admin/orders'); await adminPage.waitForSelector('table tbody tr', { state: 'visible', timeout: TIMEOUTS.PAGE_LOAD }); console.debug('[后台] 导航到订单管理页面'); // 3. 点击创建订单按钮 await adminPage.getByTestId('create-order-button').click(); await adminPage.waitForSelector('[role="dialog"]', { state: 'visible', timeout: TIMEOUTS.DIALOG }); console.debug('[后台] 打开创建订单对话框'); // 4. 填写订单表单 const timestamp = Date.now(); orderName = `跨端同步测试_${timestamp}`; // 填写订单名称 await adminPage.getByLabel('订单名称').fill(orderName); console.debug(`[后台] 订单名称: ${orderName}`); // 选择平台(选择第一个可用平台) await adminPage.getByTestId('platform-selector-create').click(); await adminPage.waitForTimeout(TIMEOUTS.SHORT); const firstPlatformOption = adminPage.locator('[role="option"]').first(); const platformName = await firstPlatformOption.textContent(); await firstPlatformOption.click(); console.debug(`[后台] 选择平台: ${platformName}`); // 选择公司(选择与测试用户关联的公司:测试公司_1768346782396) await adminPage.getByTestId('company-selector-create').click(); await adminPage.waitForTimeout(TIMEOUTS.SHORT); // 选择测试公司_1768346782396(与 13800001111 用户关联的公司) const companyOption = adminPage.getByRole('option', { name: '测试公司_1768346782396' }); await companyOption.click(); console.debug('[后台] 选择公司: 测试公司_1768346782396'); // 5. 选择残疾人 // 首先检查是否已经有残疾人被选择(可能在之前的测试中) // 通过检查是否存在显示残疾人详情的区域来判断 const hasExistingPerson = await adminPage.getByText('残疾证号:', { exact: false }).count() > 0; if (hasExistingPerson) { console.debug('[后台] 订单中已有残疾人,跳过选择步骤'); } else { // 需要选择残疾人,点击"选择残疾人"按钮 await adminPage.getByTestId('select-persons-button').click(); console.debug('[后台] 点击选择残疾人按钮'); // 等待残疾人选择对话框出现 await adminPage.waitForSelector('text=选择残疾人', { state: 'visible', timeout: TIMEOUTS.DIALOG }); console.debug('[后台] 选择残疾人对话框已打开'); // 等待残疾人列表加载 await adminPage.waitForSelector('table tbody tr', { state: 'visible', timeout: TIMEOUTS.TABLE_LOAD }); // 选择第一个残疾人 - 使用复选框选择器 const firstCheckbox = adminPage.locator('[data-testid^="person-checkbox-"]').first(); await firstCheckbox.click(); console.debug('[后台] 已勾选第一个残疾人'); // 等待确认按钮变为可用状态 await adminPage.waitForSelector('[data-testid="confirm-batch-button"]:not([disabled])', { timeout: TIMEOUTS.SHORT }); // 点击确认选择按钮 await adminPage.getByTestId('confirm-batch-button').click(); await adminPage.waitForTimeout(TIMEOUTS.MEDIUM); console.debug('[后台] 已确认选择残疾人'); } // 等待 UI 稳定 await adminPage.waitForTimeout(1000); // 6. 提交表单 await adminPage.getByTestId('order-create-submit-button').click(); await adminPage.waitForLoadState('domcontentloaded'); await adminPage.waitForTimeout(TIMEOUTS.LONG); console.debug('[后台] 提交订单表单'); // 7. 验证创建成功的 Toast const successToast = adminPage.locator('[data-sonner-toast][data-type="success"]'); const toastCount = await successToast.count(); expect(toastCount).toBeGreaterThan(0); console.debug('[后台] 订单创建成功'); // 8. 验证订单出现在列表中 const orderExists = adminPage.locator('table tbody tr').filter({ hasText: orderName }).count() > 0; expect(orderExists).toBe(true); console.debug(`[后台] 订单 "${orderName}" 出现在列表中`); // 9. 记录创建完成时间 const endTime = Date.now(); const syncTime = endTime - startTime; console.debug(`[后台] 订单创建完成,耗时: ${syncTime}ms`); // 保存订单名称到环境变量,供后续测试使用 process.env.__TEST_ORDER_NAME__ = orderName; }); }); test.describe.serial('小程序验证订单同步', () => { test.use({ storageState: undefined }); // 确保使用新的浏览器上下文 test('应该在小程序中显示后台创建的订单', async ({ page: miniPage }) => { // 从环境变量获取订单名称 const testOrderName = process.env.__TEST_ORDER_NAME__; if (!testOrderName) { throw new Error('未找到测试订单名称,请先运行后台创建订单测试'); } console.debug(`[小程序] 查找订单: ${testOrderName}`); // 等待一段时间,确保数据同步完成 await new Promise(resolve => setTimeout(resolve, 3000)); // 1. 小程序登录 await miniPage.goto('http://localhost:8080/mini'); await miniPage.waitForLoadState('networkidle'); // 填写登录表单(使用企业账号) await miniPage.getByTestId('mini-phone-input').getByPlaceholder('请输入手机号').fill('13800001111'); await miniPage.getByRole('textbox', { name: '请输入密码' }).fill('password123'); await miniPage.getByTestId('mini-login-button').click(); console.debug('[小程序] 登录请求已发送'); // 等待登录成功(跳转到 dashboard) await miniPage.waitForURL( url => url.pathname.includes('/dashboard') || url.pathname.includes('/pages/yongren/dashboard'), { timeout: TIMEOUTS.PAGE_LOAD } ); console.debug('[小程序] 登录成功'); // 2. 导航到订单列表页面 await miniPage.getByText('订单', { exact: true }).click(); await miniPage.waitForLoadState('domcontentloaded'); console.debug('[小程序] 导航到订单列表页面'); // 3. 等待订单列表加载 await miniPage.waitForTimeout(TIMEOUTS.LONG); // 4. 验证订单出现在小程序列表中 // 使用多种方法验证订单存在 const orderExistsByLocator = await miniPage.locator('text=' + testOrderName).count() > 0; const orderExistsByGetByText = await miniPage.getByText(testOrderName).count() > 0; const orderExists = orderExistsByLocator || orderExistsByGetByText; expect(orderExists).toBe(true); console.debug(`[小程序] 订单 "${testOrderName}" 已同步到小程序`); // 5. 点击查看详情 const detailButton = miniPage.getByText('查看详情').first(); await detailButton.click(); await miniPage.waitForURL(/\/detail/, { timeout: TIMEOUTS.PAGE_LOAD }); console.debug('[小程序] 打开订单详情'); // 6. 验证订单详情信息 // 验证订单名称显示 const orderNameElement = miniPage.getByText(testOrderName); await expect(orderNameElement).toBeVisible(); console.debug('[小程序] 订单详情显示正确'); // 7. 记录数据同步完成时间 const syncEndTime = Date.now(); console.debug(`[小程序] 数据同步验证完成,时间戳: ${syncEndTime}`); // 清理环境变量 delete process.env.__TEST_ORDER_NAME__; }); }); });